extension-develop 4.1.20 → 4.1.21
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/672~0.mjs +24 -1
- package/dist/747~0.mjs +4 -2
- package/dist/832~0.mjs +1 -1
- package/dist/840~0.mjs +432 -20
- package/dist/950~0.mjs +15 -24
- package/dist/command-preview.d.ts +8 -0
- package/dist/dev-server/control-bridge/consumer-client.d.ts +10 -0
- package/dist/dev-server/control-bridge/contracts.d.ts +42 -0
- package/dist/dev-server/control-bridge/logs-query.d.ts +16 -0
- package/dist/dev-server~0.mjs +2 -0
- package/dist/lib/addon-lint.d.ts +4 -1
- package/dist/lib/build-summary.d.ts +11 -0
- package/dist/lib/chunk-dependency-provenance.d.ts +14 -0
- package/dist/lib/constants.d.ts +1 -1
- package/dist/lib/manifest-utils.d.ts +2 -0
- package/dist/lib/messages.d.ts +3 -3
- package/dist/lib/package-manager.d.ts +2 -0
- package/dist/plugin-browsers/index.d.ts +28 -0
- package/dist/plugin-compilation/env.d.ts +2 -0
- package/dist/plugin-js-frameworks/js-frameworks-lib/messages.d.ts +1 -0
- package/dist/plugin-js-frameworks/js-tools/solid.d.ts +3 -0
- package/dist/plugin-js-frameworks/js-tools/typescript.d.ts +16 -0
- package/dist/plugin-perf-budgets/categorize.d.ts +2 -1
- package/dist/plugin-perf-budgets/index.d.ts +1 -1
- package/dist/plugin-reload/classify-reload.d.ts +4 -0
- package/dist/plugin-reload/index.d.ts +18 -0
- package/dist/plugin-special-folders/folder-extensions/types.d.ts +13 -0
- package/dist/plugin-web-extension/feature-manifest/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/emitted-evidence.d.ts +22 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/patch-background.d.ts +9 -0
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults-lib/patch-web-resources.d.ts +7 -16
- package/dist/plugin-web-extension/feature-manifest/steps/apply-dev-defaults.d.ts +6 -2
- package/dist/plugin-web-extension/feature-manifest/steps/warn-gecko-unsupported-apis.d.ts +2 -13
- package/dist/plugin-web-extension/feature-scripts/messages.d.ts +5 -0
- package/dist/plugin-web-extension/feature-scripts/steps/warn-page-context-worker.d.ts +5 -0
- package/dist/plugin-web-extension/feature-web-resources/collect-entry-imports.d.ts +1 -0
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/messages.d.ts +1 -0
- package/dist/plugin-web-extension/feature-web-resources/web-resources-lib/unreachable-resources.d.ts +9 -0
- package/dist/rspack-config.d.ts +1 -1
- package/dist/rspack-config~0.mjs +430 -463
- package/dist/types.d.ts +190 -0
- package/package.json +1 -1
package/dist/672~0.mjs
CHANGED
|
@@ -104,6 +104,16 @@ function findDroppedVendorKeys(manifest, browser) {
|
|
|
104
104
|
walk(manifest, '');
|
|
105
105
|
return found;
|
|
106
106
|
}
|
|
107
|
+
function isValidManifestVersion(value) {
|
|
108
|
+
return 2 === value || 3 === value;
|
|
109
|
+
}
|
|
110
|
+
function findPrefixedManifestVersionKeys(manifest) {
|
|
111
|
+
if (!manifest || 'object' != typeof manifest) return [];
|
|
112
|
+
return Object.keys(manifest).filter((key)=>{
|
|
113
|
+
const colon = key.indexOf(':');
|
|
114
|
+
return colon > 0 && 'manifest_version' === key.substring(colon + 1);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
107
117
|
const THEME_DISQUALIFYING_KEYS = [
|
|
108
118
|
'background',
|
|
109
119
|
"content_scripts",
|
|
@@ -198,6 +208,19 @@ function entrySplitAcrossInitialFiles(entryName, surface, ownFile, extraFiles) {
|
|
|
198
208
|
lines.push(`Only a user-set optimization.splitChunks cache group does this. Use chunks: 'async' and import() the shared module: ${pintor.blue(SPLIT_ENTRY_RECIPE_URL)}`);
|
|
199
209
|
return lines.join('\n');
|
|
200
210
|
}
|
|
211
|
+
const PAGE_CONTEXT_SURFACES = {
|
|
212
|
+
content_script: "a content script",
|
|
213
|
+
script: "an injected script"
|
|
214
|
+
};
|
|
215
|
+
function workerStartedFromPageContext(assetName, surface) {
|
|
216
|
+
const lines = [];
|
|
217
|
+
lines.push(`${assetName} starts a worker from an extension URL, which the browser refuses in ${PAGE_CONTEXT_SURFACES[surface]}.`);
|
|
218
|
+
lines.push(`${pintor.gray('SCRIPT')} ${pintor.underline(assetName)}`);
|
|
219
|
+
lines.push("The worker file ships, but a worker script must be same-origin with the document that starts it, and this document is the page, so the worker never runs. Chromium throws a SecurityError and Firefox fires an error event on the worker.");
|
|
220
|
+
lines.push(`- Fetch the worker file first and start the worker from a blob: ${pintor.blue("new Worker(URL.createObjectURL(new Blob([await (await fetch(chrome.runtime.getURL('worker.js'))).text()])))")}`);
|
|
221
|
+
lines.push("- Or start the worker from an extension page, where the document is the extension and this spelling works as written.");
|
|
222
|
+
return lines.join('\n');
|
|
223
|
+
}
|
|
201
224
|
function fetchedFileDependencyMissing(assetName, literal, expectedPath) {
|
|
202
225
|
const lines = [];
|
|
203
226
|
lines.push(`${assetName} loads '${literal}' at runtime (fetch/XMLHttpRequest/new URL), but the file isn't in the output.`);
|
|
@@ -243,4 +266,4 @@ function compiledSourceSpelling(assetName, api, literal, emittedPath) {
|
|
|
243
266
|
lines.push(`Reference the emitted path: ${pintor.blue(emittedPath)}.`);
|
|
244
267
|
return lines.join('\n');
|
|
245
268
|
}
|
|
246
|
-
export { compiledSourceSpelling, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, filterKeysForThisBrowser, findDroppedVendorKeys, getURLDependencyMissing, importScriptsDependencyMissing, injectedCompiledSourceLiteral, injectedFileDependencyMissing, isStaticTheme, isStaticThemeSource, reservedScriptsFolder, runtimeSetSurfaceDependencyMissing, staticImportDependencyMissing };
|
|
269
|
+
export { compiledSourceSpelling, entrySplitAcrossInitialFiles, fetchedFileDependencyMissing, filterKeysForThisBrowser, findDroppedVendorKeys, findPrefixedManifestVersionKeys, getURLDependencyMissing, importScriptsDependencyMissing, injectedCompiledSourceLiteral, injectedFileDependencyMissing, isStaticTheme, isStaticThemeSource, isValidManifestVersion, reservedScriptsFolder, runtimeSetSurfaceDependencyMissing, staticImportDependencyMissing, workerStartedFromPageContext };
|
package/dist/747~0.mjs
CHANGED
|
@@ -69,10 +69,12 @@ function toRuntimeStylesheetModule(css) {
|
|
|
69
69
|
`var __extjsCssText = ${JSON.stringify(css)};`,
|
|
70
70
|
'function __extjsExtensionRoot() {',
|
|
71
71
|
' try {',
|
|
72
|
-
'
|
|
72
|
+
' var b = globalThis.browser;',
|
|
73
|
+
' if (typeof b === "object" && b && b.runtime && typeof b.runtime.getURL === "function") return String(b.runtime.getURL("/"));',
|
|
73
74
|
' } catch (error) {}',
|
|
74
75
|
' try {',
|
|
75
|
-
'
|
|
76
|
+
' var c = globalThis.chrome;',
|
|
77
|
+
' if (typeof c === "object" && c && c.runtime && typeof c.runtime.getURL === "function") return String(c.runtime.getURL("/"));',
|
|
76
78
|
' } catch (error) {}',
|
|
77
79
|
' try {',
|
|
78
80
|
' var base = (typeof globalThis === "object" && globalThis && globalThis.__EXTJS_EXTENSION_BASE__) ? String(globalThis.__EXTJS_EXTENSION_BASE__) : "";',
|
package/dist/832~0.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
|
|
|
19
19
|
import * as __rspack_external_node_os_4f3c9d58 from "node:os";
|
|
20
20
|
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
21
21
|
import * as __rspack_external_node_vm_ef240610 from "node:vm";
|
|
22
|
-
var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.
|
|
22
|
+
var package_namespaceObject = /*#__PURE__*/ JSON.parse('{"rE":"4.1.21","El":{"@prefresh/core":"1.5.9","@prefresh/utils":"1.2.1","@rspack/core":"^2.2.3","@rspack/dev-server":"2.1.0","@rspack/plugin-preact-refresh":"2.0.1","@rspack/plugin-react-refresh":"2.0.2","@vue/compiler-sfc":"3.5.26","acorn":"^8.16.0","browser-extension-manifest-fields":"^3.0.1","case-sensitive-paths-webpack-plugin":"^2.4.0","content-security-policy-parser":"^0.6.0","cross-spawn":"^7.0.6","dotenv":"^17.2.3","es-module-lexer":"^3.0.2","extension-from-store":"^0.2.5","fflate":"^0.8.3","go-git-it":"^5.1.5","ignore":"^7.0.5","less":"4.6.7","less-loader":"13.0.0","parse5-utilities":"^1.0.0","pintor":"0.3.0","postcss":"8.5.23","postcss-loader":"8.2.1","postcss-preset-env":"11.1.1","postcss-scss":"4.0.9","preact":"10.27.3","prefers-yarn":"2.0.1","react-refresh":"0.18.0","sass-loader":"17.0.0","schema-utils":"^4.3.3","svelte-loader":"3.2.4","tiny-glob":"^0.2.9","vue":"3.5.26","vue-loader":"17.4.2","webextension-polyfill":"^0.12.0","webpack-merge":"^6.0.1","webpack-target-webextension":"^2.1.3","ws":"^8.20.1"}}');
|
|
23
23
|
const preloadedEnvKeys = new Set();
|
|
24
24
|
function getPreloadedEnvKeys() {
|
|
25
25
|
return preloadedEnvKeys;
|
package/dist/840~0.mjs
CHANGED
|
@@ -3,13 +3,15 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
4
|
import { spawn, sync } from "cross-spawn";
|
|
5
5
|
import { buildExecEnv, detectPackageManagerFromLockfile } from "prefers-yarn";
|
|
6
|
-
import "pintor";
|
|
6
|
+
import pintor from "pintor";
|
|
7
|
+
import { DefinePlugin } from "@rspack/core";
|
|
8
|
+
import { pathToFileURL } from "node:url";
|
|
7
9
|
import { EventEmitter } from "node:events";
|
|
8
|
-
import {
|
|
10
|
+
import { humanWarn, browserRowValue, CODES, ENVELOPE, prefix as messaging_prefix, card, isDebug, claimCardKey, isMachineOutput } from "./852~0.mjs";
|
|
9
11
|
import { package_namespaceObject, loadCommandConfig, DEV_COMMAND_DEFAULTS, stampReadyDistExtensionId, loadProjectConfigDefaults, mergeOptionLayers, stampReadyKnownExtensionId, assertNoManagedDependencyConflicts, loadCustomConfig, START_BUILD_DEFAULTS, loadBrowserConfig, resolveCompanionExtensionsConfig, BUILD_COMMAND_DEFAULTS, getSpecialFoldersDataForProjectRoot, withDarkMode } from "./832~0.mjs";
|
|
10
12
|
import { stripBom, hasProjectDependency, parseJsonSafe, findNearestProjectManifestDirSync } from "./731~0.mjs";
|
|
11
13
|
import { isGeckoBasedBrowser } from "./331~0.mjs";
|
|
12
|
-
import { buildWarningsDetails, buildFailed, getDirs, zipArtifactReady, projectInstallFallbackToNpm, debugDirs, browserLaunchFailed, buildSummaryPath, addonLintMore, extensionLoadRecovered, writingTypeDefinitionsError, extensionLoadStillRefused, projectInstallScriptsDisabled, authorInstallNotice, addonLintFailed, buildAssetsTree, addonLintSummary, addonLintFinding, configBrowserOrThrow, needsInstall, projectInstallInWorkspaceRoot, buildCommandFailed, addonLintNotInstalled, writingTypeDefinitions, buildComplete, ensureSessionStateInProjectGitignore, ensureSessionArtifactsIgnoreFile, debugBrowser, normalizeBrowser, debugOutputPath, devCommandFailed,
|
|
14
|
+
import { buildWarningsDetails, buildFailed, getDirs, zipArtifactReady, projectInstallFallbackToNpm, debugDirs, addonLintDependencyAttribution, browserLaunchFailed, buildSummaryPath, addonLintMore, extensionLoadRecovered, writingTypeDefinitionsError, extensionLoadStillRefused, projectInstallScriptsDisabled, authorInstallNotice, addonLintFailed, buildAssetsTree, addonLintSummary, addonLintFinding, configBrowserOrThrow, needsInstall, projectInstallInWorkspaceRoot, buildCommandFailed, addonLintNotInstalled, writingTypeDefinitions, buildComplete, ensureSessionStateInProjectGitignore, ensureSessionArtifactsIgnoreFile, debugBrowser, normalizeBrowser, debugOutputPath, devCommandFailed, buildShareHint, getDistPath, getProjectStructure, debugSplitChunksNarrowed } from "./950~0.mjs";
|
|
13
15
|
import { publicRootsFor } from "./105~0.mjs";
|
|
14
16
|
import { getCanonicalContentScriptEntryName } from "./640~0.mjs";
|
|
15
17
|
import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
|
|
@@ -775,7 +777,7 @@ function readPnpmWorkspacePackages(workspaceRoot) {
|
|
|
775
777
|
for(let j = i + 1; j < lines.length; j++){
|
|
776
778
|
const line = lines[j];
|
|
777
779
|
if (!line.trim() || line.trim().startsWith('#')) continue;
|
|
778
|
-
const item = /^\s
|
|
780
|
+
const item = /^\s*-\s*(.+)$/.exec(line);
|
|
779
781
|
if (!item) break;
|
|
780
782
|
const value = cleanYamlListItem(item[1]);
|
|
781
783
|
if (value) patterns.push(value);
|
|
@@ -900,19 +902,21 @@ function buildSpawnInvocation(command, args) {
|
|
|
900
902
|
args
|
|
901
903
|
};
|
|
902
904
|
}
|
|
903
|
-
function
|
|
905
|
+
function spawnInstallCommand(command, args, options) {
|
|
904
906
|
const invocation = buildSpawnInvocation(command, args);
|
|
905
907
|
const env = buildExecEnv();
|
|
906
|
-
|
|
908
|
+
return spawn(invocation.command, invocation.args, {
|
|
909
|
+
cwd: options?.cwd,
|
|
910
|
+
stdio: options?.stdio ?? 'ignore',
|
|
911
|
+
env: {
|
|
912
|
+
...env || process.env,
|
|
913
|
+
...options?.env
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
function execInstallCommand(command, args, options) {
|
|
907
918
|
return new Promise((resolve, reject)=>{
|
|
908
|
-
const child =
|
|
909
|
-
cwd: options?.cwd,
|
|
910
|
-
stdio,
|
|
911
|
-
env: {
|
|
912
|
-
...env || process.env,
|
|
913
|
-
...options?.env
|
|
914
|
-
}
|
|
915
|
-
});
|
|
919
|
+
const child = spawnInstallCommand(command, args, options);
|
|
916
920
|
child.on('close', (code)=>{
|
|
917
921
|
if (0 !== code) reject(new Error(`Install failed with exit code ${code}`));
|
|
918
922
|
else resolve();
|
|
@@ -1340,7 +1344,14 @@ function collectAddonLintLines(output) {
|
|
|
1340
1344
|
...warnings.map((finding)=>toLine('warning', finding))
|
|
1341
1345
|
].filter((line)=>!DUPLICATED_BY_BUILD_WARNINGS.has(line.code));
|
|
1342
1346
|
}
|
|
1343
|
-
function
|
|
1347
|
+
function attributionFor(location, chunkProvenance) {
|
|
1348
|
+
if (!chunkProvenance || 0 === chunkProvenance.size) return '';
|
|
1349
|
+
const file = location.split(':')[0].replace(/\\/g, '/').replace(/^\.?\//, '');
|
|
1350
|
+
const provenance = chunkProvenance.get(file);
|
|
1351
|
+
if (!provenance) return '';
|
|
1352
|
+
return addonLintDependencyAttribution(provenance.packages, provenance.onlyDependencies);
|
|
1353
|
+
}
|
|
1354
|
+
function formatAddonLintFindings(output, distDisplay, maxPrinted = ADDON_LINT_MAX_PRINTED, chunkProvenance) {
|
|
1344
1355
|
const all = collectAddonLintLines(output);
|
|
1345
1356
|
if (0 === all.length) return {
|
|
1346
1357
|
findings: 0,
|
|
@@ -1351,7 +1362,7 @@ function formatAddonLintFindings(output, distDisplay, maxPrinted = ADDON_LINT_MA
|
|
|
1351
1362
|
const shown = all.slice(0, Math.max(0, maxPrinted));
|
|
1352
1363
|
const lines = [
|
|
1353
1364
|
addonLintSummary(errorCount, warningCount, distDisplay),
|
|
1354
|
-
...shown.map((line)=>addonLintFinding(line.level, line.code, line.message, line.location))
|
|
1365
|
+
...shown.map((line)=>addonLintFinding(line.level, line.code, line.message, line.location, attributionFor(line.location, chunkProvenance)))
|
|
1355
1366
|
];
|
|
1356
1367
|
if (all.length > shown.length) lines.push(addonLintMore(all.length - shown.length, distDisplay));
|
|
1357
1368
|
return {
|
|
@@ -1424,7 +1435,7 @@ async function runAddonLint(input) {
|
|
|
1424
1435
|
}), input.timeoutMs ?? ADDON_LINT_TIMEOUT_MS);
|
|
1425
1436
|
return {
|
|
1426
1437
|
status: 'linted',
|
|
1427
|
-
...formatAddonLintFindings(output, input.distDisplay)
|
|
1438
|
+
...formatAddonLintFindings(output, input.distDisplay, ADDON_LINT_MAX_PRINTED, input.chunkProvenance?.())
|
|
1428
1439
|
};
|
|
1429
1440
|
} catch (error) {
|
|
1430
1441
|
return {
|
|
@@ -1514,6 +1525,85 @@ function getBuildSummary(browser, info, outputPath) {
|
|
|
1514
1525
|
} : {}
|
|
1515
1526
|
};
|
|
1516
1527
|
}
|
|
1528
|
+
function packageNameFromPath(candidate) {
|
|
1529
|
+
const normalized = candidate.replace(/\\/g, '/');
|
|
1530
|
+
const marker = '/node_modules/';
|
|
1531
|
+
const at = normalized.lastIndexOf(marker);
|
|
1532
|
+
if (-1 === at) return null;
|
|
1533
|
+
const rest = normalized.slice(at + marker.length);
|
|
1534
|
+
const segments = rest.split('/').filter(Boolean);
|
|
1535
|
+
if (0 === segments.length) return null;
|
|
1536
|
+
if (segments[0].startsWith('@')) return segments.length > 1 ? `${segments[0]}/${segments[1]}` : null;
|
|
1537
|
+
if (segments[0].includes('@') && segments.length > 1) return packageNameFromPath(`/node_modules/${segments.slice(1).join('/')}`);
|
|
1538
|
+
return segments[0];
|
|
1539
|
+
}
|
|
1540
|
+
function isAbsoluteFilePath(candidate) {
|
|
1541
|
+
return /^([a-zA-Z]:[\\/]|[\\/])/.test(candidate);
|
|
1542
|
+
}
|
|
1543
|
+
function pathOfModule(moduleObj) {
|
|
1544
|
+
const candidate = moduleObj;
|
|
1545
|
+
if ('string' == typeof candidate?.resource && candidate.resource) return candidate.resource;
|
|
1546
|
+
if ('function' == typeof candidate?.identifier) {
|
|
1547
|
+
const identifier = candidate.identifier();
|
|
1548
|
+
if ('string' == typeof identifier && identifier) return identifier;
|
|
1549
|
+
}
|
|
1550
|
+
return null;
|
|
1551
|
+
}
|
|
1552
|
+
function collectChunkDependencyProvenance(compilation) {
|
|
1553
|
+
const provenance = new Map();
|
|
1554
|
+
const chunkGraph = compilation?.chunkGraph;
|
|
1555
|
+
const chunks = compilation?.chunks;
|
|
1556
|
+
if (!chunkGraph?.getChunkModulesIterable || !chunks) return provenance;
|
|
1557
|
+
for (const chunk of chunks){
|
|
1558
|
+
const files = chunk?.files;
|
|
1559
|
+
if (!files) continue;
|
|
1560
|
+
let modules = [];
|
|
1561
|
+
try {
|
|
1562
|
+
modules = Array.from(chunkGraph.getChunkModulesIterable(chunk));
|
|
1563
|
+
} catch {
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
const packages = new Set();
|
|
1567
|
+
let counted = 0;
|
|
1568
|
+
let fromDependencies = 0;
|
|
1569
|
+
for (const moduleObj of modules){
|
|
1570
|
+
const modulePath = pathOfModule(moduleObj);
|
|
1571
|
+
if (!modulePath) continue;
|
|
1572
|
+
if (!isAbsoluteFilePath(modulePath)) continue;
|
|
1573
|
+
counted += 1;
|
|
1574
|
+
const packageName = packageNameFromPath(modulePath);
|
|
1575
|
+
if (packageName) {
|
|
1576
|
+
fromDependencies += 1;
|
|
1577
|
+
packages.add(packageName);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (0 === packages.size) continue;
|
|
1581
|
+
const entry = {
|
|
1582
|
+
packages: [
|
|
1583
|
+
...packages
|
|
1584
|
+
].sort(),
|
|
1585
|
+
onlyDependencies: counted > 0 && fromDependencies === counted
|
|
1586
|
+
};
|
|
1587
|
+
for (const file of files){
|
|
1588
|
+
if ('string' != typeof file || !file.endsWith('.js')) continue;
|
|
1589
|
+
const existing = provenance.get(file);
|
|
1590
|
+
if (!existing) {
|
|
1591
|
+
provenance.set(file, entry);
|
|
1592
|
+
continue;
|
|
1593
|
+
}
|
|
1594
|
+
provenance.set(file, {
|
|
1595
|
+
packages: [
|
|
1596
|
+
...new Set([
|
|
1597
|
+
...existing.packages,
|
|
1598
|
+
...entry.packages
|
|
1599
|
+
])
|
|
1600
|
+
].sort(),
|
|
1601
|
+
onlyDependencies: existing.onlyDependencies && entry.onlyDependencies
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
return provenance;
|
|
1606
|
+
}
|
|
1517
1607
|
async function ensureUserProjectDependencies(packageJsonDir) {
|
|
1518
1608
|
const member = findPnpmWorkspaceMember(packageJsonDir);
|
|
1519
1609
|
if (!needsInstall(packageJsonDir, member?.root)) return;
|
|
@@ -1805,6 +1895,9 @@ function isUsingJSFramework(projectPath) {
|
|
|
1805
1895
|
function isUsingIntegration(name) {
|
|
1806
1896
|
return `integration use=${name}`;
|
|
1807
1897
|
}
|
|
1898
|
+
function solidIsNotSupported() {
|
|
1899
|
+
return `${messaging_prefix('warn')} Solid is not a supported framework, so this project compiles through the JSX runtime only.\nA signal read in a child position, like ${pintor.yellow('{count()}')}, renders once and does not update.\nOnly Solid's own compiler makes that expression reactive, and the JSX runtime cannot recover it.`;
|
|
1900
|
+
}
|
|
1808
1901
|
function creatingTSConfig() {
|
|
1809
1902
|
return `${messaging_prefix('info')} Creating a default tsconfig.json…`;
|
|
1810
1903
|
}
|
|
@@ -1824,6 +1917,319 @@ function jsFrameworksHmrSummary(enabled, frameworks) {
|
|
|
1824
1917
|
const names = frameworks.length > 0 ? frameworks.join(',') : 'none';
|
|
1825
1918
|
return `${messaging_prefix('debug')} js hmr=${enabled ? 'enabled' : 'disabled'} frameworks=${names}`;
|
|
1826
1919
|
}
|
|
1920
|
+
let userMessageDelivered = false;
|
|
1921
|
+
function isUsingPreact(projectPath) {
|
|
1922
|
+
if (hasDependency(projectPath, 'preact')) {
|
|
1923
|
+
if (!userMessageDelivered) {
|
|
1924
|
+
if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('Preact')}`);
|
|
1925
|
+
userMessageDelivered = true;
|
|
1926
|
+
}
|
|
1927
|
+
return true;
|
|
1928
|
+
}
|
|
1929
|
+
return false;
|
|
1930
|
+
}
|
|
1931
|
+
async function maybeUsePreact(projectPath) {
|
|
1932
|
+
if (!isUsingPreact(projectPath)) return;
|
|
1933
|
+
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
1934
|
+
const resolveFromProject = (id)=>{
|
|
1935
|
+
try {
|
|
1936
|
+
return requireFromProject.resolve(id);
|
|
1937
|
+
} catch {
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
};
|
|
1941
|
+
const preactPkgJson = resolveFromProject('preact/package.json');
|
|
1942
|
+
const preactDir = preactPkgJson ? __rspack_external_node_path_806ed179.dirname(preactPkgJson) : void 0;
|
|
1943
|
+
const preactCompat = resolveFromProject('preact/compat');
|
|
1944
|
+
const preactTestUtils = resolveFromProject('preact/test-utils');
|
|
1945
|
+
const preactJsxRuntime = resolveFromProject('preact/jsx-runtime');
|
|
1946
|
+
const preactJsxDevRuntime = resolveFromProject('preact/jsx-dev-runtime');
|
|
1947
|
+
const alias = {};
|
|
1948
|
+
if (preactJsxRuntime) alias['preact/jsx-runtime'] = preactJsxRuntime;
|
|
1949
|
+
if (preactJsxDevRuntime) alias['preact/jsx-dev-runtime'] = preactJsxDevRuntime;
|
|
1950
|
+
if (preactDir) alias.preact = preactDir;
|
|
1951
|
+
if (preactCompat) {
|
|
1952
|
+
alias.react = preactCompat;
|
|
1953
|
+
alias['react-dom'] = preactCompat;
|
|
1954
|
+
}
|
|
1955
|
+
if (preactTestUtils) alias['react-dom/test-utils'] = preactTestUtils;
|
|
1956
|
+
if (preactJsxRuntime) alias['react/jsx-runtime'] = preactJsxRuntime;
|
|
1957
|
+
if (preactJsxDevRuntime) alias['react/jsx-dev-runtime'] = preactJsxDevRuntime;
|
|
1958
|
+
return {
|
|
1959
|
+
plugins: [],
|
|
1960
|
+
loaders: void 0,
|
|
1961
|
+
alias
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
let react_userMessageDelivered = false;
|
|
1965
|
+
function isUsingReact(projectPath) {
|
|
1966
|
+
if (hasDependency(projectPath, 'react')) {
|
|
1967
|
+
if (!react_userMessageDelivered) {
|
|
1968
|
+
if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('React')}`);
|
|
1969
|
+
react_userMessageDelivered = true;
|
|
1970
|
+
}
|
|
1971
|
+
return true;
|
|
1972
|
+
}
|
|
1973
|
+
return false;
|
|
1974
|
+
}
|
|
1975
|
+
async function maybeUseReact(projectPath, options = {}) {
|
|
1976
|
+
if (!isUsingReact(projectPath)) return;
|
|
1977
|
+
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
1978
|
+
let reactPath;
|
|
1979
|
+
let reactDomPath;
|
|
1980
|
+
let reactDomClientPath;
|
|
1981
|
+
let jsxRuntimePath;
|
|
1982
|
+
let jsxDevRuntimePath;
|
|
1983
|
+
try {
|
|
1984
|
+
reactPath = requireFromProject.resolve('react');
|
|
1985
|
+
} catch {}
|
|
1986
|
+
try {
|
|
1987
|
+
reactDomPath = requireFromProject.resolve('react-dom');
|
|
1988
|
+
} catch {}
|
|
1989
|
+
try {
|
|
1990
|
+
reactDomClientPath = requireFromProject.resolve('react-dom/client');
|
|
1991
|
+
} catch {}
|
|
1992
|
+
try {
|
|
1993
|
+
jsxRuntimePath = requireFromProject.resolve('react/jsx-runtime');
|
|
1994
|
+
} catch {}
|
|
1995
|
+
try {
|
|
1996
|
+
jsxDevRuntimePath = requireFromProject.resolve('react/jsx-dev-runtime');
|
|
1997
|
+
} catch {}
|
|
1998
|
+
const alias = {};
|
|
1999
|
+
if (reactPath) alias.react$ = reactPath;
|
|
2000
|
+
if (reactDomPath) alias['react-dom$'] = reactDomPath;
|
|
2001
|
+
if (reactDomClientPath) alias['react-dom/client'] = reactDomClientPath;
|
|
2002
|
+
if (jsxRuntimePath) alias['react/jsx-runtime'] = jsxRuntimePath;
|
|
2003
|
+
if (jsxDevRuntimePath) alias['react/jsx-dev-runtime'] = jsxDevRuntimePath;
|
|
2004
|
+
if (true === options.disableRefresh) return {
|
|
2005
|
+
plugins: [],
|
|
2006
|
+
loaders: void 0,
|
|
2007
|
+
alias
|
|
2008
|
+
};
|
|
2009
|
+
resolveOptionalContractPackageWithoutInstall({
|
|
2010
|
+
contractId: 'react-refresh',
|
|
2011
|
+
projectPath,
|
|
2012
|
+
dependencyId: 'react-refresh'
|
|
2013
|
+
});
|
|
2014
|
+
const ReactRefreshPlugin = loadOptionalContractModuleWithoutInstall({
|
|
2015
|
+
contractId: 'react-refresh',
|
|
2016
|
+
projectPath,
|
|
2017
|
+
dependencyId: '@rspack/plugin-react-refresh',
|
|
2018
|
+
moduleAdapter: (mod)=>mod && (mod.default || mod.ReactRefreshRspackPlugin) || mod
|
|
2019
|
+
});
|
|
2020
|
+
const reactPlugins = [
|
|
2021
|
+
new ReactRefreshPlugin({
|
|
2022
|
+
overlay: false,
|
|
2023
|
+
...void 0 === options.refreshExclude ? {} : {
|
|
2024
|
+
exclude: options.refreshExclude
|
|
2025
|
+
}
|
|
2026
|
+
})
|
|
2027
|
+
];
|
|
2028
|
+
return {
|
|
2029
|
+
plugins: reactPlugins,
|
|
2030
|
+
loaders: void 0,
|
|
2031
|
+
alias
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
let solid_userMessageDelivered = false;
|
|
2035
|
+
function isUsingSolid(projectPath) {
|
|
2036
|
+
if (hasDependency(projectPath, 'solid-js')) {
|
|
2037
|
+
if (!solid_userMessageDelivered) {
|
|
2038
|
+
if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('Solid')}`);
|
|
2039
|
+
humanWarn(solidIsNotSupported());
|
|
2040
|
+
solid_userMessageDelivered = true;
|
|
2041
|
+
}
|
|
2042
|
+
return true;
|
|
2043
|
+
}
|
|
2044
|
+
return false;
|
|
2045
|
+
}
|
|
2046
|
+
function pickEsmCondition(entry) {
|
|
2047
|
+
if ('string' == typeof entry) return entry;
|
|
2048
|
+
if (!entry || 'object' != typeof entry) return;
|
|
2049
|
+
const conditions = entry;
|
|
2050
|
+
for (const name of [
|
|
2051
|
+
'browser',
|
|
2052
|
+
'import',
|
|
2053
|
+
'module',
|
|
2054
|
+
'default'
|
|
2055
|
+
]){
|
|
2056
|
+
const picked = pickEsmCondition(conditions[name]);
|
|
2057
|
+
if (picked) return picked;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
function resolveSolidHyperscript(resolveFromProject) {
|
|
2061
|
+
const packageJsonPath = resolveFromProject('solid-js/package.json');
|
|
2062
|
+
if (packageJsonPath) try {
|
|
2063
|
+
const packageJson = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(packageJsonPath, 'utf-8'));
|
|
2064
|
+
const subpath = pickEsmCondition(packageJson?.exports?.['./h']);
|
|
2065
|
+
if (subpath) {
|
|
2066
|
+
const esmPath = __rspack_external_node_path_806ed179.resolve(__rspack_external_node_path_806ed179.dirname(packageJsonPath), subpath);
|
|
2067
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(esmPath)) return esmPath;
|
|
2068
|
+
}
|
|
2069
|
+
} catch {}
|
|
2070
|
+
return resolveFromProject('solid-js/h/dist/h.js') || resolveFromProject('solid-js/h');
|
|
2071
|
+
}
|
|
2072
|
+
async function maybeUseSolid(projectPath) {
|
|
2073
|
+
if (!isUsingSolid(projectPath)) return;
|
|
2074
|
+
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2075
|
+
const resolveFromProject = (id)=>{
|
|
2076
|
+
try {
|
|
2077
|
+
return requireFromProject.resolve(id);
|
|
2078
|
+
} catch {
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
};
|
|
2082
|
+
const adapter = resolveDevelopDistFile('solid-jsx-runtime');
|
|
2083
|
+
const hyperscript = resolveSolidHyperscript(resolveFromProject);
|
|
2084
|
+
const alias = {
|
|
2085
|
+
'solid-js/jsx-runtime$': adapter,
|
|
2086
|
+
'solid-js/jsx-dev-runtime$': adapter
|
|
2087
|
+
};
|
|
2088
|
+
if (hyperscript) alias['solid-js/h$'] = hyperscript;
|
|
2089
|
+
return {
|
|
2090
|
+
plugins: [],
|
|
2091
|
+
loaders: void 0,
|
|
2092
|
+
alias
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
2095
|
+
let load_loader_options_userMessageDelivered = false;
|
|
2096
|
+
function resolveLoaderConfigPath(projectPath, framework) {
|
|
2097
|
+
const candidates = [
|
|
2098
|
+
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.ts`),
|
|
2099
|
+
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.mts`),
|
|
2100
|
+
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.js`),
|
|
2101
|
+
__rspack_external_node_path_806ed179.join(projectPath, `${framework}.loader.mjs`)
|
|
2102
|
+
];
|
|
2103
|
+
return candidates.find((p)=>__rspack_external_node_fs_1b05aee1.existsSync(p)) || null;
|
|
2104
|
+
}
|
|
2105
|
+
async function loadLoaderOptions(projectPath, framework) {
|
|
2106
|
+
const configPath = resolveLoaderConfigPath(projectPath, framework);
|
|
2107
|
+
if (configPath) {
|
|
2108
|
+
if (!load_loader_options_userMessageDelivered && isDebug()) {
|
|
2109
|
+
const display = __rspack_external_node_path_806ed179.basename(configPath);
|
|
2110
|
+
console.log(isUsingCustomLoader(display));
|
|
2111
|
+
load_loader_options_userMessageDelivered = true;
|
|
2112
|
+
}
|
|
2113
|
+
try {
|
|
2114
|
+
const module = await import(pathToFileURL(configPath).href);
|
|
2115
|
+
return module.default || module;
|
|
2116
|
+
} catch (err) {
|
|
2117
|
+
const error = err;
|
|
2118
|
+
console.error(`Error loading ${framework} loader options: ${error.message}`);
|
|
2119
|
+
throw err;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
return null;
|
|
2123
|
+
}
|
|
2124
|
+
let vue_userMessageDelivered = false;
|
|
2125
|
+
function isUsingVue(projectPath) {
|
|
2126
|
+
const using = hasDependency(projectPath, 'vue');
|
|
2127
|
+
if (using && !vue_userMessageDelivered) {
|
|
2128
|
+
if (isDebug()) console.log(`${messaging_prefix('debug')} ${isUsingIntegration('Vue')}`);
|
|
2129
|
+
vue_userMessageDelivered = true;
|
|
2130
|
+
}
|
|
2131
|
+
return using;
|
|
2132
|
+
}
|
|
2133
|
+
function resolveVueBundlerEntry(requireFromProject, id) {
|
|
2134
|
+
try {
|
|
2135
|
+
const manifestPath = requireFromProject.resolve(`${id}/package.json`);
|
|
2136
|
+
const manifest = JSON.parse(__rspack_external_node_fs_1b05aee1.readFileSync(manifestPath, 'utf8'));
|
|
2137
|
+
if ('string' == typeof manifest.module && manifest.module) {
|
|
2138
|
+
const entry = __rspack_external_node_path_806ed179.join(__rspack_external_node_path_806ed179.dirname(manifestPath), manifest.module);
|
|
2139
|
+
if (__rspack_external_node_fs_1b05aee1.existsSync(entry)) return entry;
|
|
2140
|
+
}
|
|
2141
|
+
} catch {}
|
|
2142
|
+
try {
|
|
2143
|
+
return requireFromProject.resolve(id);
|
|
2144
|
+
} catch {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
async function maybeUseVue(projectPath, mode = 'development') {
|
|
2149
|
+
if (!isUsingVue(projectPath)) return;
|
|
2150
|
+
const vueLoaderPath = await ensureOptionalContractPackageResolved({
|
|
2151
|
+
contractId: 'vue',
|
|
2152
|
+
projectPath,
|
|
2153
|
+
dependencyId: 'vue-loader'
|
|
2154
|
+
});
|
|
2155
|
+
const VueLoaderPlugin = await ensureOptionalContractModuleLoaded({
|
|
2156
|
+
contractId: 'vue',
|
|
2157
|
+
projectPath,
|
|
2158
|
+
dependencyId: 'vue-loader',
|
|
2159
|
+
moduleAdapter: (mod)=>mod?.VueLoaderPlugin || mod?.default?.VueLoaderPlugin
|
|
2160
|
+
});
|
|
2161
|
+
const customOptions = await loadLoaderOptions(projectPath, 'vue');
|
|
2162
|
+
const defaultLoaders = [
|
|
2163
|
+
{
|
|
2164
|
+
test: /\.vue$/,
|
|
2165
|
+
loader: vueLoaderPath,
|
|
2166
|
+
options: {
|
|
2167
|
+
experimentalInlineMatchResource: true,
|
|
2168
|
+
...customOptions || {}
|
|
2169
|
+
},
|
|
2170
|
+
include: projectPath,
|
|
2171
|
+
exclude: /node_modules/
|
|
2172
|
+
}
|
|
2173
|
+
];
|
|
2174
|
+
const isProd = 'production' === mode;
|
|
2175
|
+
const defaultPlugins = [
|
|
2176
|
+
new VueLoaderPlugin(),
|
|
2177
|
+
new DefinePlugin({
|
|
2178
|
+
__VUE_OPTIONS_API__: JSON.stringify(true),
|
|
2179
|
+
__VUE_PROD_DEVTOOLS__: JSON.stringify(!isProd),
|
|
2180
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: JSON.stringify(!isProd)
|
|
2181
|
+
})
|
|
2182
|
+
];
|
|
2183
|
+
const requireFromProject = createRequire(__rspack_external_node_path_806ed179.join(projectPath, 'package.json'));
|
|
2184
|
+
const resolveFromProject = (id)=>resolveVueBundlerEntry(requireFromProject, id);
|
|
2185
|
+
const alias = {};
|
|
2186
|
+
const vuePath = resolveFromProject('vue');
|
|
2187
|
+
const vueRuntimeDom = resolveFromProject('@vue/runtime-dom');
|
|
2188
|
+
const vueRuntimeCore = resolveFromProject('@vue/runtime-core');
|
|
2189
|
+
const vueShared = resolveFromProject('@vue/shared');
|
|
2190
|
+
if (vuePath) alias.vue$ = vuePath;
|
|
2191
|
+
if (vueRuntimeDom) alias['@vue/runtime-dom'] = vueRuntimeDom;
|
|
2192
|
+
if (vueRuntimeCore) alias['@vue/runtime-core'] = vueRuntimeCore;
|
|
2193
|
+
if (vueShared) alias['@vue/shared'] = vueShared;
|
|
2194
|
+
return {
|
|
2195
|
+
plugins: defaultPlugins,
|
|
2196
|
+
loaders: defaultLoaders,
|
|
2197
|
+
alias
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2200
|
+
function isUsingJsxFramework(projectPath) {
|
|
2201
|
+
return isUsingReact(projectPath) || isUsingPreact(projectPath) || isUsingSolid(projectPath) || isUsingVue(projectPath);
|
|
2202
|
+
}
|
|
2203
|
+
function getJsxImportSource(projectPath) {
|
|
2204
|
+
if (isUsingSolid(projectPath)) return 'solid-js';
|
|
2205
|
+
if (isUsingPreact(projectPath) && !isUsingReact(projectPath)) return 'preact';
|
|
2206
|
+
if (isUsingVue(projectPath) && !isUsingReact(projectPath) && !isUsingPreact(projectPath)) return 'vue';
|
|
2207
|
+
return 'react';
|
|
2208
|
+
}
|
|
2209
|
+
function swcParserForFile(resourcePath, jsxInPlainJs) {
|
|
2210
|
+
const clean = String(resourcePath || '').split('?')[0];
|
|
2211
|
+
const ext = __rspack_external_node_path_806ed179.extname(clean).toLowerCase();
|
|
2212
|
+
if ('.tsx' === ext || '.mtsx' === ext) return {
|
|
2213
|
+
syntax: "typescript",
|
|
2214
|
+
tsx: true,
|
|
2215
|
+
dynamicImport: true
|
|
2216
|
+
};
|
|
2217
|
+
if ('.ts' === ext || '.mts' === ext || '.cts' === ext) return {
|
|
2218
|
+
syntax: "typescript",
|
|
2219
|
+
tsx: false,
|
|
2220
|
+
dynamicImport: true
|
|
2221
|
+
};
|
|
2222
|
+
if ('.jsx' === ext || '.mjsx' === ext) return {
|
|
2223
|
+
syntax: "ecmascript",
|
|
2224
|
+
jsx: true,
|
|
2225
|
+
dynamicImport: true
|
|
2226
|
+
};
|
|
2227
|
+
return {
|
|
2228
|
+
syntax: "ecmascript",
|
|
2229
|
+
jsx: jsxInPlainJs,
|
|
2230
|
+
dynamicImport: true
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
1827
2233
|
let hasShownUserMessage = false;
|
|
1828
2234
|
function findNearestPackageJsonDirectory(startPath) {
|
|
1829
2235
|
return findNearestProjectManifestDirSync(startPath, 6);
|
|
@@ -1884,13 +2290,18 @@ function ensureTypeScriptConfig(projectPath) {
|
|
|
1884
2290
|
}
|
|
1885
2291
|
}
|
|
1886
2292
|
function defaultTypeScriptConfig(projectPath, _opts) {
|
|
2293
|
+
const usesJsFramework = isUsingJSFramework(projectPath);
|
|
2294
|
+
const jsxImportSource = usesJsFramework ? {
|
|
2295
|
+
jsxImportSource: getJsxImportSource(projectPath)
|
|
2296
|
+
} : {};
|
|
1887
2297
|
return {
|
|
1888
2298
|
compilerOptions: {
|
|
1889
2299
|
allowJs: true,
|
|
1890
2300
|
allowSyntheticDefaultImports: true,
|
|
1891
2301
|
esModuleInterop: true,
|
|
1892
2302
|
forceConsistentCasingInFileNames: true,
|
|
1893
|
-
jsx:
|
|
2303
|
+
jsx: usesJsFramework ? 'react-jsx' : 'preserve',
|
|
2304
|
+
...jsxImportSource,
|
|
1894
2305
|
lib: [
|
|
1895
2306
|
'dom',
|
|
1896
2307
|
'dom.iterable',
|
|
@@ -2122,7 +2533,8 @@ async function extensionBuild(pathOrRemoteUrl, buildOptions) {
|
|
|
2122
2533
|
distDisplay,
|
|
2123
2534
|
browser,
|
|
2124
2535
|
mode: resolvedMode,
|
|
2125
|
-
enabled: mergedBuildOptions.addonLint
|
|
2536
|
+
enabled: mergedBuildOptions.addonLint,
|
|
2537
|
+
chunkProvenance: ()=>collectChunkDependencyProvenance(stats.compilation)
|
|
2126
2538
|
});
|
|
2127
2539
|
if ('missing' === lint.status && lint.hint) lintLines.push(lint.hint);
|
|
2128
2540
|
else if ('failed' === lint.status && isDebug()) lintLines.push(lint.debugLine);
|
|
@@ -2907,4 +3319,4 @@ async function extensionDev(pathOrRemoteUrl, devOptions) {
|
|
|
2907
3319
|
process.exit(1);
|
|
2908
3320
|
}
|
|
2909
3321
|
}
|
|
2910
|
-
export { BuildEmitter, applySplitChunksGuard, attachLifecycleStream, buildSourceFeatureIndex, classifyEntrySurface, classifyReloadFromSources, createChangedSourcesTracker, createLifecycleStream, defaultSplitChunks, dispatchReload,
|
|
3322
|
+
export { BuildEmitter, applySplitChunksGuard, attachLifecycleStream, buildSourceFeatureIndex, classifyEntrySurface, classifyReloadFromSources, createChangedSourcesTracker, createLifecycleStream, defaultSplitChunks, dispatchReload, ensureOptionalContractPackageResolved, ensureTypeScriptConfig, extensionBuild, extensionDev, getJsxImportSource, getUserTypeScriptConfigFile, hasDependency, humanLine, isUsingIntegration, isUsingJsxFramework, isUsingReact, isUsingTypeScript, isUsingVue, jsFrameworksConfigsDetected, jsFrameworksHmrSummary, jsFrameworksIntegrationsEnabled, loadLoaderOptions, maybeUsePreact, maybeUseReact, maybeUseSolid, maybeUseVue, readContentScriptCount, recordZipArtifact, resolveDevelopDistFile, resolveDevelopInstallRoot, swcParserForFile };
|