@hyperframes/lint 0.8.207 → 0.8.208
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/browser.js +81 -1
- package/dist/index.js +81 -1
- package/package.json +2 -2
package/dist/browser.js
CHANGED
|
@@ -4117,6 +4117,23 @@ ${allInlineStyles}`.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
|
4117
4117
|
snippet: truncateSnippet(rootTag.raw)
|
|
4118
4118
|
}
|
|
4119
4119
|
];
|
|
4120
|
+
},
|
|
4121
|
+
// subcomposition_linked_style_names_root_id
|
|
4122
|
+
// The compiler flattens a sub-composition root into its host and rewrites inline <style>
|
|
4123
|
+
// selectors to match; a linked stylesheet is not rewritten, so `#root-id` in it matches nothing.
|
|
4124
|
+
({ styles, rootTag, options }) => {
|
|
4125
|
+
if (!options.isSubComposition || !rootTag) return [];
|
|
4126
|
+
const rootId = readAttr(rootTag.raw, "id");
|
|
4127
|
+
if (!rootId) return [];
|
|
4128
|
+
const escaped = rootId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4129
|
+
const names = new RegExp(`#${escaped}(?![\\w-])`);
|
|
4130
|
+
return styles.filter((style) => style.index === -1 && names.test(stripCssComments(style.content))).map((style) => ({
|
|
4131
|
+
code: "subcomposition_linked_style_names_root_id",
|
|
4132
|
+
severity: "warning",
|
|
4133
|
+
message: `The linked stylesheet "${style.rootRelativePath ?? style.file}" has a rule on #${rootId}, the id of this sub-composition's root. The root is merged into its host when the composition is compiled, so that selector matches nothing (the same rule in an inline <style> is rewritten and works).`,
|
|
4134
|
+
fixHint: `Move the #${rootId} rules into a <style> inside the <template>, where they are rewritten for the merged root, or select a child element of the root in the linked file instead of the root itself.`,
|
|
4135
|
+
snippet: truncateSnippet(style.content.slice(0, 120))
|
|
4136
|
+
}));
|
|
4120
4137
|
}
|
|
4121
4138
|
];
|
|
4122
4139
|
var CLIP_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "audio"]);
|
|
@@ -6872,6 +6889,68 @@ var shaderRules = [
|
|
|
6872
6889
|
})
|
|
6873
6890
|
];
|
|
6874
6891
|
|
|
6892
|
+
// src/rules/rootPaths.ts
|
|
6893
|
+
var URL_ATTRS = ["src", "href", "poster", "xlink:href"];
|
|
6894
|
+
var ROOT_PATH = /^\/(?!\/)/;
|
|
6895
|
+
var CSS_ROOT_URL = /\burl\(\s*["']?(\/(?!\/)[^"')\s]*)/g;
|
|
6896
|
+
var SCRIPT_ROOT_URL = /\b(?:fetch|new\s+URL)\(\s*(["'`])(\/(?!\/)[^"'`$]*)\1/g;
|
|
6897
|
+
function relativeForm(path, cssFile) {
|
|
6898
|
+
const depth = (cssFile ?? "").split("/").filter(Boolean).length - 1;
|
|
6899
|
+
return `${"../".repeat(Math.max(depth, 0))}${path.slice(1)}`;
|
|
6900
|
+
}
|
|
6901
|
+
function rootPathFinding(path, cssFile, snippet) {
|
|
6902
|
+
return {
|
|
6903
|
+
code: "root_path_missing_in_preview",
|
|
6904
|
+
severity: "warning",
|
|
6905
|
+
message: `"${path}" starts at the server's root. Render and snapshot serve the project there, but Studio's preview serves it under the project's own path, so the preview cannot find this file.`,
|
|
6906
|
+
fixHint: `Use "${relativeForm(path, cssFile)}" instead.`,
|
|
6907
|
+
snippet: truncateSnippet(snippet)
|
|
6908
|
+
};
|
|
6909
|
+
}
|
|
6910
|
+
function cssRootPaths(css, cssFile) {
|
|
6911
|
+
return [...css.matchAll(CSS_ROOT_URL)].map(
|
|
6912
|
+
(match) => rootPathFinding(match[1] ?? "", cssFile, match[0])
|
|
6913
|
+
);
|
|
6914
|
+
}
|
|
6915
|
+
function tagRootPaths(tag) {
|
|
6916
|
+
if (tag.name === "a" || tag.name === "base") return [];
|
|
6917
|
+
const paths = URL_ATTRS.map((attr) => readAttr(tag.raw, attr)?.trim() ?? "").filter(
|
|
6918
|
+
(value) => ROOT_PATH.test(value)
|
|
6919
|
+
);
|
|
6920
|
+
return [
|
|
6921
|
+
...paths.map((path) => rootPathFinding(path, void 0, tag.raw)),
|
|
6922
|
+
...cssRootPaths(readAttr(tag.raw, "style") ?? "")
|
|
6923
|
+
];
|
|
6924
|
+
}
|
|
6925
|
+
var scriptRootPaths = (script) => [...script.matchAll(SCRIPT_ROOT_URL)].map(
|
|
6926
|
+
(match) => rootPathFinding(match[2] ?? "", void 0, match[0])
|
|
6927
|
+
);
|
|
6928
|
+
function invalidImportMap(script) {
|
|
6929
|
+
if (!/\btype\s*=\s*["']?importmap\b/i.test(script.attrs)) return [];
|
|
6930
|
+
try {
|
|
6931
|
+
JSON.parse(script.content);
|
|
6932
|
+
return [];
|
|
6933
|
+
} catch (error) {
|
|
6934
|
+
return [
|
|
6935
|
+
{
|
|
6936
|
+
code: "import_map_invalid",
|
|
6937
|
+
severity: "warning",
|
|
6938
|
+
message: `This import map is not valid JSON (${error instanceof Error ? error.message : String(error)}). The browser ignores it, and preview cannot map root module paths ("/assets/x.js") to the project.`,
|
|
6939
|
+
fixHint: "Make the import map valid JSON: double-quoted keys and values, no trailing commas.",
|
|
6940
|
+
snippet: truncateSnippet(script.content)
|
|
6941
|
+
}
|
|
6942
|
+
];
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6945
|
+
var rootPathRules = [
|
|
6946
|
+
(ctx) => [
|
|
6947
|
+
...ctx.tags.flatMap(tagRootPaths),
|
|
6948
|
+
...ctx.styles.flatMap((style) => cssRootPaths(style.content, style.rootRelativePath)),
|
|
6949
|
+
...ctx.scripts.flatMap((script) => scriptRootPaths(script.content)),
|
|
6950
|
+
...ctx.scripts.flatMap(invalidImportMap)
|
|
6951
|
+
]
|
|
6952
|
+
];
|
|
6953
|
+
|
|
6875
6954
|
// src/hyperframeLinter.ts
|
|
6876
6955
|
var RULE_GROUPS = [
|
|
6877
6956
|
{ group: "core", rules: coreRules },
|
|
@@ -6884,7 +6963,8 @@ var RULE_GROUPS = [
|
|
|
6884
6963
|
{ group: "fonts", rules: fontRules },
|
|
6885
6964
|
{ group: "slideshow", rules: slideshowRules },
|
|
6886
6965
|
{ group: "structure", rules: structureRules },
|
|
6887
|
-
{ group: "shaders", rules: shaderRules }
|
|
6966
|
+
{ group: "shaders", rules: shaderRules },
|
|
6967
|
+
{ group: "rootPaths", rules: rootPathRules }
|
|
6888
6968
|
];
|
|
6889
6969
|
var LINT_RULE_COUNT = RULE_GROUPS.reduce((n, g) => n + g.rules.length, 0);
|
|
6890
6970
|
var LINT_RULE_GROUP_COUNTS = Object.fromEntries(
|
package/dist/index.js
CHANGED
|
@@ -4123,6 +4123,23 @@ ${allInlineStyles}`.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
|
4123
4123
|
snippet: truncateSnippet(rootTag.raw)
|
|
4124
4124
|
}
|
|
4125
4125
|
];
|
|
4126
|
+
},
|
|
4127
|
+
// subcomposition_linked_style_names_root_id
|
|
4128
|
+
// The compiler flattens a sub-composition root into its host and rewrites inline <style>
|
|
4129
|
+
// selectors to match; a linked stylesheet is not rewritten, so `#root-id` in it matches nothing.
|
|
4130
|
+
({ styles, rootTag, options }) => {
|
|
4131
|
+
if (!options.isSubComposition || !rootTag) return [];
|
|
4132
|
+
const rootId = readAttr(rootTag.raw, "id");
|
|
4133
|
+
if (!rootId) return [];
|
|
4134
|
+
const escaped = rootId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4135
|
+
const names = new RegExp(`#${escaped}(?![\\w-])`);
|
|
4136
|
+
return styles.filter((style) => style.index === -1 && names.test(stripCssComments(style.content))).map((style) => ({
|
|
4137
|
+
code: "subcomposition_linked_style_names_root_id",
|
|
4138
|
+
severity: "warning",
|
|
4139
|
+
message: `The linked stylesheet "${style.rootRelativePath ?? style.file}" has a rule on #${rootId}, the id of this sub-composition's root. The root is merged into its host when the composition is compiled, so that selector matches nothing (the same rule in an inline <style> is rewritten and works).`,
|
|
4140
|
+
fixHint: `Move the #${rootId} rules into a <style> inside the <template>, where they are rewritten for the merged root, or select a child element of the root in the linked file instead of the root itself.`,
|
|
4141
|
+
snippet: truncateSnippet(style.content.slice(0, 120))
|
|
4142
|
+
}));
|
|
4126
4143
|
}
|
|
4127
4144
|
];
|
|
4128
4145
|
var CLIP_MEDIA_TAGS = /* @__PURE__ */ new Set(["img", "video", "audio"]);
|
|
@@ -6878,6 +6895,68 @@ var shaderRules = [
|
|
|
6878
6895
|
})
|
|
6879
6896
|
];
|
|
6880
6897
|
|
|
6898
|
+
// src/rules/rootPaths.ts
|
|
6899
|
+
var URL_ATTRS = ["src", "href", "poster", "xlink:href"];
|
|
6900
|
+
var ROOT_PATH = /^\/(?!\/)/;
|
|
6901
|
+
var CSS_ROOT_URL = /\burl\(\s*["']?(\/(?!\/)[^"')\s]*)/g;
|
|
6902
|
+
var SCRIPT_ROOT_URL = /\b(?:fetch|new\s+URL)\(\s*(["'`])(\/(?!\/)[^"'`$]*)\1/g;
|
|
6903
|
+
function relativeForm(path, cssFile) {
|
|
6904
|
+
const depth = (cssFile ?? "").split("/").filter(Boolean).length - 1;
|
|
6905
|
+
return `${"../".repeat(Math.max(depth, 0))}${path.slice(1)}`;
|
|
6906
|
+
}
|
|
6907
|
+
function rootPathFinding(path, cssFile, snippet) {
|
|
6908
|
+
return {
|
|
6909
|
+
code: "root_path_missing_in_preview",
|
|
6910
|
+
severity: "warning",
|
|
6911
|
+
message: `"${path}" starts at the server's root. Render and snapshot serve the project there, but Studio's preview serves it under the project's own path, so the preview cannot find this file.`,
|
|
6912
|
+
fixHint: `Use "${relativeForm(path, cssFile)}" instead.`,
|
|
6913
|
+
snippet: truncateSnippet(snippet)
|
|
6914
|
+
};
|
|
6915
|
+
}
|
|
6916
|
+
function cssRootPaths(css, cssFile) {
|
|
6917
|
+
return [...css.matchAll(CSS_ROOT_URL)].map(
|
|
6918
|
+
(match) => rootPathFinding(match[1] ?? "", cssFile, match[0])
|
|
6919
|
+
);
|
|
6920
|
+
}
|
|
6921
|
+
function tagRootPaths(tag) {
|
|
6922
|
+
if (tag.name === "a" || tag.name === "base") return [];
|
|
6923
|
+
const paths = URL_ATTRS.map((attr) => readAttr(tag.raw, attr)?.trim() ?? "").filter(
|
|
6924
|
+
(value) => ROOT_PATH.test(value)
|
|
6925
|
+
);
|
|
6926
|
+
return [
|
|
6927
|
+
...paths.map((path) => rootPathFinding(path, void 0, tag.raw)),
|
|
6928
|
+
...cssRootPaths(readAttr(tag.raw, "style") ?? "")
|
|
6929
|
+
];
|
|
6930
|
+
}
|
|
6931
|
+
var scriptRootPaths = (script) => [...script.matchAll(SCRIPT_ROOT_URL)].map(
|
|
6932
|
+
(match) => rootPathFinding(match[2] ?? "", void 0, match[0])
|
|
6933
|
+
);
|
|
6934
|
+
function invalidImportMap(script) {
|
|
6935
|
+
if (!/\btype\s*=\s*["']?importmap\b/i.test(script.attrs)) return [];
|
|
6936
|
+
try {
|
|
6937
|
+
JSON.parse(script.content);
|
|
6938
|
+
return [];
|
|
6939
|
+
} catch (error) {
|
|
6940
|
+
return [
|
|
6941
|
+
{
|
|
6942
|
+
code: "import_map_invalid",
|
|
6943
|
+
severity: "warning",
|
|
6944
|
+
message: `This import map is not valid JSON (${error instanceof Error ? error.message : String(error)}). The browser ignores it, and preview cannot map root module paths ("/assets/x.js") to the project.`,
|
|
6945
|
+
fixHint: "Make the import map valid JSON: double-quoted keys and values, no trailing commas.",
|
|
6946
|
+
snippet: truncateSnippet(script.content)
|
|
6947
|
+
}
|
|
6948
|
+
];
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
var rootPathRules = [
|
|
6952
|
+
(ctx) => [
|
|
6953
|
+
...ctx.tags.flatMap(tagRootPaths),
|
|
6954
|
+
...ctx.styles.flatMap((style) => cssRootPaths(style.content, style.rootRelativePath)),
|
|
6955
|
+
...ctx.scripts.flatMap((script) => scriptRootPaths(script.content)),
|
|
6956
|
+
...ctx.scripts.flatMap(invalidImportMap)
|
|
6957
|
+
]
|
|
6958
|
+
];
|
|
6959
|
+
|
|
6881
6960
|
// src/hyperframeLinter.ts
|
|
6882
6961
|
var RULE_GROUPS = [
|
|
6883
6962
|
{ group: "core", rules: coreRules },
|
|
@@ -6890,7 +6969,8 @@ var RULE_GROUPS = [
|
|
|
6890
6969
|
{ group: "fonts", rules: fontRules },
|
|
6891
6970
|
{ group: "slideshow", rules: slideshowRules },
|
|
6892
6971
|
{ group: "structure", rules: structureRules },
|
|
6893
|
-
{ group: "shaders", rules: shaderRules }
|
|
6972
|
+
{ group: "shaders", rules: shaderRules },
|
|
6973
|
+
{ group: "rootPaths", rules: rootPathRules }
|
|
6894
6974
|
];
|
|
6895
6975
|
var LINT_RULE_COUNT = RULE_GROUPS.reduce((n, g) => n + g.rules.length, 0);
|
|
6896
6976
|
var LINT_RULE_GROUP_COUNTS = Object.fromEntries(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/lint",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.208",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"linkedom": "^0.18.12",
|
|
36
36
|
"postcss": "^8.5.8",
|
|
37
37
|
"postcss-selector-parser": "^7.1.4",
|
|
38
|
-
"@hyperframes/parsers": "0.8.
|
|
38
|
+
"@hyperframes/parsers": "0.8.208"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^25.0.10",
|