-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from EPA-WG/develop
0.0.18
- Loading branch information
Showing
19 changed files
with
2,332 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"html.customData": [ | ||
"./ide/customData-dce.json", | ||
"./ide/customData-xsl.json" | ||
], | ||
"terminal.integrated.profiles.windows": { | ||
|
||
"PowerShell": { | ||
"source": "PowerShell", | ||
"icon": "terminal-powershell" | ||
}, | ||
"Command Prompt": { | ||
"path": [ | ||
"${env:windir}\\Sysnative\\cmd.exe", | ||
"${env:windir}\\System32\\cmd.exe" | ||
], | ||
"args": [], | ||
"icon": "terminal-cmd" | ||
}, | ||
"Git Bash": { | ||
"source": "Git Bash" | ||
} | ||
}, | ||
"terminal.integrated.defaultProfile.windows": "Git Bash" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,8 @@ This project is a POC( Proof of Concept ) targeting to become a base for native | |
</details> | ||
|
||
# use | ||
|
||
Use the [bootstrap project](https://github.com/EPA-WG/custom-element-bootstrap) with all pre-configured or | ||
## install | ||
use via CDN | ||
```html | ||
|
@@ -56,17 +58,21 @@ npm i -P @epa-wg/custom-element | |
yarn add @epa-wg/custom-element | ||
``` | ||
|
||
## [enable IDE support](ide/IDE.md) | ||
|
||
|
||
|
||
## [Live demo 🔗][demo-url] | ||
```html | ||
<custom-element tag="pokemon-tile" hidden> | ||
<h3>{title}</h3> <!-- title is an attribute in instance | ||
mapped into /*/attributes/title --> | ||
<xsl:if test="//smile"> <!-- data-smile DCE instance attribute, | ||
<if test="//smile"> <!-- data-smile DCE instance attribute, | ||
mapped into /*/dataset/smile | ||
used in condition --> | ||
<!-- data-smile DCE instance attribute, used as HTML --> | ||
<div>Smile as: {//smile} </div> | ||
</xsl:if> | ||
</if> | ||
<!-- image would not be visible in sandbox, see live demo --> | ||
<img src="https://unpkg.com/[email protected]/sprites/pokemon/other/dream-world/{pokemon-id}.svg" | ||
alt="{title} image"/> | ||
|
@@ -205,12 +211,12 @@ In same way as in DCE itself: | |
</dce-2> | ||
``` | ||
## Attributes | ||
To be served by IDE and to track the attributes changes, they have to be declared via `xsl:param` syntax: | ||
To be served by IDE and to track the attributes changes, they have to be declared via `attribute`: | ||
```html | ||
<custom-element tag="dce-with-attrs" hidden> | ||
<xsl:param name="p1" >default_P1</xsl:param> | ||
<xsl:param name="p2" select="'always_p2'" ></xsl:param> | ||
<xsl:param name="p3" select="//p3 ?? 'def_P3' " ></xsl:param> | ||
<attribute name="p1" >default_P1 </attribute> | ||
<attribute name="p2" select="'always_p2'" ></attribute> | ||
<attribute name="p3" select="//p3 ?? 'def_P3' " ></attribute> | ||
p1: {$p1} <br/> p2: {$p2} <br/> p3: {$p3} | ||
</custom-element> | ||
<dce-with-attrs p1="123" p3="qwe"></dce-with-attrs> | ||
|
@@ -229,7 +235,7 @@ i.e. slot `xxx` is matching `<i slot="xxx">...</i>` in payload. | |
<custom-element tag="with-description" > | ||
<slot name="description">description is not available</slot> | ||
<!-- same as | ||
<xsl:value-of select='/*/payload/*[@slot="description"]'/> | ||
<value-of select='/*/payload/*[@slot="description"]'/> | ||
--> | ||
</custom-element> | ||
<with-description> | ||
|
@@ -238,12 +244,12 @@ i.e. slot `xxx` is matching `<i slot="xxx">...</i>` in payload. | |
``` | ||
|
||
## loops, variables | ||
Loop implemented via [xsl:for-each](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each) | ||
Loop implemented via [for-each](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each) | ||
|
||
[Variables in XSLT](https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/variable) | ||
|
||
## [XPath](https://developer.mozilla.org/en-US/docs/Web/XSLT/Transforming_XML_with_XSLT/The_Netscape_XSLT_XPath_Reference) | ||
is available in `{}` in attributes, in `xsl:for-each`, `xsl:if`, `xsl:value-of`, and other XSL tags. | ||
is available in `{}` in attributes, in `for-each`, `if`, `value-of`, and other XSL tags. | ||
|
||
XPath is a selector language to navigate over custom element instance data, attributes, and payload. | ||
|
||
|
@@ -262,12 +268,12 @@ in template. In such cases the `xhtml:` prefix in front of troubled tag would so | |
<local-storage key="basket" slice="basket" live type="json"></local-storage> | ||
<xhtml:table xmlns:xhtml="http://www.w3.org/1999/xhtml" > | ||
<xhtml:tbody> | ||
<xsl:for-each select="//basket/@*"> | ||
<for-each select="//basket/@*"> | ||
<xhtml:tr> | ||
<xhtml:th> {name()} </xhtml:th> | ||
<xhtml:td> {.} </xhtml:td> | ||
</xhtml:tr> | ||
</xsl:for-each> | ||
</for-each> | ||
</xhtml:tbody> | ||
<xhtml:tfoot> | ||
<xhtml:tr> | ||
|
@@ -302,7 +308,7 @@ run transformation under debugger. | |
* try to add as attribute you could observe and put the value of node name or text to identify the current location in data | ||
within template | ||
```xml | ||
<b title="{name(*)} : {text()}">xml tag name: <xsl:value-of select='name()'/></b> | ||
<b title="{name(*)} : {text()}">xml tag name: <value-of select='name()'/></b> | ||
``` | ||
|
||
[git-url]: https://github.com/EPA-WG/custom-element | ||
|
@@ -317,9 +323,9 @@ within template | |
[github-image]: https://cdnjs.cloudflare.com/ajax/libs/octicons/8.5.0/svg/mark-github.svg | ||
[npm-image]: https://img.shields.io/npm/v/@epa-wg/custom-element.svg | ||
[npm-url]: https://npmjs.org/package/@epa-wg/custom-element | ||
[coverage-image]: https://unpkg.com/@epa-wg/[email protected].17/coverage/coverage.svg | ||
[coverage-url]: https://unpkg.com/@epa-wg/[email protected].17/coverage/lcov-report/index.html | ||
[storybook-url]: https://unpkg.com/@epa-wg/[email protected].17/storybook-static/index.html?path=/story/welcome--introduction | ||
[coverage-image]: https://unpkg.com/@epa-wg/[email protected].18/coverage/coverage.svg | ||
[coverage-url]: https://unpkg.com/@epa-wg/[email protected].18/coverage/lcov-report/index.html | ||
[storybook-url]: https://unpkg.com/@epa-wg/[email protected].18/storybook-static/index.html?path=/story/welcome--introduction | ||
[sandbox-url]: https://stackblitz.com/github/EPA-WG/custom-element?file=index.html | ||
[webcomponents-url]: https://www.webcomponents.org/element/@epa-wg/custom-element | ||
[webcomponents-img]: https://img.shields.io/badge/webcomponents.org-published-blue.svg | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/** | ||
* node xslDtd2Ide.cjs | ||
* would get xsl 1.0 schema and populate IntelliJ and VS Code IDE custom elements definitions | ||
* | ||
* This is one time use script as XSLT 1.0 schema is not changing. | ||
* DTD parsing here is not generic and cobers only particula XSLT 1.0 schema. | ||
*/ | ||
import { readFileSync, writeFileSync } from 'node:fs'; | ||
|
||
|
||
const dtdText = await fetch( 'https://www.w3.org/1999/11/xslt10.dtd' ) | ||
.then( ( response ) => response.text() ) | ||
.then( ( body ) => | ||
{ | ||
return body; | ||
} ); | ||
const matches = dtdText.match( /<([^>]*)>/g ); | ||
|
||
const chopOff = ( s, begin = 1, end = 1 ) => s.substring( begin, s.length - end ); | ||
const trim = s => s?.trim ? s.trim() : s; | ||
|
||
let lastComment = '' | ||
const dtdObj = { ENTITY: {}, ELEMENT: {} } | ||
for( const match of matches ){ | ||
if( match.startsWith( '<!--' ) ) { | ||
lastComment = match; | ||
continue; | ||
} | ||
const body = chopOff( match, 2 ); | ||
const arr = body.split( /\s/ ); | ||
const name = arr[ 1 ].trim(); | ||
const resolveRef = s => s ? ( s.startsWith ? ( s.startsWith( '%' ) ? dtdObj.ENTITY[ chopOff( s, 1, 0 ).replace( ';', | ||
'' ) ] : s ) : s ) : s; | ||
const attrObj = a => | ||
{ | ||
if( !a || Array.isArray( a ) || !a.trim ) | ||
return a; | ||
const as = a.trim(); | ||
if( 'CDATA,#PCDATA,NMTOKEN,NMTOKENS,'.includes( as + ',' ) ) | ||
return as; | ||
const ar = as.split( ';' ) | ||
const aa = ar[ 0 ].split( ' ' ); | ||
// if( aa[0].includes('select')){debugger;} | ||
return { name: aa[ 0 ], type: resolveRef( aa[ 1 ] ), defValue: aa[ 1 ], required: (ar[1] || aa[ 2 ])?.trim() } | ||
}; | ||
switch( arr[ 0 ] ){ | ||
case 'ENTITY':{ | ||
let key = arr[ 2 ]; | ||
let val = body.substring( body.indexOf( key ) + key.length ).trim(); | ||
let ss; | ||
if( val.startsWith( '"' ) || val.startsWith( "'" ) ) { | ||
val = chopOff( val ); | ||
if( val.includes( '(#PCDATA' ) ) { | ||
val = val.replace( '(#PCDATA', '' ).replace( ')*', '' ).trim(); | ||
ss = [ '#PCDATA', ...val.split( '\n' ).map( s => s.trim() ).map( resolveRef ).flat() ]; | ||
} else | ||
ss = val.split( /[\n]/ ).map( s => s.replace( '|', '' ).trim() ).filter( s => s ); | ||
} else | ||
ss = val.split( /[|\n]/ ); | ||
|
||
const v = ss.map( trim ).filter( s => s ).map( resolveRef ).map( attrObj ).flat().filter( s => s ); | ||
dtdObj.ENTITY[ key ] = !v.length ? '' : v.length === 1 ? v[ 0 ] : v; | ||
break; | ||
} | ||
case 'ELEMENT': | ||
dtdObj.ELEMENT[ name ] = { values: arr[ 2 ], attributes: [] }; | ||
break; | ||
case 'ATTLIST':{ | ||
const attrStr = body.split( name )[ 1 ].trim(); | ||
const attrs = attrStr.split( '\n' ).map( s => s.trim() ); | ||
const elementAttrs = dtdObj.ELEMENT[ name ].attributes; | ||
for( let a of attrs ){ | ||
if( a.startsWith( '%' ) ) { | ||
const v = dtdObj.ENTITY[ chopOff( a.split( ';' )[ 0 ], 1, 0 ) ]; | ||
if( !v ) { | ||
debugger; | ||
} | ||
Array.isArray( v ) | ||
? elementAttrs.push( ...v ) | ||
: elementAttrs.push( v ); | ||
} else | ||
elementAttrs.push( attrObj( a ) ); | ||
} | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
||
// replace the tags list in custom-element.js | ||
|
||
const tagsCsv = Object.keys( dtdObj.ELEMENT ).map( s => s.replace( 'xsl:', '' ) ).join( ',' ); | ||
const jsText = readFileSync( '../custom-element.js', 'utf8' ) | ||
const updatedJs = jsText.replace( /^.*export const xslTags = .*$/mg, | ||
`export const xslTags = '${ tagsCsv }'.split(',');` ); | ||
writeFileSync( '../custom-element.js', updatedJs ); | ||
|
||
const vsCode = { | ||
"version": 1.1, tags: Object.keys( dtdObj.ELEMENT ).map( s => ( | ||
{ name : s.replace( 'xsl:', '' ) | ||
, description : `${ s }` | ||
, attributes : dtdObj.ELEMENT[ s ].attributes.map( a => ( | ||
{ name : a.name | ||
, description: `${ JSON.stringify( a ) }` | ||
, type : "string" | ||
, required : a.required === '#REQUIRED' | ||
} ) ) | ||
, references : [ { name: "MDN docs" | ||
, url : `https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/${s.replace( 'xsl:', '' )}` | ||
}] | ||
} ) ) | ||
}; | ||
|
||
writeFileSync( '.././ide/customData-xsl.json', JSON.stringify( vsCode, undefined, 4 ) ); | ||
|
||
const intelliJ = { | ||
"$schema": "http://json.schemastore.org/web-types", | ||
"name": "@epa-wg/custom-element", | ||
"version": "0.0.18", | ||
"js-types-syntax": "typescript", | ||
"description-markup": "markdown", | ||
"contributions": { | ||
"html": { | ||
"elements": [ | ||
...Object.keys( dtdObj.ELEMENT ).map( s => ( | ||
{ name : s.replace( 'xsl:', '' ) | ||
, description : `${ s }` | ||
, attributes : dtdObj.ELEMENT[ s ].attributes.map( a => ( | ||
{ name : a.name | ||
, description : `${ JSON.stringify( a ) }` | ||
, type : "string" | ||
, required : a.required === '#REQUIRED' | ||
} ) ) | ||
, 'doc-url' : `https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/${s.replace( 'xsl:', '' )}` | ||
} ) ), | ||
{ | ||
"name": "for-each", | ||
"description": "The <xsl:for-each> element selects a set of nodes and processes each of them in the same way. It is often used to iterate through a set of nodes or to change the current node. If one or more <xsl:sort> elements appear as the children of this element, sorting occurs before processing. Otherwise, nodes are processed in document order.", | ||
"doc-url": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each", | ||
"attributes": [ | ||
{ | ||
"name": "select", | ||
"description": "Uses an XPath expression to select nodes to be processed.", | ||
"required": true, | ||
"doc-url": "https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/for-each#select", | ||
"value": { | ||
"type": "string" | ||
} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
}; | ||
|
||
|
||
writeFileSync( '.././ide/web-types-xsl.json', JSON.stringify( intelliJ, undefined, 4 ) ); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.