@jay-framework/compiler-jay-html 0.19.6 → 0.19.8
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/index.d.cts +8 -1
- package/dist/index.js +123 -8
- package/package.json +9 -9
package/dist/index.d.cts
CHANGED
|
@@ -180,6 +180,12 @@ interface JayHtmlHeadLink {
|
|
|
180
180
|
href: string;
|
|
181
181
|
attributes: Record<string, string>;
|
|
182
182
|
}
|
|
183
|
+
interface JayHtmlScript {
|
|
184
|
+
src?: string;
|
|
185
|
+
inline?: string;
|
|
186
|
+
attributes: Record<string, string>;
|
|
187
|
+
position: 'head' | 'body';
|
|
188
|
+
}
|
|
183
189
|
interface JayHtmlSourceFile extends CompilerSourceFile {
|
|
184
190
|
format: SourceFileFormat.JayHtml;
|
|
185
191
|
baseElementName: string;
|
|
@@ -214,6 +220,7 @@ interface JayHtmlSourceFile extends CompilerSourceFile {
|
|
|
214
220
|
*/
|
|
215
221
|
clientTrackByMap?: Record<string, string>;
|
|
216
222
|
headMeta?: JayHtmlHeadMeta;
|
|
223
|
+
scripts?: JayHtmlScript[];
|
|
217
224
|
}
|
|
218
225
|
|
|
219
226
|
declare function parseTemplateParts(value: string): TemplatePart[];
|
|
@@ -601,4 +608,4 @@ declare function resolveHeadlessInstances(preRenderedJayHtml: string, instanceDa
|
|
|
601
608
|
*/
|
|
602
609
|
declare function hasSlowPhaseProperties(contract: Contract | undefined): boolean;
|
|
603
610
|
|
|
604
|
-
export { type ActionDefinition, type AssignCoordinatesOptions, type AssignCoordinatesResult, type Contract, type ContractImportInfo, type ContractParam, type ContractParamKind, type ContractProp, type ContractResolver, type ContractTag, ContractTagType, type DiscoveredHeadlessInstance, type EnumToImport, type ForEachHeadlessInstance, type HeadlessContractInfo, type HeadlessInstanceDiscoveryResult, type HeadlessInstanceResolvedData, JAY_IMPORT_RESOLVER, type JayContractImportLink, type JayHtmlSourceFile, type JayImportResolver, type PhaseViewStates, type RenderingPhase, type ServerElementOptions, type SlowRenderInput, type SlowRenderOutput, assignCoordinates, assignCoordinatesToJayHtml, buildInstanceCoordinateKey, compileAction, compileContract, contractToAllPhaseViewStates, contractToImportsViewStateAndRefs, contractToPhaseViewState, createPhaseContract, defaultContractResolver, discoverHeadlessInstances, filterTagsByPhase, generateElementBridgeFile, generateElementDefinitionFile, generateElementFile, generateElementFileReactTarget, generateElementHydrateFile, generateSandboxRootFile, generateServerElementFile, generateTypes, getEffectivePhase, getJayHtmlImports, getLinkedContractDir, hasSlowPhaseProperties, htmlElementTagNameMap, injectHeadfullFSTemplates, isTagInPhase, loadLinkedContract, parseAction, parseContract, parseEnumValues, parseIsEnum, parseJayFile, parseTemplateParts, renderRefsType, resolveHeadlessInstances, slowRenderTransform, validateContractPhases };
|
|
611
|
+
export { type ActionDefinition, type AssignCoordinatesOptions, type AssignCoordinatesResult, type Contract, type ContractImportInfo, type ContractParam, type ContractParamKind, type ContractProp, type ContractResolver, type ContractTag, ContractTagType, type DiscoveredHeadlessInstance, type EnumToImport, type ForEachHeadlessInstance, type HeadlessContractInfo, type HeadlessInstanceDiscoveryResult, type HeadlessInstanceResolvedData, JAY_IMPORT_RESOLVER, type JayContractImportLink, type JayHtmlScript, type JayHtmlSourceFile, type JayImportResolver, type PhaseViewStates, type RenderingPhase, type ServerElementOptions, type SlowRenderInput, type SlowRenderOutput, assignCoordinates, assignCoordinatesToJayHtml, buildInstanceCoordinateKey, compileAction, compileContract, contractToAllPhaseViewStates, contractToImportsViewStateAndRefs, contractToPhaseViewState, createPhaseContract, defaultContractResolver, discoverHeadlessInstances, filterTagsByPhase, generateElementBridgeFile, generateElementDefinitionFile, generateElementFile, generateElementFileReactTarget, generateElementHydrateFile, generateSandboxRootFile, generateServerElementFile, generateTypes, getEffectivePhase, getJayHtmlImports, getLinkedContractDir, hasSlowPhaseProperties, htmlElementTagNameMap, injectHeadfullFSTemplates, isTagInPhase, loadLinkedContract, parseAction, parseContract, parseEnumValues, parseIsEnum, parseJayFile, parseTemplateParts, renderRefsType, resolveHeadlessInstances, slowRenderTransform, validateContractPhases };
|
package/dist/index.js
CHANGED
|
@@ -14657,16 +14657,52 @@ function mergeContractStubRefs(templateRefs, contractRefs) {
|
|
|
14657
14657
|
);
|
|
14658
14658
|
}
|
|
14659
14659
|
}
|
|
14660
|
-
|
|
14660
|
+
const mergedChildren = { ...templateRefs.children };
|
|
14661
|
+
for (const [childName, contractChild] of Object.entries(contractRefs.children)) {
|
|
14662
|
+
if (mergedChildren[childName]) {
|
|
14663
|
+
mergedChildren[childName] = mergeContractStubRefs(
|
|
14664
|
+
mergedChildren[childName],
|
|
14665
|
+
contractChild
|
|
14666
|
+
);
|
|
14667
|
+
} else {
|
|
14668
|
+
mergedChildren[childName] = markAllRefsAsStubs(contractChild);
|
|
14669
|
+
}
|
|
14670
|
+
}
|
|
14671
|
+
const childrenChanged = Object.keys(mergedChildren).length !== Object.keys(templateRefs.children).length || Object.keys(mergedChildren).some((k) => mergedChildren[k] !== templateRefs.children[k]);
|
|
14672
|
+
if (stubRefs.length === 0 && !childrenChanged)
|
|
14661
14673
|
return templateRefs;
|
|
14662
14674
|
return mkRefsTree(
|
|
14663
14675
|
[...templateRefs.refs, ...stubRefs],
|
|
14664
|
-
|
|
14676
|
+
mergedChildren,
|
|
14665
14677
|
templateRefs.repeated,
|
|
14666
14678
|
templateRefs.imported?.refsTypeName,
|
|
14667
14679
|
templateRefs.imported?.repeatedRefsTypeName
|
|
14668
14680
|
);
|
|
14669
14681
|
}
|
|
14682
|
+
function markAllRefsAsStubs(tree) {
|
|
14683
|
+
const stubbedRefs = tree.refs.map(
|
|
14684
|
+
(ref) => mkRef(
|
|
14685
|
+
ref.originalName,
|
|
14686
|
+
ref.originalName,
|
|
14687
|
+
camelCase(`ref ${ref.originalName}`),
|
|
14688
|
+
ref.repeated,
|
|
14689
|
+
true,
|
|
14690
|
+
ref.viewStateType,
|
|
14691
|
+
ref.elementType
|
|
14692
|
+
)
|
|
14693
|
+
);
|
|
14694
|
+
const stubbedChildren = {};
|
|
14695
|
+
for (const [name, child] of Object.entries(tree.children)) {
|
|
14696
|
+
stubbedChildren[name] = markAllRefsAsStubs(child);
|
|
14697
|
+
}
|
|
14698
|
+
return mkRefsTree(
|
|
14699
|
+
stubbedRefs,
|
|
14700
|
+
stubbedChildren,
|
|
14701
|
+
tree.repeated,
|
|
14702
|
+
tree.imported?.refsTypeName,
|
|
14703
|
+
tree.imported?.repeatedRefsTypeName
|
|
14704
|
+
);
|
|
14705
|
+
}
|
|
14670
14706
|
const COORD_ATTR = "jay-coordinate-base";
|
|
14671
14707
|
function expandContractType(renderedElement, baseName) {
|
|
14672
14708
|
const contractPattern = new RegExp(
|
|
@@ -18264,7 +18300,11 @@ function parseHeadfullImports(elements, validations, filePath, options, importRe
|
|
|
18264
18300
|
const exportedTypes = importResolver.analyzeExportedTypes(importedFile, options);
|
|
18265
18301
|
for (const name of names) {
|
|
18266
18302
|
const exportedType = exportedTypes.find((_) => _.name === name.name);
|
|
18267
|
-
if (exportedType && exportedType
|
|
18303
|
+
if (exportedType instanceof JayComponentType && exportedType.fullStack) {
|
|
18304
|
+
validations.push(
|
|
18305
|
+
`${name.name} from ${module} is a full-stack component (makeJayStackComponent). Create a .jay-contract file for the component and add a contract attribute to the import`
|
|
18306
|
+
);
|
|
18307
|
+
} else if (exportedType && exportedType !== JayUnknown)
|
|
18268
18308
|
name.type = new JayImportedType(name.as ? name.as : name.name, exportedType);
|
|
18269
18309
|
else if (exportedType === JayUnknown)
|
|
18270
18310
|
validations.push(
|
|
@@ -18746,6 +18786,49 @@ async function parseHeadfullFSImports(elements, validations, filePath, importRes
|
|
|
18746
18786
|
function normalizeFilename(filename) {
|
|
18747
18787
|
return filename.replace(".jay-html", "");
|
|
18748
18788
|
}
|
|
18789
|
+
function isLocalSrc(src) {
|
|
18790
|
+
return src.startsWith("./") || src.startsWith("../") || !src.includes("://") && !src.startsWith("//");
|
|
18791
|
+
}
|
|
18792
|
+
function validateAndCollectScripts(root, validations) {
|
|
18793
|
+
const scripts = [];
|
|
18794
|
+
const allScripts = root.querySelectorAll("script");
|
|
18795
|
+
for (const script of allScripts) {
|
|
18796
|
+
const type2 = script.getAttribute("type");
|
|
18797
|
+
if (type2?.startsWith("application/jay-"))
|
|
18798
|
+
continue;
|
|
18799
|
+
const jayScript = script.getAttribute("jay-script");
|
|
18800
|
+
const src = script.getAttribute("src");
|
|
18801
|
+
const inline = script.textContent?.trim();
|
|
18802
|
+
const isInHead = !!script.closest("head");
|
|
18803
|
+
if (src && isLocalSrc(src)) {
|
|
18804
|
+
validations.push(
|
|
18805
|
+
`Local script imports are not supported in jay-html. Move the script logic into page.ts with makeJayStackComponent. See designer/script-tags.md.`
|
|
18806
|
+
);
|
|
18807
|
+
continue;
|
|
18808
|
+
}
|
|
18809
|
+
if (jayScript === "allow") {
|
|
18810
|
+
const attributes2 = { ...script.attributes };
|
|
18811
|
+
delete attributes2["jay-script"];
|
|
18812
|
+
delete attributes2["src"];
|
|
18813
|
+
if (src) {
|
|
18814
|
+
scripts.push({ src, attributes: attributes2, position: isInHead ? "head" : "body" });
|
|
18815
|
+
} else if (inline) {
|
|
18816
|
+
scripts.push({ inline, attributes: attributes2, position: isInHead ? "head" : "body" });
|
|
18817
|
+
}
|
|
18818
|
+
continue;
|
|
18819
|
+
}
|
|
18820
|
+
if (src) {
|
|
18821
|
+
validations.push(
|
|
18822
|
+
`External scripts should be explicitly marked. If this script is required (e.g., analytics or tag manager), add jay-script="allow". Prefer page.ts for page behavior. See designer/script-tags.md.`
|
|
18823
|
+
);
|
|
18824
|
+
} else if (inline) {
|
|
18825
|
+
validations.push(
|
|
18826
|
+
`Inline scripts are not supported in jay-html. Use page.ts with makeJayStackComponent for page behavior. If this is a third-party script that must be included as-is, add jay-script="allow". See designer/script-tags.md.`
|
|
18827
|
+
);
|
|
18828
|
+
}
|
|
18829
|
+
}
|
|
18830
|
+
return scripts;
|
|
18831
|
+
}
|
|
18749
18832
|
function parseHeadLinks(root, excludeCssLinks = false) {
|
|
18750
18833
|
const allLinks = root.querySelectorAll("head link");
|
|
18751
18834
|
return allLinks.filter((link) => {
|
|
@@ -18945,6 +19028,7 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
|
|
|
18945
19028
|
const excludeCssLinks = !!filePath;
|
|
18946
19029
|
const headLinks = parseHeadLinks(root, excludeCssLinks);
|
|
18947
19030
|
const headMeta = parseHeadMeta(root);
|
|
19031
|
+
const scripts = validateAndCollectScripts(root, validations);
|
|
18948
19032
|
validations.push(...cssResult.validations);
|
|
18949
19033
|
if (validations.length > 0)
|
|
18950
19034
|
return new WithValidations(void 0, validations);
|
|
@@ -18980,7 +19064,8 @@ async function parseJayFile(html2, filename, filePath, options, linkedContractRe
|
|
|
18980
19064
|
hasInlineData: jayYaml.hasInlineData,
|
|
18981
19065
|
serverTrackByMap: Object.keys(serverTrackByMap).length > 0 ? serverTrackByMap : void 0,
|
|
18982
19066
|
clientTrackByMap: Object.keys(clientTrackByMap).length > 0 ? clientTrackByMap : void 0,
|
|
18983
|
-
headMeta
|
|
19067
|
+
headMeta,
|
|
19068
|
+
scripts: scripts.length > 0 ? scripts : void 0
|
|
18984
19069
|
},
|
|
18985
19070
|
validations
|
|
18986
19071
|
);
|
|
@@ -19872,6 +19957,11 @@ ${context.indent.firstLine} ${createBody})`,
|
|
|
19872
19957
|
childContent.refs
|
|
19873
19958
|
);
|
|
19874
19959
|
}
|
|
19960
|
+
if (isConditional(element) && isForEach(element)) {
|
|
19961
|
+
return new RenderFragment("", Imports.none(), [
|
|
19962
|
+
`"if" and "forEach" cannot be on the same element. Wrap the forEach in a separate element: <div if="..."><div forEach="...">...</div></div>`
|
|
19963
|
+
]);
|
|
19964
|
+
}
|
|
19875
19965
|
if (isConditional(element) && context.interactivePaths.size > 0) {
|
|
19876
19966
|
const condition = element.getAttribute("if");
|
|
19877
19967
|
const viewStateVars = new Variables(
|
|
@@ -20412,7 +20502,21 @@ function renderHydrateElementContent(element, context, renderContext, coordinate
|
|
|
20412
20502
|
childRefs.push(frag.refs);
|
|
20413
20503
|
}
|
|
20414
20504
|
} else {
|
|
20415
|
-
const
|
|
20505
|
+
const htmlChild2 = child;
|
|
20506
|
+
const isComponent = getComponentName(
|
|
20507
|
+
htmlChild2.rawTagName,
|
|
20508
|
+
context.importedSymbols,
|
|
20509
|
+
context.headlessContractNames
|
|
20510
|
+
) !== null;
|
|
20511
|
+
const isNonInteractiveConditional = isConditional(htmlChild2) && !conditionIsInteractive(htmlChild2.getAttribute("if"), context.interactivePaths);
|
|
20512
|
+
const needsWrap = !isComponent && !isNonInteractiveConditional;
|
|
20513
|
+
const frag = needsWrap ? renderHydrateElementContent(
|
|
20514
|
+
htmlChild2,
|
|
20515
|
+
context,
|
|
20516
|
+
buildRenderContext(context),
|
|
20517
|
+
null,
|
|
20518
|
+
true
|
|
20519
|
+
) : renderHydrateNode(child, context);
|
|
20416
20520
|
if (frag.rendered.trim()) {
|
|
20417
20521
|
childParts.push(frag.rendered);
|
|
20418
20522
|
childImports = childImports.plus(frag.imports);
|
|
@@ -21296,6 +21400,10 @@ const ${componentSymbol} = makeHeadlessInstanceComponent(
|
|
|
21296
21400
|
mkRefsTree([], {})
|
|
21297
21401
|
);
|
|
21298
21402
|
}
|
|
21403
|
+
} else if (isConditional(htmlElement) && isForEach(htmlElement)) {
|
|
21404
|
+
return new RenderFragment("", Imports.none(), [
|
|
21405
|
+
`"if" and "forEach" cannot be on the same element. Wrap the forEach in a separate element: <div if="..."><div forEach="...">...</div></div>`
|
|
21406
|
+
]);
|
|
21299
21407
|
} else if (isConditional(htmlElement)) {
|
|
21300
21408
|
let condition = htmlElement.getAttribute("if");
|
|
21301
21409
|
let childElement = renderHtmlElement(htmlElement, {
|
|
@@ -22401,6 +22509,11 @@ function renderServerElement(element, context) {
|
|
|
22401
22509
|
if (componentMatch !== null && componentMatch.kind === "headless-instance") {
|
|
22402
22510
|
return renderServerHeadlessInstance(element, context, componentMatch.name);
|
|
22403
22511
|
}
|
|
22512
|
+
if (isConditional(element) && isForEach(element)) {
|
|
22513
|
+
return new RenderFragment("", Imports.none(), [
|
|
22514
|
+
`"if" and "forEach" cannot be on the same element. Wrap the forEach in a separate element: <div if="..."><div forEach="...">...</div></div>`
|
|
22515
|
+
]);
|
|
22516
|
+
}
|
|
22404
22517
|
if (isConditional(element)) {
|
|
22405
22518
|
const condition = element.getAttribute("if");
|
|
22406
22519
|
const renderedCondition = parseServerCondition(condition, variables);
|
|
@@ -22888,7 +23001,7 @@ function renderServerElementContent(element, context, options) {
|
|
|
22888
23001
|
}
|
|
22889
23002
|
}
|
|
22890
23003
|
const refName = element.attributes.ref ? camelCase(element.attributes.ref) : null;
|
|
22891
|
-
const needsCoordinate = options?.isRoot === true || isConditional(element) || dynamicTextFragment !== null || refName !== null || hasDynamicAttributeBindings(element, variables) || hasInteractiveChildElements(childNodes) || hasMixedContentDynamicTextInteractive(childNodes, context.interactivePaths);
|
|
23004
|
+
const needsCoordinate = options?.isRoot === true || isConditional(element) || dynamicTextFragment !== null || refName !== null || hasDynamicAttributeBindings(element, variables) || hasInteractiveChildElements(childNodes) || hasMixedContentDynamicTextInteractive(childNodes, context.interactivePaths) || context.parentHasInteractiveChildren;
|
|
22892
23005
|
const coordTemplate = needsCoordinate ? element.getAttribute(COORD_ATTR) : null;
|
|
22893
23006
|
const isVoid = voidElements.has(element.rawTagName.toLowerCase());
|
|
22894
23007
|
const closeTag = isVoid ? " />" : ">";
|
|
@@ -22926,7 +23039,8 @@ function renderServerElementContent(element, context, options) {
|
|
|
22926
23039
|
} else {
|
|
22927
23040
|
const childContext = {
|
|
22928
23041
|
...context,
|
|
22929
|
-
indent: new Indent(indent.curr + " ")
|
|
23042
|
+
indent: new Indent(indent.curr + " "),
|
|
23043
|
+
parentHasInteractiveChildren: hasInteractiveChildElements(childNodes)
|
|
22930
23044
|
};
|
|
22931
23045
|
const asyncGroups = collectAsyncGroups(childNodes);
|
|
22932
23046
|
const processedAsyncProps = /* @__PURE__ */ new Set();
|
|
@@ -23077,7 +23191,8 @@ function generateServerElementFile(jayFile, _options) {
|
|
|
23077
23191
|
headlessInstanceCounter: { count: 0 },
|
|
23078
23192
|
varMappings: {},
|
|
23079
23193
|
insideForEach: false,
|
|
23080
|
-
interactivePaths: buildInteractivePaths(jayFile.contract)
|
|
23194
|
+
interactivePaths: buildInteractivePaths(jayFile.contract),
|
|
23195
|
+
parentHasInteractiveChildren: false
|
|
23081
23196
|
};
|
|
23082
23197
|
const rendered = renderServerElementContent(rootElement.val, context, {
|
|
23083
23198
|
isRoot: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/compiler-jay-html",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
},
|
|
35
35
|
"author": "",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@jay-framework/compiler-analyze-exported-types": "^0.19.
|
|
38
|
-
"@jay-framework/compiler-shared": "^0.19.
|
|
39
|
-
"@jay-framework/component": "^0.19.
|
|
40
|
-
"@jay-framework/logger": "^0.19.
|
|
41
|
-
"@jay-framework/runtime": "^0.19.
|
|
42
|
-
"@jay-framework/secure": "^0.19.
|
|
37
|
+
"@jay-framework/compiler-analyze-exported-types": "^0.19.8",
|
|
38
|
+
"@jay-framework/compiler-shared": "^0.19.8",
|
|
39
|
+
"@jay-framework/component": "^0.19.8",
|
|
40
|
+
"@jay-framework/logger": "^0.19.8",
|
|
41
|
+
"@jay-framework/runtime": "^0.19.8",
|
|
42
|
+
"@jay-framework/secure": "^0.19.8",
|
|
43
43
|
"@types/js-yaml": "^4.0.9",
|
|
44
44
|
"change-case": "^4.1.2",
|
|
45
45
|
"he": "^1.2.0",
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@caiogondim/strip-margin": "^1.0.0",
|
|
55
|
-
"@jay-framework/4-react": "^0.19.
|
|
56
|
-
"@jay-framework/dev-environment": "^0.19.
|
|
55
|
+
"@jay-framework/4-react": "^0.19.8",
|
|
56
|
+
"@jay-framework/dev-environment": "^0.19.8",
|
|
57
57
|
"@testing-library/jest-dom": "^6.2.0",
|
|
58
58
|
"@types/js-beautify": "^1",
|
|
59
59
|
"@types/node": "^20.11.5",
|