@hominis/fireforge 0.9.0
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/CHANGELOG.md +7 -0
- package/LICENSE.md +294 -0
- package/README.md +435 -0
- package/dist/bin/fireforge.d.ts +10 -0
- package/dist/bin/fireforge.js +29 -0
- package/dist/src/cli.d.ts +33 -0
- package/dist/src/cli.js +180 -0
- package/dist/src/commands/bootstrap.d.ts +9 -0
- package/dist/src/commands/bootstrap.js +73 -0
- package/dist/src/commands/build.d.ts +11 -0
- package/dist/src/commands/build.js +102 -0
- package/dist/src/commands/config.d.ts +13 -0
- package/dist/src/commands/config.js +135 -0
- package/dist/src/commands/discard.d.ts +12 -0
- package/dist/src/commands/discard.js +84 -0
- package/dist/src/commands/doctor.d.ts +18 -0
- package/dist/src/commands/doctor.js +356 -0
- package/dist/src/commands/download.d.ts +11 -0
- package/dist/src/commands/download.js +127 -0
- package/dist/src/commands/export-all.d.ts +11 -0
- package/dist/src/commands/export-all.js +122 -0
- package/dist/src/commands/export-shared.d.ts +48 -0
- package/dist/src/commands/export-shared.js +208 -0
- package/dist/src/commands/export.d.ts +13 -0
- package/dist/src/commands/export.js +178 -0
- package/dist/src/commands/furnace/apply.d.ts +7 -0
- package/dist/src/commands/furnace/apply.js +80 -0
- package/dist/src/commands/furnace/create.d.ts +8 -0
- package/dist/src/commands/furnace/create.js +377 -0
- package/dist/src/commands/furnace/deploy.d.ts +8 -0
- package/dist/src/commands/furnace/deploy.js +338 -0
- package/dist/src/commands/furnace/diff.d.ts +7 -0
- package/dist/src/commands/furnace/diff.js +119 -0
- package/dist/src/commands/furnace/index.d.ts +16 -0
- package/dist/src/commands/furnace/index.js +121 -0
- package/dist/src/commands/furnace/list.d.ts +5 -0
- package/dist/src/commands/furnace/list.js +65 -0
- package/dist/src/commands/furnace/override.d.ts +8 -0
- package/dist/src/commands/furnace/override.js +188 -0
- package/dist/src/commands/furnace/preview.d.ts +7 -0
- package/dist/src/commands/furnace/preview.js +96 -0
- package/dist/src/commands/furnace/remove.d.ts +8 -0
- package/dist/src/commands/furnace/remove.js +159 -0
- package/dist/src/commands/furnace/scan.d.ts +5 -0
- package/dist/src/commands/furnace/scan.js +112 -0
- package/dist/src/commands/furnace/status.d.ts +7 -0
- package/dist/src/commands/furnace/status.js +137 -0
- package/dist/src/commands/furnace/validate.d.ts +6 -0
- package/dist/src/commands/furnace/validate.js +91 -0
- package/dist/src/commands/furnace/validation-output.d.ts +7 -0
- package/dist/src/commands/furnace/validation-output.js +22 -0
- package/dist/src/commands/import.d.ts +11 -0
- package/dist/src/commands/import.js +241 -0
- package/dist/src/commands/lint.d.ts +10 -0
- package/dist/src/commands/lint.js +118 -0
- package/dist/src/commands/package.d.ts +11 -0
- package/dist/src/commands/package.js +80 -0
- package/dist/src/commands/re-export.d.ts +12 -0
- package/dist/src/commands/re-export.js +242 -0
- package/dist/src/commands/rebase/abort.d.ts +7 -0
- package/dist/src/commands/rebase/abort.js +49 -0
- package/dist/src/commands/rebase/confirm.d.ts +18 -0
- package/dist/src/commands/rebase/confirm.js +33 -0
- package/dist/src/commands/rebase/continue.d.ts +7 -0
- package/dist/src/commands/rebase/continue.js +81 -0
- package/dist/src/commands/rebase/index.d.ts +22 -0
- package/dist/src/commands/rebase/index.js +127 -0
- package/dist/src/commands/rebase/patch-loop.d.ts +9 -0
- package/dist/src/commands/rebase/patch-loop.js +135 -0
- package/dist/src/commands/rebase/summary.d.ts +12 -0
- package/dist/src/commands/rebase/summary.js +43 -0
- package/dist/src/commands/rebase.d.ts +4 -0
- package/dist/src/commands/rebase.js +6 -0
- package/dist/src/commands/register.d.ts +13 -0
- package/dist/src/commands/register.js +67 -0
- package/dist/src/commands/reset.d.ts +11 -0
- package/dist/src/commands/reset.js +83 -0
- package/dist/src/commands/resolve.d.ts +9 -0
- package/dist/src/commands/resolve.js +124 -0
- package/dist/src/commands/run.d.ts +9 -0
- package/dist/src/commands/run.js +91 -0
- package/dist/src/commands/setup-support.d.ts +23 -0
- package/dist/src/commands/setup-support.js +310 -0
- package/dist/src/commands/setup.d.ts +11 -0
- package/dist/src/commands/setup.js +94 -0
- package/dist/src/commands/status.d.ts +11 -0
- package/dist/src/commands/status.js +268 -0
- package/dist/src/commands/test.d.ts +12 -0
- package/dist/src/commands/test.js +182 -0
- package/dist/src/commands/token-coverage.d.ts +5 -0
- package/dist/src/commands/token-coverage.js +57 -0
- package/dist/src/commands/token.d.ts +14 -0
- package/dist/src/commands/token.js +121 -0
- package/dist/src/commands/watch.d.ts +9 -0
- package/dist/src/commands/watch.js +112 -0
- package/dist/src/commands/wire.d.ts +13 -0
- package/dist/src/commands/wire.js +149 -0
- package/dist/src/core/ast-utils.d.ts +47 -0
- package/dist/src/core/ast-utils.js +57 -0
- package/dist/src/core/brand-validation.d.ts +7 -0
- package/dist/src/core/brand-validation.js +15 -0
- package/dist/src/core/branding.d.ts +49 -0
- package/dist/src/core/branding.js +229 -0
- package/dist/src/core/browser-wire.d.ts +40 -0
- package/dist/src/core/browser-wire.js +66 -0
- package/dist/src/core/build-prepare.d.ts +25 -0
- package/dist/src/core/build-prepare.js +93 -0
- package/dist/src/core/config-mutate.d.ts +15 -0
- package/dist/src/core/config-mutate.js +51 -0
- package/dist/src/core/config-paths.d.ts +28 -0
- package/dist/src/core/config-paths.js +65 -0
- package/dist/src/core/config-state.d.ts +28 -0
- package/dist/src/core/config-state.js +152 -0
- package/dist/src/core/config-validate.d.ts +11 -0
- package/dist/src/core/config-validate.js +141 -0
- package/dist/src/core/config.d.ts +39 -0
- package/dist/src/core/config.js +70 -0
- package/dist/src/core/file-lock.d.ts +11 -0
- package/dist/src/core/file-lock.js +80 -0
- package/dist/src/core/firefox-archive.d.ts +40 -0
- package/dist/src/core/firefox-archive.js +63 -0
- package/dist/src/core/firefox-cache.d.ts +23 -0
- package/dist/src/core/firefox-cache.js +134 -0
- package/dist/src/core/firefox-download.d.ts +21 -0
- package/dist/src/core/firefox-download.js +129 -0
- package/dist/src/core/firefox-extract.d.ts +21 -0
- package/dist/src/core/firefox-extract.js +53 -0
- package/dist/src/core/firefox.d.ts +34 -0
- package/dist/src/core/firefox.js +78 -0
- package/dist/src/core/furnace-apply-helpers.d.ts +21 -0
- package/dist/src/core/furnace-apply-helpers.js +244 -0
- package/dist/src/core/furnace-apply.d.ts +16 -0
- package/dist/src/core/furnace-apply.js +147 -0
- package/dist/src/core/furnace-config.d.ts +94 -0
- package/dist/src/core/furnace-config.js +372 -0
- package/dist/src/core/furnace-constants.d.ts +4 -0
- package/dist/src/core/furnace-constants.js +6 -0
- package/dist/src/core/furnace-registration-ast.d.ts +24 -0
- package/dist/src/core/furnace-registration-ast.js +218 -0
- package/dist/src/core/furnace-registration-remove.d.ts +14 -0
- package/dist/src/core/furnace-registration-remove.js +89 -0
- package/dist/src/core/furnace-registration-validate.d.ts +20 -0
- package/dist/src/core/furnace-registration-validate.js +40 -0
- package/dist/src/core/furnace-registration.d.ts +29 -0
- package/dist/src/core/furnace-registration.js +96 -0
- package/dist/src/core/furnace-rollback.d.ts +20 -0
- package/dist/src/core/furnace-rollback.js +66 -0
- package/dist/src/core/furnace-scanner.d.ts +40 -0
- package/dist/src/core/furnace-scanner.js +143 -0
- package/dist/src/core/furnace-stories.d.ts +37 -0
- package/dist/src/core/furnace-stories.js +185 -0
- package/dist/src/core/furnace-validate-accessibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-accessibility.js +32 -0
- package/dist/src/core/furnace-validate-checks.d.ts +4 -0
- package/dist/src/core/furnace-validate-checks.js +7 -0
- package/dist/src/core/furnace-validate-compatibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-compatibility.js +57 -0
- package/dist/src/core/furnace-validate-helpers.d.ts +28 -0
- package/dist/src/core/furnace-validate-helpers.js +129 -0
- package/dist/src/core/furnace-validate-registration.d.ts +37 -0
- package/dist/src/core/furnace-validate-registration.js +220 -0
- package/dist/src/core/furnace-validate-structure.d.ts +6 -0
- package/dist/src/core/furnace-validate-structure.js +66 -0
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +103 -0
- package/dist/src/core/git-base.d.ts +47 -0
- package/dist/src/core/git-base.js +50 -0
- package/dist/src/core/git-diff.d.ts +63 -0
- package/dist/src/core/git-diff.js +246 -0
- package/dist/src/core/git-file-ops.d.ts +65 -0
- package/dist/src/core/git-file-ops.js +141 -0
- package/dist/src/core/git-status.d.ts +65 -0
- package/dist/src/core/git-status.js +163 -0
- package/dist/src/core/git.d.ts +113 -0
- package/dist/src/core/git.js +363 -0
- package/dist/src/core/license-headers.d.ts +36 -0
- package/dist/src/core/license-headers.js +83 -0
- package/dist/src/core/mach-build-artifacts.d.ts +29 -0
- package/dist/src/core/mach-build-artifacts.js +117 -0
- package/dist/src/core/mach-mozconfig.d.ts +17 -0
- package/dist/src/core/mach-mozconfig.js +50 -0
- package/dist/src/core/mach-python.d.ts +16 -0
- package/dist/src/core/mach-python.js +126 -0
- package/dist/src/core/mach.d.ts +106 -0
- package/dist/src/core/mach.js +166 -0
- package/dist/src/core/manifest-helpers.d.ts +25 -0
- package/dist/src/core/manifest-helpers.js +96 -0
- package/dist/src/core/manifest-register.d.ts +30 -0
- package/dist/src/core/manifest-register.js +65 -0
- package/dist/src/core/manifest-rules.d.ts +39 -0
- package/dist/src/core/manifest-rules.js +151 -0
- package/dist/src/core/manifest-tokenizers.d.ts +34 -0
- package/dist/src/core/manifest-tokenizers.js +84 -0
- package/dist/src/core/parser-fallback.d.ts +36 -0
- package/dist/src/core/parser-fallback.js +43 -0
- package/dist/src/core/patch-apply-fuzz.d.ts +29 -0
- package/dist/src/core/patch-apply-fuzz.js +70 -0
- package/dist/src/core/patch-apply.d.ts +46 -0
- package/dist/src/core/patch-apply.js +235 -0
- package/dist/src/core/patch-export.d.ts +99 -0
- package/dist/src/core/patch-export.js +314 -0
- package/dist/src/core/patch-files.d.ts +11 -0
- package/dist/src/core/patch-files.js +51 -0
- package/dist/src/core/patch-lint.d.ts +72 -0
- package/dist/src/core/patch-lint.js +403 -0
- package/dist/src/core/patch-lock.d.ts +8 -0
- package/dist/src/core/patch-lock.js +29 -0
- package/dist/src/core/patch-manifest-consistency.d.ts +24 -0
- package/dist/src/core/patch-manifest-consistency.js +135 -0
- package/dist/src/core/patch-manifest-io.d.ts +36 -0
- package/dist/src/core/patch-manifest-io.js +77 -0
- package/dist/src/core/patch-manifest-query.d.ts +48 -0
- package/dist/src/core/patch-manifest-query.js +124 -0
- package/dist/src/core/patch-manifest-validate.d.ts +22 -0
- package/dist/src/core/patch-manifest-validate.js +72 -0
- package/dist/src/core/patch-manifest.d.ts +11 -0
- package/dist/src/core/patch-manifest.js +12 -0
- package/dist/src/core/patch-parse.d.ts +43 -0
- package/dist/src/core/patch-parse.js +143 -0
- package/dist/src/core/patch-transform.d.ts +21 -0
- package/dist/src/core/patch-transform.js +138 -0
- package/dist/src/core/rebase-session.d.ts +47 -0
- package/dist/src/core/rebase-session.js +65 -0
- package/dist/src/core/register-browser-content.d.ts +11 -0
- package/dist/src/core/register-browser-content.js +116 -0
- package/dist/src/core/register-module.d.ts +11 -0
- package/dist/src/core/register-module.js +76 -0
- package/dist/src/core/register-shared-css.d.ts +11 -0
- package/dist/src/core/register-shared-css.js +117 -0
- package/dist/src/core/register-test-manifest.d.ts +18 -0
- package/dist/src/core/register-test-manifest.js +99 -0
- package/dist/src/core/state-file.d.ts +4 -0
- package/dist/src/core/state-file.js +25 -0
- package/dist/src/core/token-coverage.d.ts +12 -0
- package/dist/src/core/token-coverage.js +74 -0
- package/dist/src/core/token-manager.d.ts +55 -0
- package/dist/src/core/token-manager.js +387 -0
- package/dist/src/core/wire-destroy.d.ts +21 -0
- package/dist/src/core/wire-destroy.js +103 -0
- package/dist/src/core/wire-dom-fragment.d.ts +23 -0
- package/dist/src/core/wire-dom-fragment.js +129 -0
- package/dist/src/core/wire-init.d.ts +23 -0
- package/dist/src/core/wire-init.js +201 -0
- package/dist/src/core/wire-subscript.d.ts +20 -0
- package/dist/src/core/wire-subscript.js +134 -0
- package/dist/src/core/wire-targets.d.ts +7 -0
- package/dist/src/core/wire-targets.js +9 -0
- package/dist/src/core/wire-utils.d.ts +88 -0
- package/dist/src/core/wire-utils.js +279 -0
- package/dist/src/errors/base.d.ts +60 -0
- package/dist/src/errors/base.js +87 -0
- package/dist/src/errors/build.d.ts +52 -0
- package/dist/src/errors/build.js +114 -0
- package/dist/src/errors/codes.d.ts +29 -0
- package/dist/src/errors/codes.js +30 -0
- package/dist/src/errors/config.d.ts +31 -0
- package/dist/src/errors/config.js +61 -0
- package/dist/src/errors/download.d.ts +42 -0
- package/dist/src/errors/download.js +95 -0
- package/dist/src/errors/furnace.d.ts +10 -0
- package/dist/src/errors/furnace.js +22 -0
- package/dist/src/errors/git.d.ts +41 -0
- package/dist/src/errors/git.js +99 -0
- package/dist/src/errors/patch.d.ts +10 -0
- package/dist/src/errors/patch.js +26 -0
- package/dist/src/errors/rebase.d.ts +20 -0
- package/dist/src/errors/rebase.js +30 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +21 -0
- package/dist/src/types/cli.d.ts +14 -0
- package/dist/src/types/cli.js +2 -0
- package/dist/src/types/commands/index.d.ts +6 -0
- package/dist/src/types/commands/index.js +6 -0
- package/dist/src/types/commands/options.d.ts +239 -0
- package/dist/src/types/commands/options.js +6 -0
- package/dist/src/types/commands/patches.d.ts +89 -0
- package/dist/src/types/commands/patches.js +6 -0
- package/dist/src/types/commands/project.d.ts +71 -0
- package/dist/src/types/commands/project.js +6 -0
- package/dist/src/types/config.d.ts +101 -0
- package/dist/src/types/config.js +2 -0
- package/dist/src/types/furnace.d.ts +158 -0
- package/dist/src/types/furnace.js +2 -0
- package/dist/src/types/index.d.ts +6 -0
- package/dist/src/types/index.js +6 -0
- package/dist/src/utils/errors.d.ts +2 -0
- package/dist/src/utils/errors.js +15 -0
- package/dist/src/utils/fs.d.ts +72 -0
- package/dist/src/utils/fs.js +179 -0
- package/dist/src/utils/logger.d.ts +58 -0
- package/dist/src/utils/logger.js +120 -0
- package/dist/src/utils/options.d.ts +8 -0
- package/dist/src/utils/options.js +16 -0
- package/dist/src/utils/package-root.d.ts +10 -0
- package/dist/src/utils/package-root.js +53 -0
- package/dist/src/utils/parse.d.ts +110 -0
- package/dist/src/utils/parse.js +200 -0
- package/dist/src/utils/paths.d.ts +10 -0
- package/dist/src/utils/paths.js +43 -0
- package/dist/src/utils/platform.d.ts +38 -0
- package/dist/src/utils/platform.js +56 -0
- package/dist/src/utils/process.d.ts +80 -0
- package/dist/src/utils/process.js +188 -0
- package/dist/src/utils/regex.d.ts +24 -0
- package/dist/src/utils/regex.js +40 -0
- package/dist/src/utils/validation.d.ts +133 -0
- package/dist/src/utils/validation.js +250 -0
- package/package.json +106 -0
- package/templates/configs/common.mozconfig +24 -0
- package/templates/configs/darwin.mozconfig +10 -0
- package/templates/configs/linux.mozconfig +12 -0
- package/templates/configs/win32.mozconfig +14 -0
- package/templates/licenses/0BSD.md +14 -0
- package/templates/licenses/EUPL-1.2.md +294 -0
- package/templates/licenses/GPL-2.0-or-later.md +339 -0
- package/templates/licenses/MPL-2.0.md +383 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Removal of custom element registrations from customElements.js.
|
|
4
|
+
* Supports three removal strategies: standalone callback, single-line array, multi-line array.
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
8
|
+
import { CUSTOM_ELEMENTS_JS } from './furnace-constants.js';
|
|
9
|
+
/**
|
|
10
|
+
* Removes a custom element registration from customElements.js.
|
|
11
|
+
*
|
|
12
|
+
* This operation is idempotent — if the tag is not registered or the file does
|
|
13
|
+
* not exist, nothing happens.
|
|
14
|
+
*
|
|
15
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
16
|
+
* @param tagName - Custom element tag name to remove
|
|
17
|
+
*/
|
|
18
|
+
export async function removeCustomElementRegistration(engineDir, tagName) {
|
|
19
|
+
const filePath = join(engineDir, CUSTOM_ELEMENTS_JS);
|
|
20
|
+
if (!(await pathExists(filePath))) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
let content = await readText(filePath);
|
|
24
|
+
const lines = content.split('\n');
|
|
25
|
+
// Strategy 1: Remove standalone callback block (setElementCreationCallback("tagName" …))
|
|
26
|
+
const callbackLine = lines.findIndex((l) => l.includes(`setElementCreationCallback("${tagName}"`));
|
|
27
|
+
if (callbackLine !== -1) {
|
|
28
|
+
let endLine = callbackLine;
|
|
29
|
+
for (let i = callbackLine + 1; i < lines.length; i++) {
|
|
30
|
+
const line = lines[i];
|
|
31
|
+
if (line === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
if (/^\s*\}\);/.test(line)) {
|
|
34
|
+
endLine = i;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
let startLine = callbackLine;
|
|
39
|
+
const precedingLine = lines[startLine - 1];
|
|
40
|
+
if (startLine > 0 && precedingLine !== undefined && precedingLine.trim() === '') {
|
|
41
|
+
startLine--;
|
|
42
|
+
}
|
|
43
|
+
lines.splice(startLine, endLine - startLine + 1);
|
|
44
|
+
content = lines.join('\n');
|
|
45
|
+
await writeText(filePath, content);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Strategy 2: Remove single-line array entry ["tagName", "..."],
|
|
49
|
+
const singleLineIdx = lines.findIndex((l) => new RegExp(`^\\s*\\["${tagName}",\\s*"[^"]*"\\],?\\s*$`).test(l));
|
|
50
|
+
if (singleLineIdx !== -1) {
|
|
51
|
+
lines.splice(singleLineIdx, 1);
|
|
52
|
+
content = lines.join('\n');
|
|
53
|
+
await writeText(filePath, content);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Strategy 3: Remove multi-line array entry where "tagName", is on its own line
|
|
57
|
+
const multiLineTagIdx = lines.findIndex((l) => new RegExp(`^\\s*"${tagName}",\\s*$`).test(l));
|
|
58
|
+
if (multiLineTagIdx !== -1) {
|
|
59
|
+
// Scan backwards from the tag line to find the opening [ (bounded to 20 lines)
|
|
60
|
+
let startLine = multiLineTagIdx;
|
|
61
|
+
const scanLimit = Math.max(0, multiLineTagIdx - 20);
|
|
62
|
+
for (let i = multiLineTagIdx - 1; i >= scanLimit; i--) {
|
|
63
|
+
const line = lines[i];
|
|
64
|
+
if (line !== undefined && /^\s*\[$/.test(line)) {
|
|
65
|
+
startLine = i;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const openIndent = (lines[startLine] ?? '').match(/^(\s*)/)?.[1]?.length ?? 0;
|
|
70
|
+
// Scan forwards from the tag line to find the closing ],
|
|
71
|
+
let endLine = multiLineTagIdx;
|
|
72
|
+
for (let i = multiLineTagIdx + 1; i < lines.length; i++) {
|
|
73
|
+
const line = lines[i];
|
|
74
|
+
if (line !== undefined && /^\s*\],?\s*$/.test(line)) {
|
|
75
|
+
const closeIndent = line.match(/^(\s*)/)?.[1]?.length ?? 0;
|
|
76
|
+
if (closeIndent === openIndent) {
|
|
77
|
+
endLine = i;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
lines.splice(startLine, endLine - startLine + 1);
|
|
83
|
+
content = lines.join('\n');
|
|
84
|
+
await writeText(filePath, content);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Tag not found in any form — idempotent no-op
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=furnace-registration-remove.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared validation for furnace custom element registration placement.
|
|
3
|
+
* Used after both AST and legacy code paths to avoid duplicating logic.
|
|
4
|
+
*/
|
|
5
|
+
/** Regex for valid custom element tag names. */
|
|
6
|
+
export declare const CUSTOM_ELEMENT_TAG_PATTERN: RegExp;
|
|
7
|
+
/**
|
|
8
|
+
* Validates that a tag name conforms to custom element naming requirements.
|
|
9
|
+
* @throws FurnaceError if the tag name is invalid
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateTagName(tagName: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Validates that a registration entry landed in the correct block
|
|
14
|
+
* (Pattern A = loadSubScript, Pattern B = DOMContentLoaded/importESModule).
|
|
15
|
+
*
|
|
16
|
+
* @param result - The full file content after insertion
|
|
17
|
+
* @param tagName - The tag that was inserted
|
|
18
|
+
* @param isESModule - Whether the module uses ESM (Pattern B) or not (Pattern A)
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateRegistrationPlacement(result: string, tagName: string, isESModule: boolean): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Shared validation for furnace custom element registration placement.
|
|
4
|
+
* Used after both AST and legacy code paths to avoid duplicating logic.
|
|
5
|
+
*/
|
|
6
|
+
import { FurnaceError } from '../errors/furnace.js';
|
|
7
|
+
/** Regex for valid custom element tag names. */
|
|
8
|
+
export const CUSTOM_ELEMENT_TAG_PATTERN = /^[a-z][a-z0-9]*-[a-z0-9-]*$/;
|
|
9
|
+
/**
|
|
10
|
+
* Validates that a tag name conforms to custom element naming requirements.
|
|
11
|
+
* @throws FurnaceError if the tag name is invalid
|
|
12
|
+
*/
|
|
13
|
+
export function validateTagName(tagName) {
|
|
14
|
+
if (!CUSTOM_ELEMENT_TAG_PATTERN.test(tagName)) {
|
|
15
|
+
throw new FurnaceError(`Invalid tag name "${tagName}": must contain a hyphen and match /^[a-z][a-z0-9]*-[a-z0-9-]*$/`, tagName);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Validates that a registration entry landed in the correct block
|
|
20
|
+
* (Pattern A = loadSubScript, Pattern B = DOMContentLoaded/importESModule).
|
|
21
|
+
*
|
|
22
|
+
* @param result - The full file content after insertion
|
|
23
|
+
* @param tagName - The tag that was inserted
|
|
24
|
+
* @param isESModule - Whether the module uses ESM (Pattern B) or not (Pattern A)
|
|
25
|
+
*/
|
|
26
|
+
export function validateRegistrationPlacement(result, tagName, isESModule) {
|
|
27
|
+
const dclPattern = /document\.addEventListener\(\s*["']DOMContentLoaded["']/;
|
|
28
|
+
const insertedPos = result.lastIndexOf(`"${tagName}"`);
|
|
29
|
+
if (insertedPos === -1)
|
|
30
|
+
return;
|
|
31
|
+
const contentBeforeTag = result.slice(0, insertedPos);
|
|
32
|
+
const hasDCLBefore = dclPattern.test(contentBeforeTag);
|
|
33
|
+
if (isESModule && !hasDCLBefore) {
|
|
34
|
+
throw new FurnaceError(`${tagName} was registered in the loadSubScript block (Pattern A) instead of the DOMContentLoaded/importESModule block (Pattern B). This will cause the component to fail at runtime. The customElements.js file structure may have changed upstream — manual intervention required.`, tagName);
|
|
35
|
+
}
|
|
36
|
+
if (!isESModule && hasDCLBefore) {
|
|
37
|
+
throw new FurnaceError(`${tagName} was registered in the DOMContentLoaded/importESModule block (Pattern B) instead of the loadSubScript block (Pattern A). This will cause the component to fail at runtime. The customElements.js file structure may have changed upstream — manual intervention required.`, tagName);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=furnace-registration-validate.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
|
|
2
|
+
export { addCustomElementRegistration, removeCustomElementRegistration, } from './furnace-registration-ast.js';
|
|
3
|
+
/**
|
|
4
|
+
* Adds jar.mn entries that map chrome:// URIs to on-disk paths for a
|
|
5
|
+
* component's files.
|
|
6
|
+
*
|
|
7
|
+
* Entry format (3-space indent, spaces not tabs):
|
|
8
|
+
* ```
|
|
9
|
+
* content/global/elements/{file} (widgets/{tagName}/{file})
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* New entries are inserted in alphabetical order relative to existing
|
|
13
|
+
* `content/global/elements/` entries. The operation is idempotent.
|
|
14
|
+
*
|
|
15
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
16
|
+
* @param tagName - Custom element tag name
|
|
17
|
+
* @param files - Filenames to register (e.g. ["moz-widget.mjs", "moz-widget.css"])
|
|
18
|
+
*/
|
|
19
|
+
export declare function addJarMnEntries(engineDir: string, tagName: string, files: string[]): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Removes all jar.mn entries for a given tag name.
|
|
22
|
+
*
|
|
23
|
+
* This operation is idempotent — if no entries exist or the file is missing,
|
|
24
|
+
* nothing happens.
|
|
25
|
+
*
|
|
26
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
27
|
+
* @param tagName - Custom element tag name whose entries should be removed
|
|
28
|
+
*/
|
|
29
|
+
export declare function removeJarMnEntries(engineDir: string, tagName: string): Promise<void>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { FurnaceError } from '../errors/furnace.js';
|
|
4
|
+
import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
5
|
+
// Re-export everything from the AST module so existing imports keep working
|
|
6
|
+
export { CUSTOM_ELEMENTS_JS, JAR_MN } from './furnace-constants.js';
|
|
7
|
+
export { addCustomElementRegistration, removeCustomElementRegistration, } from './furnace-registration-ast.js';
|
|
8
|
+
import { JAR_MN } from './furnace-constants.js';
|
|
9
|
+
/**
|
|
10
|
+
* Adds jar.mn entries that map chrome:// URIs to on-disk paths for a
|
|
11
|
+
* component's files.
|
|
12
|
+
*
|
|
13
|
+
* Entry format (3-space indent, spaces not tabs):
|
|
14
|
+
* ```
|
|
15
|
+
* content/global/elements/{file} (widgets/{tagName}/{file})
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* New entries are inserted in alphabetical order relative to existing
|
|
19
|
+
* `content/global/elements/` entries. The operation is idempotent.
|
|
20
|
+
*
|
|
21
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
22
|
+
* @param tagName - Custom element tag name
|
|
23
|
+
* @param files - Filenames to register (e.g. ["moz-widget.mjs", "moz-widget.css"])
|
|
24
|
+
*/
|
|
25
|
+
export async function addJarMnEntries(engineDir, tagName, files) {
|
|
26
|
+
const filePath = join(engineDir, JAR_MN);
|
|
27
|
+
if (!(await pathExists(filePath))) {
|
|
28
|
+
throw new FurnaceError('jar.mn not found in engine', tagName);
|
|
29
|
+
}
|
|
30
|
+
let content = await readText(filePath);
|
|
31
|
+
const lines = content.split('\n');
|
|
32
|
+
// Filter to files not already registered
|
|
33
|
+
const newFiles = files.filter((f) => !content.includes(`content/global/elements/${f}`));
|
|
34
|
+
if (newFiles.length === 0)
|
|
35
|
+
return;
|
|
36
|
+
// Build new entry lines
|
|
37
|
+
const newEntries = newFiles.map((f) => ` content/global/elements/${f} (widgets/${tagName}/${f})`);
|
|
38
|
+
// Find insertion point among existing content/global/elements/ lines
|
|
39
|
+
const elementLinePattern = /^\s+content\/global\/elements\/([^.]+)\./;
|
|
40
|
+
let insertIndex = -1;
|
|
41
|
+
for (let i = 0; i < lines.length; i++) {
|
|
42
|
+
const line = lines[i];
|
|
43
|
+
if (line === undefined)
|
|
44
|
+
continue;
|
|
45
|
+
const match = elementLinePattern.exec(line);
|
|
46
|
+
if (match) {
|
|
47
|
+
const existingTag = match[1] ?? '';
|
|
48
|
+
if (existingTag > tagName) {
|
|
49
|
+
insertIndex = i;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
// Track last element entry line as fallback (insert after it)
|
|
53
|
+
insertIndex = i + 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (insertIndex === -1) {
|
|
57
|
+
// Fallback: find last content/global/ line
|
|
58
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
59
|
+
const line = lines[i];
|
|
60
|
+
if (line !== undefined && /^\s+content\/global\//.test(line)) {
|
|
61
|
+
insertIndex = i + 1;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (insertIndex === -1) {
|
|
67
|
+
throw new FurnaceError('Could not find insertion point in jar.mn for element entries', tagName);
|
|
68
|
+
}
|
|
69
|
+
lines.splice(insertIndex, 0, ...newEntries);
|
|
70
|
+
content = lines.join('\n');
|
|
71
|
+
await writeText(filePath, content);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Removes all jar.mn entries for a given tag name.
|
|
75
|
+
*
|
|
76
|
+
* This operation is idempotent — if no entries exist or the file is missing,
|
|
77
|
+
* nothing happens.
|
|
78
|
+
*
|
|
79
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
80
|
+
* @param tagName - Custom element tag name whose entries should be removed
|
|
81
|
+
*/
|
|
82
|
+
export async function removeJarMnEntries(engineDir, tagName) {
|
|
83
|
+
const filePath = join(engineDir, JAR_MN);
|
|
84
|
+
if (!(await pathExists(filePath))) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
let content = await readText(filePath);
|
|
88
|
+
const lines = content.split('\n');
|
|
89
|
+
const pattern = `content/global/elements/${tagName}.`;
|
|
90
|
+
const filtered = lines.filter((line) => !line.includes(pattern));
|
|
91
|
+
if (filtered.length === lines.length)
|
|
92
|
+
return;
|
|
93
|
+
content = filtered.join('\n');
|
|
94
|
+
await writeText(filePath, content);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=furnace-registration.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface FileSnapshot {
|
|
2
|
+
existed: boolean;
|
|
3
|
+
content?: Uint8Array;
|
|
4
|
+
mode?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface RollbackJournal {
|
|
7
|
+
files: Map<string, FileSnapshot>;
|
|
8
|
+
createdDirs: Set<string>;
|
|
9
|
+
}
|
|
10
|
+
/** Creates an empty rollback journal for tracking touched files and created directories. */
|
|
11
|
+
export declare function createRollbackJournal(): RollbackJournal;
|
|
12
|
+
/** Records a directory that should be removed if the operation later rolls back. */
|
|
13
|
+
export declare function recordCreatedDir(journal: RollbackJournal, dirPath: string): void;
|
|
14
|
+
/** Snapshots a file once so rollback can restore its previous contents or absence. */
|
|
15
|
+
export declare function snapshotFile(journal: RollbackJournal, filePath: string): Promise<void>;
|
|
16
|
+
/** Restores all snapshotted files and removes directories created during the operation. */
|
|
17
|
+
export declare function restoreRollbackJournal(journal: RollbackJournal): Promise<void>;
|
|
18
|
+
/** Restores a rollback journal and wraps rollback failures in a FurnaceError. */
|
|
19
|
+
export declare function restoreRollbackJournalOrThrow(journal: RollbackJournal, context: string): Promise<void>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { chmod, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { FurnaceError } from '../errors/furnace.js';
|
|
5
|
+
import { toError } from '../utils/errors.js';
|
|
6
|
+
import { pathExists } from '../utils/fs.js';
|
|
7
|
+
/** Creates an empty rollback journal for tracking touched files and created directories. */
|
|
8
|
+
export function createRollbackJournal() {
|
|
9
|
+
return {
|
|
10
|
+
files: new Map(),
|
|
11
|
+
createdDirs: new Set(),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/** Records a directory that should be removed if the operation later rolls back. */
|
|
15
|
+
export function recordCreatedDir(journal, dirPath) {
|
|
16
|
+
journal.createdDirs.add(dirPath);
|
|
17
|
+
}
|
|
18
|
+
/** Snapshots a file once so rollback can restore its previous contents or absence. */
|
|
19
|
+
export async function snapshotFile(journal, filePath) {
|
|
20
|
+
if (journal.files.has(filePath)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!(await pathExists(filePath))) {
|
|
24
|
+
journal.files.set(filePath, { existed: false });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const [content, fileStat] = await Promise.all([readFile(filePath), stat(filePath)]);
|
|
28
|
+
journal.files.set(filePath, {
|
|
29
|
+
existed: true,
|
|
30
|
+
content,
|
|
31
|
+
mode: fileStat.mode,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function restoreFile(filePath, snapshot) {
|
|
35
|
+
if (!snapshot.existed) {
|
|
36
|
+
await rm(filePath, { force: true });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
40
|
+
await writeFile(filePath, snapshot.content ?? new Uint8Array());
|
|
41
|
+
if (snapshot.mode !== undefined) {
|
|
42
|
+
await chmod(filePath, snapshot.mode);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Restores all snapshotted files and removes directories created during the operation. */
|
|
46
|
+
export async function restoreRollbackJournal(journal) {
|
|
47
|
+
const fileEntries = [...journal.files.entries()].sort(([left], [right]) => right.length - left.length);
|
|
48
|
+
for (const [filePath, snapshot] of fileEntries) {
|
|
49
|
+
await restoreFile(filePath, snapshot);
|
|
50
|
+
}
|
|
51
|
+
const createdDirs = [...journal.createdDirs].sort((left, right) => right.length - left.length);
|
|
52
|
+
for (const dirPath of createdDirs) {
|
|
53
|
+
await rm(dirPath, { recursive: true, force: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Restores a rollback journal and wraps rollback failures in a FurnaceError. */
|
|
57
|
+
export async function restoreRollbackJournalOrThrow(journal, context) {
|
|
58
|
+
try {
|
|
59
|
+
await restoreRollbackJournal(journal);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
const message = toError(error).message;
|
|
63
|
+
throw new FurnaceError(`${context}; automatic rollback failed: ${message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=furnace-rollback.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ScannedComponent } from '../types/furnace.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parses customElements.js to extract tag-to-module mappings.
|
|
4
|
+
*
|
|
5
|
+
* Looks for registration patterns like:
|
|
6
|
+
* ```
|
|
7
|
+
* lazy.customElements.setElementCreationCallback("moz-button", () => {
|
|
8
|
+
* import("chrome://global/content/elements/moz-button.mjs");
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
13
|
+
* @returns Map of tagName to module path
|
|
14
|
+
*/
|
|
15
|
+
export declare function scanCustomElementsRegistrations(engineDir: string): Promise<Map<string, string>>;
|
|
16
|
+
/**
|
|
17
|
+
* Scans the widgets directory to discover all MozLitElement custom elements.
|
|
18
|
+
*
|
|
19
|
+
* Each subdirectory starting with `moz-` that contains a `.mjs` file is
|
|
20
|
+
* considered a component. For each component, checks whether it has associated
|
|
21
|
+
* CSS, Fluent localization, and customElements.js registration.
|
|
22
|
+
*
|
|
23
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
24
|
+
* @returns Array of discovered components
|
|
25
|
+
*/
|
|
26
|
+
export declare function scanWidgetsDirectory(engineDir: string): Promise<ScannedComponent[]>;
|
|
27
|
+
/**
|
|
28
|
+
* Gets detailed information about a single component by tag name.
|
|
29
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
30
|
+
* @param tagName - Component tag name (e.g., "moz-button")
|
|
31
|
+
* @returns Component details, or null if not found in the source tree
|
|
32
|
+
*/
|
|
33
|
+
export declare function getComponentDetails(engineDir: string, tagName: string): Promise<ScannedComponent | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Checks whether a component directory exists in the engine source tree.
|
|
36
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
37
|
+
* @param tagName - Component tag name (e.g., "moz-button")
|
|
38
|
+
* @returns True if the component directory exists
|
|
39
|
+
*/
|
|
40
|
+
export declare function isComponentInEngine(engineDir: string, tagName: string): Promise<boolean>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { pathExists, readText } from '../utils/fs.js';
|
|
5
|
+
import { CUSTOM_ELEMENTS_JS } from './furnace-constants.js';
|
|
6
|
+
/** Path to the widgets directory within the engine source tree */
|
|
7
|
+
const WIDGETS_DIR = 'toolkit/content/widgets';
|
|
8
|
+
/** Path to the Fluent localization directory for toolkit global components */
|
|
9
|
+
const FTL_DIR = 'toolkit/locales/en-US/toolkit/global';
|
|
10
|
+
/**
|
|
11
|
+
* Parses customElements.js to extract tag-to-module mappings.
|
|
12
|
+
*
|
|
13
|
+
* Looks for registration patterns like:
|
|
14
|
+
* ```
|
|
15
|
+
* lazy.customElements.setElementCreationCallback("moz-button", () => {
|
|
16
|
+
* import("chrome://global/content/elements/moz-button.mjs");
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
21
|
+
* @returns Map of tagName to module path
|
|
22
|
+
*/
|
|
23
|
+
export async function scanCustomElementsRegistrations(engineDir) {
|
|
24
|
+
const registrations = new Map();
|
|
25
|
+
const filePath = join(engineDir, CUSTOM_ELEMENTS_JS);
|
|
26
|
+
if (!(await pathExists(filePath))) {
|
|
27
|
+
return registrations;
|
|
28
|
+
}
|
|
29
|
+
const content = await readText(filePath);
|
|
30
|
+
const lines = content.split('\n');
|
|
31
|
+
for (let i = 0; i < lines.length; i++) {
|
|
32
|
+
const line = lines[i];
|
|
33
|
+
if (line === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const callbackMatch = /setElementCreationCallback\(\s*"([^"]+)"/.exec(line);
|
|
36
|
+
if (!callbackMatch?.[1])
|
|
37
|
+
continue;
|
|
38
|
+
const tagName = callbackMatch[1];
|
|
39
|
+
let modulePath = '';
|
|
40
|
+
// Search the following lines for an import() statement
|
|
41
|
+
const searchEnd = Math.min(i + 5, lines.length);
|
|
42
|
+
for (let j = i + 1; j < searchEnd; j++) {
|
|
43
|
+
const importLine = lines[j];
|
|
44
|
+
if (importLine === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
const importMatch = /import\(\s*"([^"]+)"/.exec(importLine);
|
|
47
|
+
if (importMatch?.[1]) {
|
|
48
|
+
modulePath = importMatch[1];
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!modulePath) {
|
|
53
|
+
// No module path found in the lookahead lines; skip this entry
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
registrations.set(tagName, modulePath);
|
|
57
|
+
}
|
|
58
|
+
return registrations;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Scans the widgets directory to discover all MozLitElement custom elements.
|
|
62
|
+
*
|
|
63
|
+
* Each subdirectory starting with `moz-` that contains a `.mjs` file is
|
|
64
|
+
* considered a component. For each component, checks whether it has associated
|
|
65
|
+
* CSS, Fluent localization, and customElements.js registration.
|
|
66
|
+
*
|
|
67
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
68
|
+
* @returns Array of discovered components
|
|
69
|
+
*/
|
|
70
|
+
export async function scanWidgetsDirectory(engineDir) {
|
|
71
|
+
const widgetsPath = join(engineDir, WIDGETS_DIR);
|
|
72
|
+
if (!(await pathExists(widgetsPath))) {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
const entries = await readdir(widgetsPath, { withFileTypes: true });
|
|
76
|
+
const registrations = await scanCustomElementsRegistrations(engineDir);
|
|
77
|
+
const components = [];
|
|
78
|
+
for (const entry of entries) {
|
|
79
|
+
if (!entry.isDirectory() || !entry.name.startsWith('moz-')) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const tagName = entry.name;
|
|
83
|
+
const componentDir = join(widgetsPath, tagName);
|
|
84
|
+
const componentEntries = await readdir(componentDir, { withFileTypes: true });
|
|
85
|
+
// Only include directories that contain a .mjs file
|
|
86
|
+
const hasMjs = componentEntries.some((e) => e.isFile() && e.name.endsWith('.mjs'));
|
|
87
|
+
if (!hasMjs) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const hasCSS = componentEntries.some((e) => e.isFile() && e.name.endsWith('.css'));
|
|
91
|
+
const ftlPath = join(engineDir, FTL_DIR, `${tagName}.ftl`);
|
|
92
|
+
const hasFTL = await pathExists(ftlPath);
|
|
93
|
+
const isRegistered = registrations.has(tagName);
|
|
94
|
+
components.push({
|
|
95
|
+
tagName,
|
|
96
|
+
sourcePath: join(WIDGETS_DIR, tagName),
|
|
97
|
+
hasCSS,
|
|
98
|
+
hasFTL,
|
|
99
|
+
isRegistered,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return components;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Gets detailed information about a single component by tag name.
|
|
106
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
107
|
+
* @param tagName - Component tag name (e.g., "moz-button")
|
|
108
|
+
* @returns Component details, or null if not found in the source tree
|
|
109
|
+
*/
|
|
110
|
+
export async function getComponentDetails(engineDir, tagName) {
|
|
111
|
+
const componentDir = join(engineDir, WIDGETS_DIR, tagName);
|
|
112
|
+
if (!(await pathExists(componentDir))) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const entries = await readdir(componentDir, { withFileTypes: true });
|
|
116
|
+
const hasMjs = entries.some((e) => e.isFile() && e.name.endsWith('.mjs'));
|
|
117
|
+
if (!hasMjs) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const hasCSS = entries.some((e) => e.isFile() && e.name.endsWith('.css'));
|
|
121
|
+
const ftlPath = join(engineDir, FTL_DIR, `${tagName}.ftl`);
|
|
122
|
+
const hasFTL = await pathExists(ftlPath);
|
|
123
|
+
const registrations = await scanCustomElementsRegistrations(engineDir);
|
|
124
|
+
const isRegistered = registrations.has(tagName);
|
|
125
|
+
return {
|
|
126
|
+
tagName,
|
|
127
|
+
sourcePath: join(WIDGETS_DIR, tagName),
|
|
128
|
+
hasCSS,
|
|
129
|
+
hasFTL,
|
|
130
|
+
isRegistered,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Checks whether a component directory exists in the engine source tree.
|
|
135
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
136
|
+
* @param tagName - Component tag name (e.g., "moz-button")
|
|
137
|
+
* @returns True if the component directory exists
|
|
138
|
+
*/
|
|
139
|
+
export async function isComponentInEngine(engineDir, tagName) {
|
|
140
|
+
const componentDir = join(engineDir, WIDGETS_DIR, tagName);
|
|
141
|
+
return pathExists(componentDir);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=furnace-scanner.js.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ComponentType, SyncResult } from '../types/furnace.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the full content of a Storybook `.stories.mjs` file for a
|
|
4
|
+
* Furnace component.
|
|
5
|
+
*
|
|
6
|
+
* @param tagName - Component tag name (e.g. "moz-button")
|
|
7
|
+
* @param displayName - Human-readable name (e.g. "Button")
|
|
8
|
+
* @param type - Component classification (stock, override, custom)
|
|
9
|
+
* @returns Complete story file content
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateStoryContent(tagName: string, displayName: string, type: ComponentType, licenseHeader?: string, modulePath?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the path to the Storybook stories directory in the engine.
|
|
14
|
+
*
|
|
15
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
16
|
+
* @returns Absolute path to `browser/components/storybook/stories/`
|
|
17
|
+
*/
|
|
18
|
+
export declare function getStoriesDir(engineDir: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Synchronises Storybook story files for all Furnace-managed components.
|
|
21
|
+
*
|
|
22
|
+
* - Stock components: story created only if not already present.
|
|
23
|
+
* - Override components: story always regenerated.
|
|
24
|
+
* - Custom components: story always regenerated.
|
|
25
|
+
* - Stale story files (for components no longer in furnace.json) are removed.
|
|
26
|
+
*
|
|
27
|
+
* @param root - Root directory of the project
|
|
28
|
+
* @returns Summary of created, updated, and removed story files
|
|
29
|
+
*/
|
|
30
|
+
export declare function syncStories(root: string): Promise<SyncResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Removes the entire `stories/furnace/` directory from the engine.
|
|
33
|
+
*
|
|
34
|
+
* @param engineDir - Path to the Firefox engine source root
|
|
35
|
+
* @returns Number of files that were removed
|
|
36
|
+
*/
|
|
37
|
+
export declare function cleanStories(engineDir: string): Promise<number>;
|