@xaendar/compiler 0.7.31 → 0.7.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler.js +15 -0
- package/package.json +8 -11
- package/dist/xaendar-compiler.es.d.ts +0 -241
- package/dist/xaendar-compiler.es.js +0 -3531
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import{indent as b}from"@xaendar/common";var h=(l=>(l[l.Element=0]="Element",l[l.Text=1]="Text",l[l.Interpolation=2]="Interpolation",l[l.If=3]="If",l[l.Else=4]="Else",l[l.ElseIf=5]="ElseIf",l[l.For=6]="For",l[l.Switch=7]="Switch",l[l.Case=8]="Case",l[l.Import=9]="Import",l))(h||{});var x=class{constructor(t=[],r){this._parent=r;for(let o of t)typeof o=="string"?this._identifiers.set(o,"value"):this._identifiers.set(o[0],o[1])}_parent;_identifiers=new Map;_unresolvableIdentifiers=new Array;addIdentifier(t,r="value"){if(this.hasIdentifier(t))throw new Error(`Identifier "${t}" is already declared in this scope.`);this._identifiers.set(t,r)}addUnresolvableIdentifier(t){if(this.hasIdentifier(t))throw new Error(`Identifier "${t}" is already declared in this scope.`);this._unresolvableIdentifiers.push(t)}removeIdentifier(t){this._identifiers.delete(t)}removeUnresolvabledIdentifier(t){this._unresolvableIdentifiers=this._unresolvableIdentifiers.filter(r=>r!==t)}hasIdentifier(t){return this._identifiers.has(t)||(this._parent?.hasIdentifier(t)??!1)}getIdentifierKind(t){return this._identifiers.get(t)??this._parent?.getIdentifierKind(t)}hasUnresolvableIdentifier(t){return this._unresolvableIdentifiers.includes(t)||(this._parent?.hasUnresolvableIdentifier(t)??!1)}};import{indent as F}from"@xaendar/common";import{forEachChild as ke,isIdentifier as Ne,isPropertyAccessExpression as It,isPropertyAssignment as At}from"typescript";var gt=new Set(["undefined","NaN","Infinity","globalThis","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape","Object","Function","Boolean","Symbol","Error","AggregateError","EvalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError","SuppressedError","InternalError","Number","BigInt","Math","Date","Temporal","String","RegExp","Array","TypedArray","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","BigInt64Array","BigUint64Array","Float16Array","Float32Array","Float64Array","Map","Set","WeakMap","WeakSet","ArrayBuffer","SharedArrayBuffer","DataView","Atomics","JSON","WeakRef","FinalizationRegistry","Iterator","AsyncIterator","Promise","GeneratorFunction","AsyncGeneratorFunction","Generator","AsyncGenerator","AsyncFunction","DisposableStack","AsyncDisposableStack","Reflect","Proxy","Intl","WebAssembly","window","document","navigator","location","history","screen","console","performance","crypto","fetch","alert","confirm","prompt","setTimeout","setInterval","clearTimeout","clearInterval","requestAnimationFrame","cancelAnimationFrame","queueMicrotask","structuredClone","URL","URLSearchParams","FormData","Headers","Request","Response","AbortController","AbortSignal","CustomEvent","Event","EventTarget","MutationObserver","IntersectionObserver","ResizeObserver","PerformanceObserver","Worker","SharedWorker","ServiceWorker","Blob","File","FileReader","ReadableStream","WritableStream","TransformStream","TextEncoder","TextDecoder","ImageData","Canvas","Storage","localStorage","sessionStorage","indexedDB","WebSocket","XMLHttpRequest","HTMLElement","HTMLInputElement","HTMLButtonElement","HTMLFormElement","HTMLAnchorElement","HTMLImageElement","HTMLVideoElement","HTMLAudioElement","HTMLCanvasElement","HTMLSelectElement","HTMLTextAreaElement","HTMLDivElement","HTMLSpanElement","HTMLParagraphElement","HTMLHeadingElement","HTMLTableElement","HTMLTableRowElement","HTMLTableCellElement","HTMLUListElement","HTMLOListElement","HTMLLIElement","HTMLLabelElement","HTMLDialogElement","HTMLDetailsElement","HTMLSlotElement","HTMLTemplateElement","SVGElement","SVGSVGElement","Element","Node","NodeList","DocumentFragment","ShadowRoot","Document","Window"]),U="root";function d(e,t,r){return Ie(e,e,t,yt(r))}function Ie(e,t,r,o){if(Ne(e)&&ge(e,t)){let a=e.text;return r?.hasUnresolvableIdentifier(a)||o.skipResolution?a:o.resolver?`${o.resolver}.${a}`:r?Lt(a,r):a}if(!Ae(e,t))return e.getText();let n=e.getSourceFile().text,i="",s=e.getStart();return ke(e,a=>{i=`${i}${n.slice(s,a.getStart())}${Ie(a,e,r,o)}`,s=a.getEnd()}),`${i}${n.slice(s,e.getEnd())}`}function Lt(e,t){if(t.hasIdentifier(e)){let r=t.getIdentifierKind(e),o=`context.get('${e}')`;return r==="signal"?`${o}()`:o}return e}function Ae(e,t){if(Ne(e)&&ge(e,t))return!0;let r=!1;return ke(e,o=>{r||(r=Ae(o,e))}),r}function ge(e,t){return!(It(t)&&t.name===e||At(t)&&t.name===e||gt.has(e.text)||!e.text)}function Le(e,t,r){return pe(e.tagName,t,r)}function ae(e="text",t,r){return pe(e,t,r)}function S(e,t,r){return pe(e,t,r)}function pe(e,t,r){return(t!==U?`${t}__${e}${r}`:`${e}${r}`).replace(/-/g,"_")}function yt(e){return{skipResolution:e?.skipResolution??!1,resolver:e?.resolver??"this"}}function ye(e,t,r,o,n){let i=vt(e.attributes,o),s=_t(e.events,o),a=Le(e,t,r),c=e.tagName,m={code:[],functionsToProcess:new Map};switch(c){case"svg":m.code.push("context.createElement = createSVGElement");break;case"math":m.code.push("context.createElement = createMATHMLElement")}switch(m.code.push(`const ${a} = _renderElement(${t}, context, ${n}, '${c}',`),i.length?m.code.push(...F(["[",...F(i),"],"])):m.code[m.code.length-1]=`${m.code[m.code.length-1]} [],`,s.length?m.code.push(...F(["[",...F(s),"]"]),");"):m.code[m.code.length-1]=`${m.code[m.code.length-1]} []);`,c){case"svg":case"math":m.code.push("context.createElement = createElement")}return e.children.length&&(m.functionsToProcess.set(`${a}Children`,{fn:{node:e,parentNode:a,context:o,precode:Ot(c)},args:[a,"parentContext"]}),m.code.push(`this.${a}Children(${a}, context);`)),m}function vt(e,t){return e?.map(({name:r,value:o})=>{let n=typeof o=="string";return`{ name: '${r}', value: () => ${n?`'${o}'`:d(o.expression,t)}, literal: ${n} },`})}function _t(e,t){t.addUnresolvableIdentifier("$event");let r=e.map(o=>{let n=!1,i=o.parameters.map(a=>{let c=d(a,t);return!n&&c==="$event"?(n=!0,`($event) => ${c},`):`() => ${c},`}),s=["{",...F([`name: '${o.name}',`,`handler: '${o.handler}',`,"parameters: ["])];return i.length?s.push(...F([...F(i),"]"]),"},"):(s[s.length-1]=`${s[s.length-1]}]`,s.push("},")),s}).flat();return t.removeIdentifier("$event"),r}function Ot(e){switch(e){case"svg":return"context.createElement = createSVGElement;";case"math":return"context.createElement = createMATHMLElement;";default:return""}}function ve(e,t,r,o){let n={code:[],functionsToProcess:new Map},i=e.iterableSource,s=o.hasIdentifier(i)?i:`this.${i}`,a=ae("items",t,r),c=ae("i",t,r),m=V(e,"$index"),l=V(e,"$first"),E=V(e,"$last"),k=V(e,"$even"),I=V(e,"$odd"),A=new x([e.itemAlias,[m,"signal"],[l,"signal"],[E,"signal"],[k,"signal"],[I,"signal"]],o),R=S("for",t,r);return n.functionsToProcess.set(R,{fn:{precode:`const { vars, update } = _iterationVariables(context, ${a}, ${c}, '${e.itemAlias}', {
|
|
2
|
+
$index: '${m}',
|
|
3
|
+
$first: '${l}',
|
|
4
|
+
$last: '${E}',
|
|
5
|
+
$even: '${k}',
|
|
6
|
+
$odd: '${I}'
|
|
7
|
+
});
|
|
8
|
+
const { ${e.itemAlias}, ${m}, ${l}, ${E}, ${k}, ${I} } = vars;`,node:e,parentNode:R,context:A,anchor:"anchor",isForBody:!0},args:[R,"parentContext",a,c,"anchor"]}),n.code.push(`_for(${t}, context, () => ${s}, ${e.itemAlias} => ${d(e.trackExpression,A,{skipResolution:!0})}, this.${R}.bind(this));`),n}function V(e,t){return e.implicitAliases.get(t)??t}import{indent as $}from"@xaendar/common";function _e(e,t,r,o){let n=new x([],o),i={code:[],functionsToProcess:new Map};i.code.push(`_if(${t}, context, [`);let s=S("if",t,r);i.code.push(...$(["{",...$([`condition: () => ${d(e.conditionNode,o)},`,`block: this.${s}.bind(this)`]),"},"])),i.functionsToProcess.set(s,{fn:{node:e,parentNode:s,context:n,anchor:"anchor"},args:[s,"parentContext","anchor"]});let a=e.alternate,c=0;for(;a?.type===5;){let m=new x([],o),l=S("elseIf",t,`${r}_${c}`),E=a.conditionNode;i.code.push(...$(["{",...$([`condition: () => ${d(E,o)},`,`block: this.${l}.bind(this)`]),"},"])),i.functionsToProcess.set(l,{fn:{node:a,parentNode:t,context:m,anchor:"anchor"},args:[t,"parentContext","anchor"]}),a=a.alternate,c++}if(a){let m=new x([],o),l=S("else",t,r);i.code.push(...$(["{",...$([`block: this.${l}.bind(this)`]),"},"])),i.functionsToProcess.set(l,{fn:{node:a,parentNode:t,context:m,anchor:"anchor"},args:[t,"parentContext","anchor"]})}return i.code.push("]);"),i}import{indent as Oe}from"@xaendar/common";function Re(e,t,r,o){let n={code:[],functionsToProcess:new Map};return n.code.push(`_switch(${t}, context, () => ${d(e.expression,o)}, [`),e.children.forEach((i,s)=>{let a=new x([],o),c=i.condition?S("case",t,`${r}_${s}`):S("default",t,r);n.functionsToProcess.set(c,{fn:{node:i,parentNode:c,context:a},args:[c,"parentContext","anchor"]});let m=`this.${c}.bind(this)`;n.code.push(...Oe(["{",...Oe([`condition: ${i.condition?`[${i.condition.join(", ")}]`:"null"},`,`block: ${m}`]),"},"]))}),n.code.push("])"),n}function ce(e,t,r,o){return{code:[`${e.type===1?`_renderLiteralText(${t}, context, '${e.value}');`:`_renderText(${t}, context, () => ${d(e.expression,o)});`}`]}}function Se(e,t,r,o){}var z=class{constructor(t){this._ast=t}_ast;_nodeToProcess=new Map;_states={1:ce,2:ce,0:ye,3:_e,6:ve,7:Re,9:Se};generate(t){this._nodeToProcess.clear();let r=new x,o=["_render() {",...b([`const ${U} = this._root;`,"const context = new Context(this, { createElement: document.createElement.bind(document), get: () => undefined });"])];t&&o.push(b(`${U}.adoptedStyleSheets = [${t}];`));for(let n=0;n<this._ast.length;n++){let i=this._processNode(this._ast[n],U,n.toString(),r,null);if(i){let{code:s,functionsToProcess:a}=i;a?.forEach((c,m)=>this._nodeToProcess.set(m,c)),o.push(...b(s))}}o.push(...b(["return context;"]),"}");for(let[n,i]of this._nodeToProcess.entries()){let{node:s,parentNode:a,context:c,precode:m,anchor:l}=i.fn;o.push(`
|
|
9
|
+
${n}(${i.args?.join(", ")}) {`,...b(["const context = new Context(this, parentContext);"])),m&&o.push(b(m)),o.push(...b([...s.children.map((E,k)=>{let I=this._processNode(E,a,k.toString(),c,l??null);if(I){let{code:A,functionsToProcess:R}=I;return R?.forEach((X,Q)=>this._nodeToProcess.set(Q,X)),A}return""}).flat(),i.fn.isForBody?"return { context, update };":"return context;"]),"}")}return o.join(`
|
|
10
|
+
`)}_processNode(t,r,o,n,i){let s=this._states[t.type];if(!s)throw new Error(`[Generator] No transition function for token type ${h[t.type]}`);return s(t,r,o,n,i)}};import{Stack as bt}from"@xaendar/common";var u=(f=>(f[f.TEXT=0]="TEXT",f[f.TAG_OPEN_NAME=1]="TAG_OPEN_NAME",f[f.TAG_SELF_CLOSE=2]="TAG_SELF_CLOSE",f[f.TAG_OPEN_END=3]="TAG_OPEN_END",f[f.TAG_CLOSE_NAME=4]="TAG_CLOSE_NAME",f[f.ATTRIBUTE=5]="ATTRIBUTE",f[f.ATTRIBUTE_VALUE=6]="ATTRIBUTE_VALUE",f[f.EVENT=7]="EVENT",f[f.EVENT_PAREMETER=8]="EVENT_PAREMETER",f[f.INTERPOLATION_LITERAL=9]="INTERPOLATION_LITERAL",f[f.INTERPOLATION_EXPRESSION=10]="INTERPOLATION_EXPRESSION",f[f.IF=11]="IF",f[f.FOR=12]="FOR",f[f.ELSE=13]="ELSE",f[f.ELSE_IF=14]="ELSE_IF",f[f.SWITCH=15]="SWITCH",f[f.CASE=16]="CASE",f[f.DEFAULT=17]="DEFAULT",f[f.CONDITION=18]="CONDITION",f[f.BLOCK_OPEN=19]="BLOCK_OPEN",f[f.BLOCK_CLOSE=20]="BLOCK_CLOSE",f[f.IMPORT=21]="IMPORT",f[f.IMPORT_PATH=22]="IMPORT_PATH",f[f.EOF=23]="EOF",f))(u||{});function we(e,t){let r=!0,o="",n;for(;r;)e.peek()===34?(e.advance(),r=!1,n={state:"tag-body",tokens:[{type:6,parts:[o]}],popState:!0}):(e.advance(),o=`${o}${e.currentChar.value}`);return n}function Fe(e,t){let r=!0,o="",n;for(;r;)switch(e.peek()){case 32:e.advance(),r=!1,n={state:"tag-body",tokens:[{type:5,parts:[o]}]};break;case 61:if(e.advance(),e.peek()!==34){let{row:s,column:a}=e.position;throw new Error(`Attribute value must start with double quotes '"'.Row ${s} Col ${a}`)}e.advance(),r=!1,n={state:e.peek()===123?"interpolation":"attribute-value",pushState:!0,tokens:[{type:5,parts:[o]}]};break;default:e.advance(),o=`${o}${e.currentChar.value}`}return n}function j(e,t){if(e.skipSpaces(),e.peek()!==40)throw new Error(`Expected '(' but got '${String.fromCharCode(e.peek())}' at row ${e.position.row}, col ${e.position.column}`);e.advance();let r="",o=1;for(;o>0;)switch(e.peek()){case 40:o++,r=me(e,r);break;case 41:if(o--,!o){e.advance();break}r=me(e,r);break;default:r=me(e,r)}return r}function me(e,t){return e.advance(),`${t}${e.currentChar.value}`}function be(e,t){let r=j(e,t);return e.skipSpaces(),{state:e.peekMatch("@case")?"flow-control":"flow-control-block",tokens:[{type:18,parts:[r]}],popState:!0}}function Pe(e,t){return{state:"flow-control-block",tokens:[{type:18,parts:[j(e,t)]}],popState:!0}}function $e(e,t){let r=!0,o="",n="",i={state:"tag-body",tokens:[]};for(;r;)switch(e.peek()){case 91:case 93:case 123:case 125:case 34:case 39:case 40:o=le(e,o),n?(n===e.currentChar.value||n==="["&&e.currentChar.value==="]"||n==="{"&&e.currentChar.value==="}")&&(n=""):n=e.currentChar.value;break;case 44:n?o=le(e,o):(i.tokens.push({type:8,parts:[o]}),e.advance(),e.skipSpaces(),o="");break;case 41:e.advance(),n||(i.tokens.push({type:8,parts:[o]}),r=!1);default:o=le(e,o)}return i}function le(e,t){return e.advance(),`${t}${e.currentChar.value}`}function Me(e,t){let r=!0,o="",n;for(e.advance();r;)switch(e.peek()){case 32:case 47:case 62:n={state:"tag-body"},r=!1;break;case 40:let i="parameter";e.advance(),e.skipSpaces(),e.peek()===41&&(i="tag-body",e.advance(2)),n={state:i,tokens:[{type:7,parts:[o]}]},r=!1;break;default:e.advance(),o=`${o}${e.currentChar.value}`}return n}function Be(e,t){let r;return e.advance(),e.peekMatch("for ")?(e.advance(4),r={state:"flow-control-condition",tokens:[{type:12}],pushState:!0}):e.peekMatch("if ")?(e.advance(2),r={state:"flow-control-condition",tokens:[{type:11}],pushState:!0}):e.peekMatch("else if ")?(e.advance(8),r={state:"flow-control-condition",tokens:[{type:14}],pushState:!0}):e.peekMatch("else ")?(e.advance(5),r={state:"flow-control-block",tokens:[{type:13}]}):e.peekMatch("switch ")?(e.advance(7),r={state:"flow-control-condition",tokens:[{type:15}],pushState:!0}):e.peekMatch("case ")?(e.advance(5),r={state:"case-flow-control-condition",tokens:[{type:16}],pushState:!0}):e.peekMatch("default ")?(e.advance(8),r={state:"flow-control-block",tokens:[{type:17}]}):e.peekMatch("import ")&&(e.advance(7),r={state:"import"}),r}function De(e,t){if(e.skipSpaces(),e.peek()!==123)throw new Error(`Expected '{' but got '${String.fromCharCode(e.peek())}' at row ${e.position.row}, col ${e.position.column}`);return e.advance(),{state:"text",tokens:[{type:19}],pushState:!0}}function Ge(e,t){let r=!0,o="",n,i=!1;if(e.skipSpaces(),!e.peekMatch("from"))throw new Error(`Expected from keywork after list of imports at ${e.currentChar}`);switch(e.advance(4),e.skipSpaces(),e.advance(),e.currentChar.code){case 39:i=!0;break;case 34:break;default:throw new Error(`Import statement must start with ' or ".
|
|
11
|
+
Found character ${e.currentChar.value} at ${e.formattedPosition}`)}let s=i?39:34;for(;r;)e.peek()===s?(e.advance(),r=!1,n={state:"text",tokens:[{type:22,parts:[o]}]}):(e.advance(),o=`${o}${e.currentChar.value}`);return n}function Ve(e,t){let r=!0,o="",n={state:"import-path",tokens:[]};if(e.skipSpaces(),e.advance(),e.currentChar.code!==123)throw new Error(`Expected { after @import at ${e.formattedPosition}`);for(;r;)switch(e.peek()){case 32:e.skipSpaces(),o&&e.peek()!==44&&e.peek()!==125&&(o=`${o} `);break;case 44:Ue(n,e,o),o="";break;case 125:Ue(n,e,o),r=!1;break;default:e.advance(),o=`${o}${e.currentChar.value}`}return n}function Ue(e,t,r){t.advance(),e.tokens.push({type:21,parts:[r]})}function He(e,t){let r=!0,o="",n=1,i;for(;r;)switch(e.peek()){case 123:n++,o=fe(e,o);break;case 125:if(n--,n===0){e.advance(),o=o.trimEnd();let s=t.history.pop(),a;switch(s){case"attribute":if(e.peek()!==34)throw new Error(`Interpolation must end with double quotes '"' Found ${String.fromCharCode(e.peek())} at ${e.formattedPosition}`);e.advance(),a="tag-body";break;case"text":a="text"}i={state:a,tokens:[{type:10,parts:[o]}],popState:!0},r=!1}else o=fe(e,o);break;default:o=fe(e,o)}return i}function fe(e,t){return e.advance(1),`${t}${e.currentChar.value}`}function We(e,t){let r=!0,o="`",n;for(e.advance();r;)switch(e.peek()){case 96:if(o=Ke(e,o),e.peek()===125){e.advance();let i=t.history.pop(),s;switch(i){case"attribute":if(e.peek()!==34)throw new Error(`Attribute interpolation expression must end with double quotes at ${e.formattedPosition}`);e.advance(),s="tag-body";break;case"text":s="text"}n={state:s,tokens:[{type:9,parts:[o]}],popState:!0},r=!1}else o=`${o}${e.currentChar.value}`;break;default:o=Ke(e,o)}return n}function Ke(e,t){return e.advance(),`${t}${e.currentChar.value}`}function qe(e,t){return e.advance(),e.skipSpaces(),e.peek()===96?{state:"interpolation-literal"}:{state:"interpolation-expression"}}function Xe(e,t){let r=!0,o;for(;r;)switch(e.peek()){case 64:o={state:"event"},r=!1;break;case 32:e.skipSpaces();break;case 62:case 47:o={state:"tag-open-end"},r=!1;break;default:o={state:"attribute"},r=!1}return o}function Qe(e,t){let r=!0,o="",n;for(e.advance(2),e.skipSpaces();r;)switch(e.peek()){case 62:e.advance(),n={state:"text",tokens:[{type:4,parts:[o]}]},r=!1;break;case 32:throw new Error("Tag Close Name cannot contains spaces");default:e.advance(),o=`${o}${e.currentChar.value}`}return n}function ze(e,t){let r;if(e.peek()===62)e.advance(),r={state:"text",tokens:[{type:3,parts:[]}]};else{e.advance();let o=e.peek();if(o===62)e.advance(),r={state:"text",tokens:[{type:2,parts:[]}]};else throw new Error(`Unexpected character ${o} for closing tag.
|
|
12
|
+
Expected />
|
|
13
|
+
Read of /${String.fromCharCode(o)} at ${e.formattedPosition}`)}return r}function je(e,t){let r=!0,o="",n;for(e.advance(),e.skipSpaces();r;)switch(e.peek()){case 32:case 47:case 62:n={state:"tag-body",tokens:[{type:1,parts:[o]}]},r=!1;break;default:e.advance(),o=`${o}${e.currentChar.value}`}return n}function Ye(e){return/\S/.test(e)}function Ze(e,t){let r=!0,o="",n;for(;r;)switch(e.peek()){case 60:n={state:e.peek(1,{offset:1})===47?"tag-close":"tag-open-name"},r=!1;break;case 123:n={state:"interpolation",pushState:!0},r=!1;break;case 64:n={state:"flow-control"},r=!1;break;case 125:t.history[t.history.length-1]==="flow-control-block"?(e.advance(),n={state:"text",tokens:[{type:20}],popState:!0},r=!1):(e.advance(),o=`${o}${e.currentChar.value}`);break;case 10:case 13:e.advance();break;default:e.advance(),o=`${o}${e.currentChar.value}`}return n.tokens??=Ye(o)?[{type:0,parts:[o]}]:void 0,n}var re=class{constructor(t){this.input=t}input;_currentChar={code:0,index:-1,value:""};get currentChar(){return this._currentChar}_peekCache=new Map;_position={row:0,column:0};get position(){return this._position}get formattedPosition(){return`[Ln ${this._position.row}, Col ${this._position.column}]`}advance(t=1){if(t<1)throw new Error(`${t} is not a valid value. Please enter a number equal or greater than 1`);let r=this._currentChar.index+t;r>=this.input.length?(this._currentChar.code=0,this._currentChar.index=-1,this._currentChar.value="",this.throwEOFError()):([10,13].includes(this._currentChar.code)?(this._position.row++,this._position.column=0):this._position.column++,this._currentChar.index=r,this._currentChar.value=this.input[r],this._currentChar.code=this.input.charCodeAt(r))}peekMatch(t,r){if(typeof t=="string"){let i=this.peek(t.length);for(let s=0;s<t.length;s++)if(i[s]!==t.charCodeAt(s))return!1;return!0}let o=this._currentChar.index+1,n=this.input.slice(o,o+r);return t.test(n)}peek(t,r){let o=this._peekCache,n=typeof t=="number"?t:1,i=(typeof t=="object"?t:r)?.offset??0;return n===1?this.peekOneChar(this._currentChar.index+i+1,o):this.peekMany(n+i,o)}skipSpaces(){for(;this.peek()===32||this.peek()===10||this.peek()===13;)this.advance()}peekMany(t,r){let o=new Array,n=this._currentChar.index+1;for(let i=n;i<n+t;i++)o.push(this.peekOneChar(i,r));return o}peekOneChar(t,r){if(r.has(t))return r.get(t);t>=this.input.length&&this.throwEOFError();let o=this.input.charCodeAt(t);return r.set(t,o),o}throwEOFError(){throw new Error("",{cause:0})}};var oe=class{constructor(t){this.input=t;this._cursor=new re(this.input)}input;_cursor;_state="text";_stack=new bt;_tokens=new Array;_states={text:Ze,"tag-open-name":je,"tag-body":Xe,"tag-open-end":ze,"tag-close":Qe,attribute:Fe,"attribute-value":we,event:Me,parameter:$e,"flow-control":Be,"flow-control-condition":Pe,"case-flow-control-condition":be,"flow-control-block":De,interpolation:qe,"interpolation-expression":He,"interpolation-literal":We,import:Ve,"import-path":Ge};tokenize(){let t=!1;for(;!t;)try{let r=this._states[this._state],{state:o,tokens:n,popState:i,pushState:s}=r(this._cursor,{history:this._stack.values,tokens:[...this._tokens]});n?.length&&this._tokens.push(...n),s&&this._stack.push(this._state),i&&this._stack.pop(),this._state=o}catch(r){if(r.cause===0)t=!0;else throw console.log(`Something went wrong while computing state ${this._state} at ${this._cursor.formattedPosition}`),r}return this._tokens}};var ne=class{constructor(t){this._tokens=t}_tokens;_currentToken={value:{type:23},index:-1};getCurrentToken(){return this._currentToken}advance(t=1){if(t<1)throw new Error(`${t} is not a valid value. Please enter a number equal or greater than 1`);let r=this._currentToken.index+t;r>=this._tokens.length?(this._currentToken.value={type:23},this._currentToken.index=-1):(this._currentToken.index=r,this._currentToken.value=this._tokens[r])}peek(t,r){let o=typeof t=="number"?t:1,n=(typeof t=="object"?t:r)?.offset??0;return o===1?this.peekOneToken(this._currentToken.index+n+1):this.peekMany(o+n)}peekMany(t){let r=new Array,o=this._currentToken.index+1;for(let n=o;n<o+t;n++)r.push(this.peekOneToken(n));return r}peekOneToken(t){return t<this._tokens.length?this._tokens[t]:{type:23}}};import{ScriptTarget as Pt,SyntaxKind as p,createSourceFile as $t,forEachChild as Mt}from"typescript";function y(e){let t="const x = ",n=$t("expression.ts",`${t}${e}`,Pt.ESNext,!0).statements[0].declarationList.declarations[0].initializer,i=new Array;if(Je(n,t.length,i),i.length)throw new Error(i.reduce((s,a)=>`${s}${a.message}
|
|
14
|
+
`,""));return{node:n}}function Je(e,t,r){if(!Bt(e))throw new Error(Dt(e));if(Mt(e,o=>Je(o,t,r)),r.length)throw new Error(r[0].message)}function Bt(e){switch(e.kind){case p.StringLiteral:case p.NumericLiteral:case p.BigIntLiteral:case p.TrueKeyword:case p.FalseKeyword:case p.NullKeyword:case p.UndefinedKeyword:case p.Identifier:case p.PropertyAccessExpression:case p.ElementAccessExpression:case p.CallExpression:case p.BinaryExpression:case p.EqualsEqualsToken:case p.EqualsEqualsEqualsToken:case p.ExclamationEqualsToken:case p.ExclamationEqualsEqualsToken:case p.LessThanToken:case p.LessThanEqualsToken:case p.GreaterThanToken:case p.GreaterThanEqualsToken:case p.PlusToken:case p.MinusToken:case p.AsteriskToken:case p.SlashToken:case p.PercentToken:case p.AsteriskAsteriskToken:case p.AmpersandAmpersandToken:case p.BarBarToken:case p.QuestionQuestionToken:case p.QuestionDotToken:case p.QuestionToken:case p.ColonToken:case p.AmpersandToken:case p.BarToken:case p.CaretToken:case p.LessThanLessThanToken:case p.GreaterThanGreaterThanToken:case p.GreaterThanGreaterThanGreaterThanToken:case p.InstanceOfKeyword:case p.InKeyword:case p.PrefixUnaryExpression:case p.PostfixUnaryExpression:case p.TypeOfExpression:case p.VoidExpression:case p.ConditionalExpression:case p.ParenthesizedExpression:case p.TemplateExpression:case p.NoSubstitutionTemplateLiteral:case p.TemplateHead:case p.TemplateMiddle:case p.TemplateTail:case p.TemplateSpan:case p.ArrayLiteralExpression:case p.ObjectLiteralExpression:case p.PropertyAssignment:case p.ShorthandPropertyAssignment:case p.SpreadAssignment:case p.SpreadElement:case p.TaggedTemplateExpression:case p.SyntaxList:return!0;default:return!1}}function Dt(e){switch(e.kind){case p.AwaitExpression:return"'await' is not allowed inside template expressions.";case p.YieldExpression:return"'yield' is not allowed inside template expressions.";case p.NewExpression:return"'new' is not allowed inside template expressions.";case p.ArrowFunction:case p.FunctionExpression:return"Function expressions are not allowed inside template expressions.";case p.BinaryExpression:return Gt(e.operatorToken.kind)?"Assignments are not allowed inside template expressions. Use @const to declare local template variables instead.":`'${p[e.kind]}' is not allowed inside template expressions.`;default:return`'${p[e.kind]}' is not allowed inside template expressions.`}}function Gt(e){return e>=p.FirstAssignment&&e<=p.LastAssignment}function K(e,t,r){return e.advance(),{type:2,expression:y(r.parts[0]).node}}function et(e,t,r){e.advance();let o=r.parts[0],n=e.peek();if(n.type===5||n.type===4||n.type===7)return{name:o,value:"true"};if(n.type===10||n.type===9)return{name:o,value:K(e,t,n)};if(n.type!==6)throw new Error(`[Parser] Attribute value missing for ${o} in: ${o}`);return e.advance(),{name:o,value:n.parts[0]}}function tt(e,t,r){e.advance();let o=r.parts[0],[n,i]=o.split("=");if(!n||!i)throw new Error(`[Parser] Invalid event format: ${o}`);let s=new Array;for(;e.peek().type===8;)e.advance(),s.push(y(e.getCurrentToken().value.parts[0]).node);return{name:n,handler:i.replace(/^[""]|[""]$/g,""),parameters:s}}function rt(e,t,r){e.advance();let o=r.parts[0],n=new Array,i=new Array,s=!0;for(;s;){let c=e.peek();switch(c.type){case 5:n.push(et(e,t,c));break;case 7:i.push(tt(e,t,c));break;default:s=!1}}if(e.peek().type===3&&e.advance(),e.peek().type===2)return e.advance(),{type:0,tagName:o,attributes:n,events:i,children:[]};let a=new Array;for(;!Ut(e,o);){let c=t();c&&a.push(c)}return e.advance(),{type:0,tagName:o,attributes:n,events:i,children:a}}function Ut(e,t){let r=e.peek();return r.type===4&&r.parts[0]===t}import{createSourceFile as Vt,isExpressionStatement as Ht,isIdentifier as Kt,ScriptTarget as Wt}from"typescript";function w(e,t){let r=new Array;for(;e.peek().type!==20;){let o=t();o&&r.push(o)}return e.advance(),r}function ot(e,t,r){e.advance();let o=e.peek();if(o.type!==18)throw new Error(`[Parser] Expected CONDITION after FOR, got ${u[o.type]}`);let n=qt(o.parts[0],0);e.advance(2);let i=w(e,t);return{type:6,...n,children:i}}function qt(e,t){let r=Qt(e);if(r.length<2)throw new Error('[Parser] @for requires at least "item of iterable; track expr".');let o=r[0].trim(),n=o.indexOf(" of ");if(n===-1)throw new Error('[Parser] @for expression must be in the form "item of iterable".');let i=o.slice(0,n).trim(),s=o.slice(n+4).trim();if(!nt(i))throw new Error(`[Parser] '${i}' is not a valid item alias.`);let a=y(s),c=r[1].trim();if(!c.startsWith("track "))throw new Error('[Parser] Second section of @for must start with "track".');let m=c.slice(6).trim(),l=y(m),E=new Map;if(r.length>=3&&r[2]!==void 0){let k=r[2].trim(),I=t+e.indexOf(r[2]);Xt(k,I,E)}return{itemAlias:i,iterableExpression:a.node,iterableSource:s,trackExpression:l.node,trackSource:m,implicitAliases:E}}function Xt(e,t,r){let o=e.split(","),n=0,i=new Set(["$index","$last","$first","$even","$odd"]);for(let s of o){let a=s.trim(),c=a.indexOf("=");if(c===-1)throw new Error(`[Parser] Invalid alias declaration '${a}'. Expected '$implicit = alias'.`);n+=s.length+1;let m=a.slice(0,c).trim(),l=a.slice(c+1).trim();if(!(k=>i.has(k))(l))throw new Error(`[Parser] '${l}' is not a known implicit variable. Known variables: ${[...i].join(", ")}.`);if(n+=s.length+1,!nt(m))throw new Error(`[Parser] '${m}' is not a valid alias identifier.`);if(n+=s.length+1,r.has(l))throw new Error(`[Parser] '${l}' is already aliased in this @for expression.`);r.set(l,m),n+=s.length+1}}function Qt(e){let t=new Array,r="",o=0,n;for(let i=0;i<e.length;i++){let s=e[i];if(!(!r&&s===" ")){if(n){r+=s,s===n&&e[i-1]!=="\\"&&(n=null);continue}if(s==='"'||s==="'"||s==="`"){n=s,r+=s;continue}if(s==="("||s==="["||s==="{"){o++,r+=s;continue}if(s===")"||s==="]"||s==="}"){o--,r+=s;continue}if(s===";"&&o===0){t.push(r),r="";continue}r+=s}}return r.trim().length&&t.push(r),t}function nt(e){if(!e.length)return!1;let r=Vt("__id.ts",e,Wt.ESNext,!1).statements[0];return!!r&&Ht(r)&&Kt(r.expression)&&r.expression.text===e}function it(e,t,r){return st(e,t,r)}function zt(e,t,r){switch(r.type){case 14:return st(e,t,r);case 13:e.advance(2);let o=w(e,t);return{type:4,children:o}}}function st(e,t,r){e.advance();let o=e.peek();if(o.type!==18)throw new Error(`[Parser] Expected CONDITION after ${u[r.type]}, got ${u[o.type]}`);e.advance(2);let n=o.parts[0],i=y(n),s=w(e,t);return{type:r.type===11?3:5,condition:n,conditionNode:i.node,children:s,alternate:zt(e,t,e.peek())}}function at(e,t,r){let o=new Array;for(;e.peek().type===21;){e.advance();let n=e.getCurrentToken().value.parts[0],i=jt(n);o.push(i)}return e.advance(),{type:9,specifiers:o,path:e.getCurrentToken().value.parts[0]}}function jt(e){let t=e.trim(),r=t.match(/^\*\s+as\s+([A-Za-z_$][\w$]*)$/);if(r)return{imported:"*",local:r[1]};let o=t.match(/^default\s+as\s+([A-Za-z_$][\w$]*)$/);if(o)return{imported:"default",local:o[1]};let n=t.match(/^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);if(n)return{imported:n[1],local:n[2]??n[1]};throw new Error(`[Parser] Invalid import specifier "${e}".`)}function pt(e,t,r){e.advance();let o=e.peek();if(o.type!==18)throw new Error(`[Parser] Expected CONDITION after SWITCH, got ${u[o.type]}`);let n=y(o.parts[0]).node;e.advance(2);let i=new Array;for(;e.peek().type!==20;)switch(e.peek().type){case 16:let a=new Array;do{e.advance();let c=e.peek();if(c.type!==18)throw new Error("[Parser] Expected CONDITION after CASE");a.push(c.parts[0]),e.advance()}while(e.peek().type!==19);e.advance(),i.push({type:8,condition:a,children:w(e,t)});break;case 17:e.advance(2),i.push({type:8,condition:null,children:w(e,t)});break}return e.advance(),{type:7,expression:n,children:i}}function ct(e,t,r){return e.advance(),{type:1,value:r.parts[0]}}var ie=class{_cursor;_states={0:ct,10:K,9:K,1:rt,11:it,12:ot,15:pt,21:at};constructor(t){this._cursor=new ne(t)}parse(){let t=new Array;for(;this._cursor.peek().type!==23;){let r=this.parseNode();r&&t.push(r)}return t}parseNode(){let t=this._cursor.peek();if(t.type===23)return;let r=this._states[t.type];if(!r)throw new Error(`[Parser] No transition function for token type ${u[t.type]}`);return r(this._cursor,this.parseNode.bind(this),t)}};import{indent as Er}from"@xaendar/common";var B=class extends x{_imports=new Array;addImport(t){this._imports.push(t)}getImportBySelector(t){return this._imports.find(r=>r.type==="component"&&r.selectors.includes(t))}};function mt(e,t,r){let o=new Array;if(er(e.tagName)){let n=r.getImportBySelector(e.tagName);if(!n)throw new Error(`[Type Checker] ${e.tagName} selector is not associated to any WebComponent imported in the template`);o.push(...Yt(e,n,r))}else e.attributes.forEach(({value:n})=>{typeof n!="string"&&o.push(`${d(n.expression,r,{resolver:"root"})};`)}),e.events.forEach(({handler:n,parameters:i})=>{let s=new x([],r);s.addUnresolvableIdentifier("$event");let a=i.map(c=>d(c,s,{resolver:"root"})).join(", ");o.push(`root.${n}(${a});`)});return e.children.forEach(n=>o.push(...t(n,r))),o}function Yt(e,t,r){let o=new Array;return e.attributes.forEach(({name:n,value:i})=>{let s=Zt(t,n);if(!s)throw new Error(`[Type Checker] Unknown property "${n}" on <${e.tagName}> (${t.className} has no @Property with this name or alias).`);if(typeof i=="string")return;let a=d(i.expression,r,{resolver:"root"});o.push(s.type?`(${a}) satisfies ${s.type};`:`${a};`)}),e.events.forEach(({name:n,handler:i,parameters:s})=>{let a=Jt(t,n);if(!a)throw new Error(`[Type Checker] Unknown event "${n}" on <${e.tagName}> (${t.className} has no @Event with this name).`);let c=new x([],r);c.addUnresolvableIdentifier("$event");let m=s.map(l=>d(l,c,{resolver:"root"})).join(", ");o.push("{"),o.push(` let $event!: ${a.detailType??"unknown"};`),o.push(` root.${i}(${m});`),o.push("}")}),o}function Zt(e,t){return e.properties.find(r=>(r.alias??r.name)===t)}function Jt(e,t){return e.events.find(r=>r.name===t)}function er(e){return/^[a-z][a-z0-9._\-]*-[a-z0-9._\-]*$/.test(e)}import{indent as tr}from"@xaendar/common";function lt(e,t,r){let o=new B([],r),n=W(e,"$index"),i=W(e,"$first"),s=W(e,"$last"),a=W(e,"$even"),c=W(e,"$odd");[n,i,s,a,c,e.itemAlias].forEach(l=>o.addUnresolvableIdentifier(l));let m=new Array;return m.push(`for (const ${e.itemAlias} of root.${e.iterableSource}) {`),m.push(...tr([`let ${n}!: number;`,`let ${i}!: boolean;`,`let ${s}!: boolean;`,`let ${a}!: boolean;`,`let ${c}!: boolean;`,`${d(e.trackExpression,r,{skipResolution:!0})};`,...e.children.flatMap(l=>t(l,o))])),m.push("}"),m}function W(e,t){return e.implicitAliases.get(t)??t}import{indent as Te}from"@xaendar/common";function ft(e,t,r){let o=new Array,n=d(e.conditionNode,r,{resolver:"root"});o.push(`if (${n}) {`),o.push(...Te(e.children.flatMap(s=>t(s,r)))),o.push("}");let i=e.alternate;for(;i?.type===5;){let s=d(i.conditionNode,r,{resolver:"root"});o.push(`else if (${s}) {`),o.push(...Te(i.children.flatMap(a=>t(a,r)))),o.push("}"),i=i.alternate}return i&&(o.push("else {"),o.push(...Te(i.children.flatMap(s=>t(s,r)))),o.push("}")),o}function dt(e,t,r){let o=e.path,n=ut(o),i=new Array;for(let s of e.specifiers){let{imported:a,local:c}=s;switch(a){case"*":i.push(`let ${c}!: typeof import('${n}');`);break;case"default":i.push(`let ${c}!: typeof import('${n}')['default'];`);break;default:let m=ut(a);i.push(`let ${c}!: typeof import('${n}')['${m}'];`);break}}return i}function ut(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}import{indent as Tt}from"@xaendar/common";function xt(e,t,r){let n=[`switch (${d(e.expression,r,{resolver:"root"})}) {`];return e.children.forEach(i=>{i.condition?.length?i.condition.forEach(s=>n.push(` case ${s}:`)):n.push(" default:"),n.push(...Tt(Tt([...i.children.flatMap(s=>t(s,r)),"break;"])))}),n.push("}"),n}function xe(e,t,r){return e.type===2?[`${d(e.expression,r,{resolver:"root"})};`]:[]}import{existsSync as he}from"fs";import{readFile as rr}from"fs/promises";import{resolve as or}from"path";import{createSourceFile as nr,forEachChild as ir,getNameOfDeclaration as ht,isAccessor as sr,isArrayLiteralExpression as ar,isCallExpression as q,isClassDeclaration as pr,isIdentifier as v,isObjectLiteralExpression as Et,isPropertyAccessExpression as Ct,isPropertyAssignment as kt,isStringLiteral as Ee,ScriptTarget as cr,SyntaxKind as Ce}from"typescript";async function Nt(e,t,r=process.cwd()){try{let o=mr(e,r);if(!o)return;let n=await rr(o,"utf8"),i=nr(o,n,cr.Latest,!0),s;return ir(i,a=>{if(!s&&pr(a)){let c=a.name?.text;if(c!==t)return;let m=a.modifiers??[],l=Array.from(m).find(A=>lr(A));if(!l)return;let E=dr(l);if(!E?.length)return;let k=new Array,I=new Array;a.members.forEach(A=>{if(!sr(A))return;let R=A.modifiers??[],X=Array.from(R).find(g=>fr(g));if(X){let g=ht(A),D=g&&v(g)?g.text:void 0;if(D){let G=xr(D,X);G&&k.push(G)}return}let Q=Array.from(R).find(g=>ur(g));if(Q){let g=ht(A),D=g&&v(g)?g.text:void 0;if(D){let G=hr(D,Q);G&&I.push(G)}}}),s={type:"component",className:c,selectors:E,properties:k,events:I}}}),s}catch(o){console.error(`Failed to extract component metadata from ${e}:`,o);return}}function mr(e,t){if(e.startsWith(".")){let r=or(t,e);if(he(`${r}.ts`))return r+".ts";if(he(`${r}/index.ts`))return`${r}/index.ts`;if(he(r))return r}}function lr(e){if(e.kind!==Ce.Decorator)return!1;let t=q(e.expression)?e.expression.expression:e.expression;return v(t)&&t.text==="WebComponent"}function fr(e){if(e.kind!==Ce.Decorator)return!1;let t=e.expression;return q(t)?v(t.expression)&&t.expression.text==="Property":Ct(t)?v(t.expression)&&t.expression.text==="Property"&&v(t.name)&&t.name.text==="required":v(t)&&t.text==="Property"}function ur(e){if(e.kind!==Ce.Decorator)return!1;let t=q(e.expression)?e.expression.expression:e.expression;return v(t)&&t.text==="Event"}function dr(e){try{let t=e.expression;if(!q(t))return[];let r=t.arguments;if(r.length===0)return[];let o=r[0];if(!o||!Et(o))return[];let n=Array.from(o.properties).find(i=>kt(i)&&v(i.name)&&i.name.text==="selector");return Tr(n.initializer)}catch{return[]}}function Tr(e){return Ee(e)?[e.text]:ar(e)?e.elements?.filter(t=>Ee(t)).map(t=>t.text):[]}function xr(e,t){let r={name:e,required:!1},o=t.expression;if(Ct(o)&&v(o.name)&&o.name.text==="required"&&(r.required=!0),q(o)){let n=o.arguments;if(n.length){let i=n[0];if(Et(i)){let s=i.properties?.find(a=>kt(a)&&v(a.name)&&a.name.text==="alias");s&&Ee(s.initializer)&&(r.alias=s.initializer.text)}}}return r}function hr(e,t){return{name:e}}var se=class{constructor(t){this._ast=t}_ast;_context=new B;_states={1:xe,2:xe,0:mt,3:ft,6:lt,7:xt,9:dt};async populateImportMetadata(t){let r=this._ast.filter(o=>o.type===9);await Promise.all(r.flatMap(o=>o.specifiers.filter(({imported:n})=>n!=="*").map(async({imported:n,local:i})=>{let s=n==="default"?i:n,a=await Nt(o.path,s,t);a&&this._context.addImport(a)})))}async generate(t){await this.populateImportMetadata(t);let r=this._ast.flatMap(o=>this._processNode(o,this._context));return["function typeCheck() {",...Er(r),"}"].join(`
|
|
15
|
+
`)}_processNode=(t,r)=>{let o=this._states[t.type];if(!o)throw new Error(`[Type Checker] No transition function for token type ${h[t.type]}`);return o(t,this._processNode,r)}};async function Ws(e,t,r){let o=new oe(e).tokenize(),n=new ie(o).parse();return{javascript:new z(n).generate(r),typescript:await new se(n).generate(t)}}export{Ws as compile};
|
package/package.json
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.32",
|
|
4
4
|
"description": "A library for transpiling Xaendar Templates into JavaScript code",
|
|
5
|
-
"
|
|
5
|
+
"author": "Kaitenjo",
|
|
6
|
+
"license": "MIT",
|
|
6
7
|
"type": "module",
|
|
7
|
-
"main": "./dist/xaendar-compiler.es.js",
|
|
8
|
-
"module": "./dist/xaendar-compiler.es.js",
|
|
9
|
-
"types": "./dist/xaendar-compiler.es.d.ts",
|
|
10
8
|
"exports": {
|
|
11
9
|
".": {
|
|
12
|
-
"import":
|
|
13
|
-
|
|
14
|
-
"default": "./dist/xaendar-compiler.es.js"
|
|
15
|
-
}
|
|
10
|
+
"import": "./dist/compiler.js",
|
|
11
|
+
"require": "./dist/compiler.js"
|
|
16
12
|
}
|
|
17
13
|
},
|
|
14
|
+
"main": "./dist/compiler.js",
|
|
18
15
|
"dependencies": {
|
|
19
|
-
"@xaendar/common": "0.7.
|
|
20
|
-
"@xaendar/types": "0.7.
|
|
16
|
+
"@xaendar/common": "0.7.32",
|
|
17
|
+
"@xaendar/types": "0.7.32",
|
|
21
18
|
"typescript": "^6.0.3"
|
|
22
19
|
}
|
|
23
20
|
}
|
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compiles a template string into a Javascript render function body.
|
|
3
|
-
*
|
|
4
|
-
* Runs the three-stage pipeline:
|
|
5
|
-
* 1. **Lexer** — tokenises the raw template text.
|
|
6
|
-
* 2. **Parser** — transforms the token stream into an AST.
|
|
7
|
-
* 3. **Render generator** — emits Javascript source lines from the AST.
|
|
8
|
-
*
|
|
9
|
-
* @param input - The raw HTML-like template source to compile.
|
|
10
|
-
* @param cssVariableName - Optional name of the CSS variable to inject
|
|
11
|
-
* into the generated `adoptedStyleSheets` assignment.
|
|
12
|
-
* @returns A string containing the compiled Javascript render method body.
|
|
13
|
-
*/
|
|
14
|
-
export declare function compile(input: string, cssVariableName?: string): {
|
|
15
|
-
javascript: string;
|
|
16
|
-
typescript: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @fileoverview CompilerHost interface — the contract between the compiler and the environment it runs in.
|
|
21
|
-
*
|
|
22
|
-
* The compiler never accesses the filesystem, network, or any external resource directly.
|
|
23
|
-
* All I/O is delegated to the CompilerHost, allowing the same compiler core to run in
|
|
24
|
-
* different environments by swapping the host implementation:
|
|
25
|
-
*
|
|
26
|
-
* - **Node.js** (`build-tools`, `cli`) — reads and writes real files on disk
|
|
27
|
-
* - **Editor** (`language-tools`) — reads live document content from the editor buffer,
|
|
28
|
-
* which may differ from the file on disk when unsaved changes are present
|
|
29
|
-
* - **Tests** — uses in-memory virtual files without touching the real filesystem
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* // Minimal Node.js implementation
|
|
33
|
-
* import * as fs from 'node:fs';
|
|
34
|
-
* import * as path from 'node:path';
|
|
35
|
-
*
|
|
36
|
-
* class NodeCompilerHost implements CompilerHost {
|
|
37
|
-
* readFile(filePath: string) {
|
|
38
|
-
* try { return fs.readFileSync(filePath, 'utf8'); }
|
|
39
|
-
* catch { return undefined; }
|
|
40
|
-
* }
|
|
41
|
-
* fileExists(filePath: string) { return fs.existsSync(filePath); }
|
|
42
|
-
* resolvePath(from: string, to: string) { return path.resolve(path.dirname(from), to); }
|
|
43
|
-
* getDirectoryEntries(dirPath: string) { return fs.readdirSync(dirPath); }
|
|
44
|
-
* isDirectory(filePath: string) { return fs.statSync(filePath).isDirectory(); }
|
|
45
|
-
* getRealPath(filePath: string) { return fs.realpathSync(filePath); }
|
|
46
|
-
* getCurrentDirectory() { return process.cwd(); }
|
|
47
|
-
* }
|
|
48
|
-
*/
|
|
49
|
-
/**
|
|
50
|
-
* The contract between the compiler and the filesystem environment it runs in.
|
|
51
|
-
*
|
|
52
|
-
* The compiler uses this host for all I/O operations. It never accesses the filesystem,
|
|
53
|
-
* the network, or any other external resource directly. This makes it possible to use
|
|
54
|
-
* the same compiler in different environments:
|
|
55
|
-
*
|
|
56
|
-
* - **Node.js** (`build-tools`, `cli`) — reads and writes real files on disk
|
|
57
|
-
* - **Editor** (`language-tools`) — reads live document content from open editor buffers,
|
|
58
|
-
* which may differ from the file on disk when unsaved changes are present
|
|
59
|
-
* - **Tests** — uses in-memory virtual files without touching the real filesystem
|
|
60
|
-
*
|
|
61
|
-
* Implementations should be **synchronous** wherever possible to ensure compatibility
|
|
62
|
-
* with the TypeScript compiler host API, which does not support async operations
|
|
63
|
-
* in its core methods.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* // Typical usage — the compiler receives the host as a dependency
|
|
67
|
-
* const host: CompilerHost = new NodeCompilerHost();
|
|
68
|
-
* const compiler = new Compiler(host);
|
|
69
|
-
* const result = compiler.compile('/src/app.component.html');
|
|
70
|
-
*/
|
|
71
|
-
export declare interface CompilerHost {
|
|
72
|
-
/**
|
|
73
|
-
* Checks whether a file exists and can be read.
|
|
74
|
-
*
|
|
75
|
-
* Used by the compiler to:
|
|
76
|
-
* - Verify that a template associated with a component exists before attempting
|
|
77
|
-
* to read it (e.g. `app.component.html` paired with `app.component.ts`)
|
|
78
|
-
* - Resolve optional imports
|
|
79
|
-
* - Decide which resolution strategy to apply
|
|
80
|
-
*
|
|
81
|
-
* In environments with a virtual file system (such as `language-tools`),
|
|
82
|
-
* this method must return `true` for virtual files that do not exist on disk,
|
|
83
|
-
* such as Template Check Blocks (TCBs) generated in memory.
|
|
84
|
-
*
|
|
85
|
-
* @param filePath - Absolute path of the file whose existence to check.
|
|
86
|
-
* @returns `true` if the file exists and is accessible, `false` otherwise.
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* const templatePath = host.resolvePath(componentPath, './app.component.html');
|
|
90
|
-
* if (host.fileExists(templatePath)) {
|
|
91
|
-
* const template = host.readFile(templatePath);
|
|
92
|
-
* }
|
|
93
|
-
*/
|
|
94
|
-
fileExists(filePath: string): boolean;
|
|
95
|
-
/**
|
|
96
|
-
* Returns the current working directory of the process.
|
|
97
|
-
*
|
|
98
|
-
* Used by the compiler as the base for resolving relative paths that have
|
|
99
|
-
* no associated source file — for example, paths specified in the project
|
|
100
|
-
* configuration or passed as CLI arguments.
|
|
101
|
-
*
|
|
102
|
-
* In an editor environment, this should return the root of the open workspace,
|
|
103
|
-
* not the directory of the editor process itself.
|
|
104
|
-
*
|
|
105
|
-
* @returns The absolute path of the current working directory.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* // Resolves a relative path from the project configuration
|
|
109
|
-
* const configRelativePath = './src';
|
|
110
|
-
* const absolutePath = host.resolvePath(
|
|
111
|
-
* host.getCurrentDirectory() + '/placeholder',
|
|
112
|
-
* configRelativePath
|
|
113
|
-
* );
|
|
114
|
-
*/
|
|
115
|
-
getCurrentDirectory(): string;
|
|
116
|
-
/**
|
|
117
|
-
* Returns the list of files and subdirectories inside a directory.
|
|
118
|
-
*
|
|
119
|
-
* Used by the compiler during the discovery phase — when it needs to find
|
|
120
|
-
* all components in the project without them being explicitly listed, or
|
|
121
|
-
* when it needs to resolve glob patterns in the project configuration.
|
|
122
|
-
*
|
|
123
|
-
* Returns only entry names, not absolute paths. The caller is responsible
|
|
124
|
-
* for combining the results with `dirPath` via `resolvePath` to obtain
|
|
125
|
-
* absolute paths.
|
|
126
|
-
*
|
|
127
|
-
* @param dirPath - Absolute path of the directory to read.
|
|
128
|
-
* @returns An array of file and directory names inside `dirPath`.
|
|
129
|
-
* Returns an empty array if the directory is empty or does not exist.
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* const entries = host.getDirectoryEntries('/src/components');
|
|
133
|
-
* // → ['button', 'input', 'modal']
|
|
134
|
-
*
|
|
135
|
-
* const componentFiles = entries
|
|
136
|
-
* .map(entry => host.resolvePath('/src/components', entry))
|
|
137
|
-
* .filter(p => host.fileExists(p) && p.endsWith('.ts'));
|
|
138
|
-
*/
|
|
139
|
-
getDirectoryEntries(dirPath: string): string[];
|
|
140
|
-
/**
|
|
141
|
-
* Resolves symlinks and returns the real physical path of a file.
|
|
142
|
-
*
|
|
143
|
-
* Used by the compiler to normalise paths before using them as keys in
|
|
144
|
-
* internal caches. Two different paths pointing to the same physical file
|
|
145
|
-
* (one through a symlink) must produce the same compiled output and must
|
|
146
|
-
* not generate duplicates in the module graph.
|
|
147
|
-
*
|
|
148
|
-
* Particularly important in monorepos using workspace links (npm/yarn/pnpm),
|
|
149
|
-
* where local packages are often symlinked inside `node_modules`.
|
|
150
|
-
*
|
|
151
|
-
* @param filePath - Absolute path, potentially containing symlinks.
|
|
152
|
-
* @returns The real absolute path with all symlinks resolved.
|
|
153
|
-
* If the path does not exist or cannot be resolved, returns `filePath` unchanged.
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* // In a pnpm monorepo:
|
|
157
|
-
* // /app/node_modules/@my-lib/core → /packages/core/src
|
|
158
|
-
* host.getRealPath('/app/node_modules/@my-lib/core/index.ts');
|
|
159
|
-
* // → '/packages/core/src/index.ts'
|
|
160
|
-
*/
|
|
161
|
-
getRealPath(filePath: string): string;
|
|
162
|
-
/**
|
|
163
|
-
* Checks whether the given path refers to a directory.
|
|
164
|
-
*
|
|
165
|
-
* Used together with `getDirectoryEntries` to distinguish files from
|
|
166
|
-
* subdirectories when recursing through the filesystem. Also needed to
|
|
167
|
-
* validate output paths before writing files.
|
|
168
|
-
*
|
|
169
|
-
* @param filePath - Absolute path to check.
|
|
170
|
-
* @returns `true` if the path exists and is a directory, `false` in all
|
|
171
|
-
* other cases (regular file, symlink to a file, non-existent path).
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* const entries = host.getDirectoryEntries('/src');
|
|
175
|
-
* for (const entry of entries) {
|
|
176
|
-
* const fullPath = host.resolvePath('/src', entry);
|
|
177
|
-
* if (host.isDirectory(fullPath)) {
|
|
178
|
-
* // recurse into subdirectory
|
|
179
|
-
* }
|
|
180
|
-
* }
|
|
181
|
-
*/
|
|
182
|
-
isDirectory(filePath: string): boolean;
|
|
183
|
-
/**
|
|
184
|
-
* Reads the content of a file as a UTF-8 string.
|
|
185
|
-
*
|
|
186
|
-
* The compiler calls this method to read:
|
|
187
|
-
* - Template files (`.html` files containing the custom DSL)
|
|
188
|
-
* - TypeScript source files (`.ts`) when needed for analysis
|
|
189
|
-
* - Project configuration files
|
|
190
|
-
*
|
|
191
|
-
* Returns `undefined` instead of throwing when the file does not exist or
|
|
192
|
-
* cannot be read. The compiler handles the `undefined` case by emitting
|
|
193
|
-
* an appropriate diagnostic.
|
|
194
|
-
*
|
|
195
|
-
* In an editor environment, this method must return the content currently
|
|
196
|
-
* held in the **editor buffer**, not the content on disk. This ensures the
|
|
197
|
-
* compiler always operates on the most up-to-date code, even when unsaved
|
|
198
|
-
* changes are present.
|
|
199
|
-
*
|
|
200
|
-
* @param filePath - Absolute path of the file to read.
|
|
201
|
-
* @returns The file content as a string, or `undefined` if the file does
|
|
202
|
-
* not exist or cannot be read.
|
|
203
|
-
*
|
|
204
|
-
* @example
|
|
205
|
-
* const content = host.readFile('/src/app.component.html');
|
|
206
|
-
* if (content === undefined) {
|
|
207
|
-
* // file not found — the compiler will emit a diagnostic
|
|
208
|
-
* }
|
|
209
|
-
*/
|
|
210
|
-
readFile(filePath: string): string | undefined;
|
|
211
|
-
/**
|
|
212
|
-
* Resolves a path relative to the source file that contains the reference.
|
|
213
|
-
*
|
|
214
|
-
* The compiler calls this method whenever it needs to turn a relative path
|
|
215
|
-
* (such as `./app.component.html` inside a `@Component` decorator) into an
|
|
216
|
-
* absolute path suitable for passing to `readFile` and `fileExists`.
|
|
217
|
-
*
|
|
218
|
-
* The default implementation should behave like
|
|
219
|
-
* `path.resolve(path.dirname(from), to)` in Node.js, but can be overridden
|
|
220
|
-
* to handle path aliases, `tsconfig.json` path mappings, or custom project
|
|
221
|
-
* conventions.
|
|
222
|
-
*
|
|
223
|
-
* @param from - Absolute path of the source file that contains the reference.
|
|
224
|
-
* Typically the `.ts` file of the component.
|
|
225
|
-
* @param to - Relative or absolute path to resolve. May be relative
|
|
226
|
-
* (`./template.html`), aliased (`@components/button.html`), or already absolute.
|
|
227
|
-
* @returns The resolved absolute path of the target file.
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* // from: '/src/features/user/user.component.ts'
|
|
231
|
-
* // to: './user.component.html'
|
|
232
|
-
* // → '/src/features/user/user.component.html'
|
|
233
|
-
* const templatePath = host.resolvePath(
|
|
234
|
-
* '/src/features/user/user.component.ts',
|
|
235
|
-
* './user.component.html'
|
|
236
|
-
* );
|
|
237
|
-
*/
|
|
238
|
-
resolvePath(from: string, to: string): string;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export { }
|