@jskit-ai/kernel 0.1.245 → 0.1.246
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/client/appConfig.js +2 -1
- package/client/asyncModuleRecovery.js +2 -4
- package/client/index.d.ts +13 -75
- package/client/index.js +1 -1
- package/client/logging.js +8 -2
- package/client/moduleBootstrap.js +41 -33
- package/client/moduleBootstrap.test.js +35 -0
- package/client/shellBootstrap.js +1 -8
- package/client/shellBootstrap.test.js +32 -5
- package/client/shellRouting.js +16 -61
- package/client/shellRouting.test.js +30 -1
- package/client/vite/clientBootstrapPlugin.js +0 -6
- package/client/vite/clientBootstrapPlugin.test.js +2 -3
- package/internal/node/installedPackages.js +14 -58
- package/package.json +2 -4
- package/server/actions/actionCatalogue.js +13 -34
- package/{shared → server}/actions/actionContributorHelpers.js +0 -5
- package/{shared → server}/actions/actionDefinitions.js +24 -131
- package/{shared → server}/actions/actionDefinitions.test.js +75 -21
- package/server/actions/actionEvents.js +97 -2
- package/server/actions/actionEvents.test.js +79 -0
- package/{shared → server}/actions/executionContext.js +3 -13
- package/server/actions/idempotency.js +24 -0
- package/server/actions/pipeline.js +87 -0
- package/{shared → server}/actions/policies.js +20 -33
- package/{shared → server}/actions/policies.test.js +6 -6
- package/{shared → server}/actions/registry.js +3 -22
- package/{shared → server}/actions/registry.test.js +70 -32
- package/server/actions/requestMeta.js +17 -0
- package/server/http/capabilityHttpRuntime.js +1 -1
- package/server/http/capabilityHttpRuntime.test.js +56 -0
- package/server/http/errorHandling.js +291 -0
- package/server/{runtime/fastifyBootstrap.test.js → http/errorHandling.test.js} +72 -120
- package/server/http/lib/routeRegistration.js +36 -150
- package/server/http/lib/routeTransport.js +2 -0
- package/server/http/lib/routeValidator.js +5 -47
- package/server/http/lib/routeValidator.test.js +15 -17
- package/server/http/lib/router.js +10 -94
- package/server/platform/providerRuntime/capabilityProviderLoader.js +2 -1
- package/server/platform/providerRuntime/helpers.js +1 -34
- package/server/runtime/integers.js +1 -5
- package/server/runtime/serviceAuthorization.js +4 -9
- package/server/support/appConfig.js +2 -1
- package/server/support/appConfigFiles.js +1 -38
- package/server/support/appConfigFiles.test.js +3 -39
- package/server/support/index.js +1 -20
- package/shared/capabilities/defineProvider.js +1 -1
- package/shared/capabilities/index.js +1 -1
- package/shared/index.js +1 -1
- package/shared/support/index.js +1 -4
- package/shared/support/mobileConfig.js +99 -0
- package/shared/support/mobileConfig.test.js +113 -0
- package/shared/support/normalize.js +0 -108
- package/shared/support/normalize.test.js +0 -134
- package/shared/{actions/actionContributorHelpers.test.js → support/permissions.test.js} +1 -1
- package/shared/support/returnToPath.js +1 -20
- package/shared/support/returnToPath.test.js +1 -36
- package/shared/support/shellLayoutTargets.js +2 -140
- package/shared/support/shellLayoutTargets.test.js +1 -110
- package/shared/support/sorting.js +1 -9
- package/shared/surface/apiPaths.js +1 -82
- package/shared/surface/paths.js +38 -171
- package/shared/surface/registry.js +2 -1
- package/shared/surface/runtime.js +18 -109
- package/shared/surface/runtime.test.js +57 -0
- package/shared/validators/index.js +1 -4
- package/shared/validators/jsonRestSchemaSupport.js +0 -9
- package/shared/validators/recordIdParamsValidator.js +0 -6
- package/shared/validators/schemaDefinitions.js +4 -30
- package/shared/validators/schemaPayloadValidation.js +2 -6
- package/test/barrelExposure.test.js +3 -7
- package/test/exportsContract.test.js +1 -3
- package/client/mobileLaunchRouting.js +0 -231
- package/client/mobileLaunchRouting.test.js +0 -230
- package/server/http/lib/controller.js +0 -183
- package/server/http/lib/controller.test.js +0 -143
- package/server/http/lib/index.js +0 -5
- package/server/runtime/canonicalJson.js +0 -74
- package/server/runtime/entityChangeEvents.js +0 -307
- package/server/runtime/entityChangeEvents.test.js +0 -274
- package/server/runtime/fastifyBootstrap.js +0 -553
- package/server/runtime/moduleConfig.js +0 -223
- package/server/runtime/moduleConfig.test.js +0 -165
- package/server/runtime/pagination.js +0 -13
- package/server/runtime/realtimeNormalization.js +0 -21
- package/server/runtime/routeUtils.js +0 -20
- package/server/runtime/securityAudit.js +0 -269
- package/server/runtime/securityAudit.test.js +0 -41
- package/server/support/pageTargets.js +0 -772
- package/server/support/pageTargets.test.js +0 -659
- package/server/support/shellOutlets.js +0 -576
- package/server/support/shellOutlets.test.js +0 -336
- package/server/surface/index.js +0 -18
- package/shared/actions/audit.js +0 -7
- package/shared/actions/idempotency.js +0 -62
- package/shared/actions/observability.js +0 -10
- package/shared/actions/pipeline.js +0 -309
- package/shared/actions/requestMeta.js +0 -36
- package/shared/actions/textNormalization.js +0 -3
- package/shared/actions/withActionDefaults.js +0 -34
- /package/{shared → server}/actions/executionContext.test.js +0 -0
|
@@ -1,772 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { pathToFileURL } from "node:url";
|
|
4
|
-
import {
|
|
5
|
-
normalizeSurfaceId,
|
|
6
|
-
normalizeSurfacePagesRoot
|
|
7
|
-
} from "../../shared/surface/index.js";
|
|
8
|
-
import {
|
|
9
|
-
normalizeObject,
|
|
10
|
-
normalizeText
|
|
11
|
-
} from "../../shared/support/normalize.js";
|
|
12
|
-
import {
|
|
13
|
-
discoverShellOutletTargetsFromVueSource,
|
|
14
|
-
findShellOutletTargetById,
|
|
15
|
-
normalizeShellOutletTargetId
|
|
16
|
-
} from "../../shared/support/shellLayoutTargets.js";
|
|
17
|
-
import {
|
|
18
|
-
discoverPlacementTopologyFromApp,
|
|
19
|
-
resolveSemanticPlacementTargetFromApp
|
|
20
|
-
} from "./shellOutlets.js";
|
|
21
|
-
import { resolveRequiredAppRoot, toPosixPath } from "./path.js";
|
|
22
|
-
import { loadAppConfigFromModuleUrl } from "./appConfigFiles.js";
|
|
23
|
-
|
|
24
|
-
const DEFAULT_PAGE_LINK_COMPONENT_TOKEN = "local.main.ui.surface-aware-menu-link-item";
|
|
25
|
-
const DEFAULT_SUBPAGE_LINK_COMPONENT_TOKEN = "local.main.ui.surface-aware-menu-link-item";
|
|
26
|
-
const PAGE_ROOT_PREFIX = "src/pages/";
|
|
27
|
-
const ROUTER_VIEW_TAG_PATTERN = /<RouterView\b/i;
|
|
28
|
-
const SECTION_CONTAINER_SHELL_TAG_PATTERN = /<SectionContainerShell\b/i;
|
|
29
|
-
const TABS_SLOT_PATTERN = /<template\b[^>]*(?:#tabs|v-slot:tabs)\b[^>]*>([\s\S]*?)<\/template>/i;
|
|
30
|
-
|
|
31
|
-
function normalizeRelativeFilePath(value = "") {
|
|
32
|
-
return String(value || "")
|
|
33
|
-
.replaceAll("\\", "/")
|
|
34
|
-
.replace(/^\.\/+/, "")
|
|
35
|
-
.trim();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function validateVueTargetFile(relativePath = "", { context = "page target" } = {}) {
|
|
39
|
-
const normalizedRelativePath = normalizeRelativeFilePath(relativePath);
|
|
40
|
-
if (!normalizedRelativePath.endsWith(".vue")) {
|
|
41
|
-
throw new Error(`${context} target file must be a .vue file: ${normalizedRelativePath || "<empty>"}.`);
|
|
42
|
-
}
|
|
43
|
-
return normalizedRelativePath;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function isAbsolutePathInput(value = "") {
|
|
47
|
-
const normalizedValue = normalizeRelativeFilePath(value);
|
|
48
|
-
if (!normalizedValue) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (normalizedValue.startsWith("/")) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return /^[A-Za-z]:\//u.test(normalizedValue);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function resolvePagesRelativeAppPath(
|
|
60
|
-
value = "",
|
|
61
|
-
{
|
|
62
|
-
context = "page target",
|
|
63
|
-
label = "target path"
|
|
64
|
-
} = {}
|
|
65
|
-
) {
|
|
66
|
-
const normalizedValue = normalizeRelativeFilePath(value);
|
|
67
|
-
if (!normalizedValue) {
|
|
68
|
-
throw new Error(`${context} requires ${label}.`);
|
|
69
|
-
}
|
|
70
|
-
if (isAbsolutePathInput(normalizedValue)) {
|
|
71
|
-
throw new Error(`${context} ${label} must be relative to src/pages/: ${normalizedValue}.`);
|
|
72
|
-
}
|
|
73
|
-
if (normalizedValue === "src/pages" || normalizedValue === PAGE_ROOT_PREFIX) {
|
|
74
|
-
throw new Error(
|
|
75
|
-
`${context} ${label} must include a path under src/pages/: ${normalizedValue}.`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
if (normalizedValue.startsWith(PAGE_ROOT_PREFIX)) {
|
|
79
|
-
return normalizedValue;
|
|
80
|
-
}
|
|
81
|
-
if (normalizedValue.startsWith("src/")) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`${context} ${label} must be relative to src/pages/ or start with src/pages/: ${normalizedValue}.`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return `${PAGE_ROOT_PREFIX}${normalizedValue}`;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function normalizePagesRelativeTargetFile(
|
|
91
|
-
targetFile = "",
|
|
92
|
-
{
|
|
93
|
-
context = "page target",
|
|
94
|
-
label = "target file"
|
|
95
|
-
} = {}
|
|
96
|
-
) {
|
|
97
|
-
return validateVueTargetFile(
|
|
98
|
-
resolvePagesRelativeAppPath(targetFile, { context, label }),
|
|
99
|
-
{ context }
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function normalizePagesRelativeTargetRoot(
|
|
104
|
-
targetRoot = "",
|
|
105
|
-
{
|
|
106
|
-
context = "page target",
|
|
107
|
-
label = "target root"
|
|
108
|
-
} = {}
|
|
109
|
-
) {
|
|
110
|
-
const normalizedRelativePath = resolvePagesRelativeAppPath(targetRoot, {
|
|
111
|
-
context,
|
|
112
|
-
label
|
|
113
|
-
});
|
|
114
|
-
if (normalizedRelativePath.endsWith(".vue")) {
|
|
115
|
-
throw new Error(`${context} ${label} must be a route directory, not a .vue file: ${normalizedRelativePath}.`);
|
|
116
|
-
}
|
|
117
|
-
return normalizedRelativePath;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function splitTextIntoWords(value = "") {
|
|
121
|
-
const normalized = String(value || "")
|
|
122
|
-
.replace(/^\[|\]$/g, "")
|
|
123
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
124
|
-
.replace(/[^A-Za-z0-9]+/g, " ")
|
|
125
|
-
.trim();
|
|
126
|
-
if (!normalized) {
|
|
127
|
-
return [];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return normalized
|
|
131
|
-
.split(/\s+/)
|
|
132
|
-
.map((entry) => entry.toLowerCase())
|
|
133
|
-
.filter(Boolean);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function wordsToKebab(words = []) {
|
|
137
|
-
return (Array.isArray(words) ? words : [])
|
|
138
|
-
.map((entry) => String(entry || "").toLowerCase())
|
|
139
|
-
.filter(Boolean)
|
|
140
|
-
.join("-");
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function toTitleCase(words = []) {
|
|
144
|
-
return (Array.isArray(words) ? words : [])
|
|
145
|
-
.map((word) => {
|
|
146
|
-
const value = String(word || "");
|
|
147
|
-
if (!value) {
|
|
148
|
-
return "";
|
|
149
|
-
}
|
|
150
|
-
return `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`;
|
|
151
|
-
})
|
|
152
|
-
.filter(Boolean)
|
|
153
|
-
.join(" ");
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function isRouteGroupSegment(value = "") {
|
|
157
|
-
const normalizedValue = normalizeText(value);
|
|
158
|
-
return normalizedValue.startsWith("(") && normalizedValue.endsWith(")");
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function isIndexRouteSegment(value = "") {
|
|
162
|
-
return normalizeText(value).toLowerCase() === "index";
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function isPathlessRouteSegment(value = "") {
|
|
166
|
-
return isRouteGroupSegment(value) || isIndexRouteSegment(value);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function normalizePlacementIdSegment(value = "") {
|
|
170
|
-
return wordsToKebab(splitTextIntoWords(value));
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function humanizePageSegment(value = "", fallback = "Page") {
|
|
174
|
-
const words = splitTextIntoWords(value);
|
|
175
|
-
if (words.length < 1) {
|
|
176
|
-
return fallback;
|
|
177
|
-
}
|
|
178
|
-
return toTitleCase(words);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async function loadPublicConfig(appRoot = "", { context = "page target" } = {}) {
|
|
182
|
-
const resolvedAppRoot = resolveRequiredAppRoot(appRoot, { context });
|
|
183
|
-
try {
|
|
184
|
-
const config = normalizeObject(
|
|
185
|
-
await loadAppConfigFromModuleUrl({
|
|
186
|
-
moduleUrl: pathToFileURL(path.join(resolvedAppRoot, "config", "public.js")).href
|
|
187
|
-
})
|
|
188
|
-
);
|
|
189
|
-
if (Object.keys(config).length < 1) {
|
|
190
|
-
throw new Error("requires exported config in config/public.js.");
|
|
191
|
-
}
|
|
192
|
-
return config;
|
|
193
|
-
} catch (error) {
|
|
194
|
-
throw new Error(
|
|
195
|
-
`${context} could not load config/public.js: ${String(error?.message || error || "unknown error")}`
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function normalizeSurfaceAccessPolicyId(value = "") {
|
|
201
|
-
return normalizeText(value).toLowerCase();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function resolveSurfaceRequiresAuth(surfaceDefinition = {}, surfaceAccessPolicies = {}) {
|
|
205
|
-
const normalizedDefinition = normalizeObject(surfaceDefinition);
|
|
206
|
-
const normalizedPolicies = normalizeObject(surfaceAccessPolicies);
|
|
207
|
-
const accessPolicyId = normalizeSurfaceAccessPolicyId(normalizedDefinition.accessPolicyId);
|
|
208
|
-
const configuredPolicy = accessPolicyId
|
|
209
|
-
? normalizeObject(normalizedPolicies[accessPolicyId])
|
|
210
|
-
: {};
|
|
211
|
-
|
|
212
|
-
if (Object.hasOwn(configuredPolicy, "requireAuth")) {
|
|
213
|
-
return configuredPolicy.requireAuth === true;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return normalizedDefinition.requiresAuth === true;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
async function listSurfacePageRoots(appRoot = "", { context = "page target" } = {}) {
|
|
220
|
-
const config = await loadPublicConfig(appRoot, { context });
|
|
221
|
-
const surfaceDefinitions = normalizeObject(config.surfaceDefinitions);
|
|
222
|
-
const surfaceAccessPolicies = normalizeObject(config.surfaceAccessPolicies);
|
|
223
|
-
|
|
224
|
-
return Object.freeze(
|
|
225
|
-
Object.entries(surfaceDefinitions)
|
|
226
|
-
.map(([key, value]) => {
|
|
227
|
-
const definition = normalizeObject(value);
|
|
228
|
-
const surfaceId = normalizeSurfaceId(definition.id || key);
|
|
229
|
-
if (!surfaceId || definition.enabled === false) {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return Object.freeze({
|
|
234
|
-
id: surfaceId,
|
|
235
|
-
pagesRoot: normalizeSurfacePagesRoot(definition.pagesRoot),
|
|
236
|
-
requiresAuth: resolveSurfaceRequiresAuth(definition, surfaceAccessPolicies)
|
|
237
|
-
});
|
|
238
|
-
})
|
|
239
|
-
.filter(Boolean)
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function deriveSurfaceMatchesFromPageFile(relativePath = "", surfacePageRoots = []) {
|
|
244
|
-
const normalizedRelativePath = normalizeRelativeFilePath(relativePath);
|
|
245
|
-
if (!normalizedRelativePath.startsWith(PAGE_ROOT_PREFIX)) {
|
|
246
|
-
return [];
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const pagePathWithinPagesRoot = normalizedRelativePath.slice(PAGE_ROOT_PREFIX.length);
|
|
250
|
-
return (Array.isArray(surfacePageRoots) ? surfacePageRoots : [])
|
|
251
|
-
.map((surface) => {
|
|
252
|
-
const pagesRoot = normalizeSurfacePagesRoot(surface?.pagesRoot);
|
|
253
|
-
if (!pagesRoot) {
|
|
254
|
-
return Object.freeze({
|
|
255
|
-
surfaceId: normalizeSurfaceId(surface?.id),
|
|
256
|
-
pagesRoot,
|
|
257
|
-
requiresAuth: surface?.requiresAuth === true,
|
|
258
|
-
surfaceRelativeFilePath: pagePathWithinPagesRoot
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const requiredPrefix = `${pagesRoot}/`;
|
|
263
|
-
if (!pagePathWithinPagesRoot.startsWith(requiredPrefix)) {
|
|
264
|
-
return null;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return Object.freeze({
|
|
268
|
-
surfaceId: normalizeSurfaceId(surface?.id),
|
|
269
|
-
pagesRoot,
|
|
270
|
-
requiresAuth: surface?.requiresAuth === true,
|
|
271
|
-
surfaceRelativeFilePath: pagePathWithinPagesRoot.slice(requiredPrefix.length)
|
|
272
|
-
});
|
|
273
|
-
})
|
|
274
|
-
.filter(Boolean);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function compareSurfaceMatchSpecificity(leftMatch = {}, rightMatch = {}) {
|
|
278
|
-
const leftPagesRoot = normalizeSurfacePagesRoot(leftMatch?.pagesRoot);
|
|
279
|
-
const rightPagesRoot = normalizeSurfacePagesRoot(rightMatch?.pagesRoot);
|
|
280
|
-
const leftSegmentCount = leftPagesRoot ? leftPagesRoot.split("/").filter(Boolean).length : 0;
|
|
281
|
-
const rightSegmentCount = rightPagesRoot ? rightPagesRoot.split("/").filter(Boolean).length : 0;
|
|
282
|
-
|
|
283
|
-
if (leftSegmentCount !== rightSegmentCount) {
|
|
284
|
-
return rightSegmentCount - leftSegmentCount;
|
|
285
|
-
}
|
|
286
|
-
if (leftPagesRoot.length !== rightPagesRoot.length) {
|
|
287
|
-
return rightPagesRoot.length - leftPagesRoot.length;
|
|
288
|
-
}
|
|
289
|
-
return leftPagesRoot.localeCompare(rightPagesRoot);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function resolveBestSurfaceMatchFromPageFile(relativePath = "", surfacePageRoots = [], { context = "page target" } = {}) {
|
|
293
|
-
const matches = deriveSurfaceMatchesFromPageFile(relativePath, surfacePageRoots);
|
|
294
|
-
if (matches.length < 1) {
|
|
295
|
-
return null;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const sortedMatches = [...matches].sort(compareSurfaceMatchSpecificity);
|
|
299
|
-
const bestMatch = sortedMatches[0];
|
|
300
|
-
const bestPagesRoot = normalizeSurfacePagesRoot(bestMatch?.pagesRoot);
|
|
301
|
-
const conflictingMatches = sortedMatches.filter(
|
|
302
|
-
(match) => normalizeSurfacePagesRoot(match?.pagesRoot) === bestPagesRoot
|
|
303
|
-
);
|
|
304
|
-
if (conflictingMatches.length > 1) {
|
|
305
|
-
const surfaceIds = conflictingMatches.map((match) => match.surfaceId).filter(Boolean).join(", ");
|
|
306
|
-
const pagesRootLabel = bestPagesRoot || "/";
|
|
307
|
-
throw new Error(
|
|
308
|
-
`${context} target file is ambiguous because multiple surfaces share pagesRoot "${pagesRootLabel}" (${surfaceIds}): ${normalizeRelativeFilePath(relativePath)}.`
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return bestMatch;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function deriveRouteInfoFromSurfaceRelativeFile(surfaceRelativeFilePath = "", surfaceId = "") {
|
|
316
|
-
const normalizedRelativeFilePath = validateVueTargetFile(surfaceRelativeFilePath, {
|
|
317
|
-
context: "page target"
|
|
318
|
-
});
|
|
319
|
-
const withoutExtension = normalizedRelativeFilePath.slice(0, -".vue".length);
|
|
320
|
-
const fileSegments = withoutExtension
|
|
321
|
-
.split("/")
|
|
322
|
-
.map((segment) => normalizeText(segment))
|
|
323
|
-
.filter(Boolean);
|
|
324
|
-
|
|
325
|
-
const routeSegments = [...fileSegments];
|
|
326
|
-
if (routeSegments[routeSegments.length - 1] === "index") {
|
|
327
|
-
routeSegments.pop();
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const visibleRouteSegments = routeSegments.filter((segment) => !isPathlessRouteSegment(segment));
|
|
331
|
-
const routeUrlSuffix = visibleRouteSegments.length > 0 ? `/${visibleRouteSegments.join("/")}` : "/";
|
|
332
|
-
const surfacePlacementIdSegment = normalizePlacementIdSegment(surfaceId || "root") || "root";
|
|
333
|
-
const placementIdSegments = visibleRouteSegments
|
|
334
|
-
.map((segment) => normalizePlacementIdSegment(segment))
|
|
335
|
-
.filter(Boolean);
|
|
336
|
-
const pageLeafSegment = visibleRouteSegments[visibleRouteSegments.length - 1] || "";
|
|
337
|
-
const defaultNameSource = pageLeafSegment || surfaceId || "page";
|
|
338
|
-
const defaultName = humanizePageSegment(defaultNameSource, "Page");
|
|
339
|
-
|
|
340
|
-
return Object.freeze({
|
|
341
|
-
fileSegments,
|
|
342
|
-
routeSegments,
|
|
343
|
-
visibleRouteSegments,
|
|
344
|
-
routeUrlSuffix,
|
|
345
|
-
pageLeafSegment,
|
|
346
|
-
defaultName,
|
|
347
|
-
placementId:
|
|
348
|
-
placementIdSegments.length > 0
|
|
349
|
-
? `ui-generator.page.${surfacePlacementIdSegment}.${placementIdSegments.join(".")}.link`
|
|
350
|
-
: `ui-generator.page.${surfacePlacementIdSegment}.link`
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
function buildRouteUrlSuffixFromVisibleSegments(segments = []) {
|
|
355
|
-
const visibleSegments = (Array.isArray(segments) ? segments : [])
|
|
356
|
-
.map((segment) => normalizeText(segment))
|
|
357
|
-
.filter(Boolean);
|
|
358
|
-
return visibleSegments.length > 0 ? `/${visibleSegments.join("/")}` : "/";
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function buildAncestorRouteContexts(pageTarget = {}) {
|
|
362
|
-
const routeSegments = Array.isArray(pageTarget?.routeSegments)
|
|
363
|
-
? pageTarget.routeSegments
|
|
364
|
-
: [];
|
|
365
|
-
const visibleRouteSegments = Array.isArray(pageTarget?.visibleRouteSegments)
|
|
366
|
-
? pageTarget.visibleRouteSegments
|
|
367
|
-
: [];
|
|
368
|
-
if (visibleRouteSegments.length < 2) {
|
|
369
|
-
return [];
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
const ancestors = [];
|
|
373
|
-
|
|
374
|
-
for (let visiblePrefixLength = visibleRouteSegments.length - 1; visiblePrefixLength >= 1; visiblePrefixLength -= 1) {
|
|
375
|
-
const parentVisibleSegments = visibleRouteSegments.slice(0, visiblePrefixLength);
|
|
376
|
-
const actualRouteSegments = [];
|
|
377
|
-
let collectedVisibleSegments = 0;
|
|
378
|
-
|
|
379
|
-
for (const segment of routeSegments) {
|
|
380
|
-
actualRouteSegments.push(segment);
|
|
381
|
-
if (!isPathlessRouteSegment(segment)) {
|
|
382
|
-
collectedVisibleSegments += 1;
|
|
383
|
-
}
|
|
384
|
-
if (collectedVisibleSegments >= visiblePrefixLength) {
|
|
385
|
-
break;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (collectedVisibleSegments !== visiblePrefixLength) {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const nextRouteSegment = normalizeText(routeSegments[actualRouteSegments.length]);
|
|
394
|
-
ancestors.push(
|
|
395
|
-
Object.freeze({
|
|
396
|
-
visibleRouteSegments: parentVisibleSegments,
|
|
397
|
-
actualRouteSegments,
|
|
398
|
-
childUsesIndexRouteOwner: isIndexRouteSegment(nextRouteSegment)
|
|
399
|
-
})
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
return ancestors;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function buildParentPageFileCandidates(pageTarget = {}, ancestorRoute = {}) {
|
|
407
|
-
const surfacePagesRootSegments = normalizeRelativeFilePath(pageTarget?.surfacePagesRoot)
|
|
408
|
-
.split("/")
|
|
409
|
-
.map((segment) => normalizeText(segment))
|
|
410
|
-
.filter(Boolean);
|
|
411
|
-
const routeSegments = (Array.isArray(ancestorRoute?.actualRouteSegments) ? ancestorRoute.actualRouteSegments : [])
|
|
412
|
-
.map((segment) => normalizeText(segment))
|
|
413
|
-
.filter(Boolean);
|
|
414
|
-
if (routeSegments.length < 1) {
|
|
415
|
-
return [];
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const baseSegments = ["src/pages", ...surfacePagesRootSegments, ...routeSegments];
|
|
419
|
-
const fileRoutePath = `${baseSegments.join("/")}.vue`;
|
|
420
|
-
const indexRoutePath = [...baseSegments, "index.vue"].join("/");
|
|
421
|
-
const preferredCandidates = ancestorRoute?.childUsesIndexRouteOwner === true
|
|
422
|
-
? [indexRoutePath, fileRoutePath]
|
|
423
|
-
: [fileRoutePath, indexRoutePath];
|
|
424
|
-
|
|
425
|
-
return preferredCandidates.map((relativePath) =>
|
|
426
|
-
Object.freeze({
|
|
427
|
-
relativePath,
|
|
428
|
-
pageShape: relativePath.endsWith("/index.vue") ? "index" : "file"
|
|
429
|
-
})
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function resolveSubpagesHostTargetFromPageSource(source = "") {
|
|
434
|
-
const sourceText = String(source || "");
|
|
435
|
-
if (!ROUTER_VIEW_TAG_PATTERN.test(sourceText)) {
|
|
436
|
-
return null;
|
|
437
|
-
}
|
|
438
|
-
const discoveredTargets = discoverShellOutletTargetsFromVueSource(sourceText, {
|
|
439
|
-
context: "subpages host"
|
|
440
|
-
});
|
|
441
|
-
const targets = Array.isArray(discoveredTargets.targets) ? discoveredTargets.targets : [];
|
|
442
|
-
if (targets.length !== 1) {
|
|
443
|
-
return null;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const target = findShellOutletTargetById(targets, targets[0]?.id);
|
|
447
|
-
if (!target) {
|
|
448
|
-
return null;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
let isSectionSubpagesHost = false;
|
|
452
|
-
if (SECTION_CONTAINER_SHELL_TAG_PATTERN.test(sourceText)) {
|
|
453
|
-
const tabsSlotMatch = TABS_SLOT_PATTERN.exec(sourceText);
|
|
454
|
-
if (tabsSlotMatch) {
|
|
455
|
-
const tabsTargets = discoverShellOutletTargetsFromVueSource(String(tabsSlotMatch[1] || ""), {
|
|
456
|
-
context: "subpages host tabs slot"
|
|
457
|
-
});
|
|
458
|
-
const tabTargetIds = Array.isArray(tabsTargets.targets)
|
|
459
|
-
? tabsTargets.targets.map((entry) => normalizeShellOutletTargetId(entry?.id)).filter(Boolean)
|
|
460
|
-
: [];
|
|
461
|
-
if (tabTargetIds.length === 1 && tabTargetIds[0] === normalizeShellOutletTargetId(target.id)) {
|
|
462
|
-
isSectionSubpagesHost = true;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return Object.freeze({
|
|
468
|
-
id: target.id,
|
|
469
|
-
isSectionSubpagesHost
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
async function resolvePageTargetDetails({
|
|
474
|
-
appRoot,
|
|
475
|
-
targetFile = "",
|
|
476
|
-
context = "page target"
|
|
477
|
-
} = {}) {
|
|
478
|
-
const resolvedAppRoot = resolveRequiredAppRoot(appRoot, { context });
|
|
479
|
-
const normalizedRelativePath = normalizePagesRelativeTargetFile(targetFile, {
|
|
480
|
-
context,
|
|
481
|
-
label: "target file"
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
const surfacePageRoots = await listSurfacePageRoots(resolvedAppRoot, { context });
|
|
485
|
-
const surfaceMatch = resolveBestSurfaceMatchFromPageFile(normalizedRelativePath, surfacePageRoots, { context });
|
|
486
|
-
if (!surfaceMatch) {
|
|
487
|
-
throw new Error(
|
|
488
|
-
`${context} target file must be relative to src/pages/ and resolve to a configured surface: ${normalizeRelativeFilePath(targetFile)}.`
|
|
489
|
-
);
|
|
490
|
-
}
|
|
491
|
-
const routeInfo = deriveRouteInfoFromSurfaceRelativeFile(surfaceMatch.surfaceRelativeFilePath, surfaceMatch.surfaceId);
|
|
492
|
-
const absolutePath = path.resolve(resolvedAppRoot, normalizedRelativePath);
|
|
493
|
-
|
|
494
|
-
return Object.freeze({
|
|
495
|
-
appRoot: resolvedAppRoot,
|
|
496
|
-
targetFilePath: Object.freeze({
|
|
497
|
-
absolutePath,
|
|
498
|
-
relativePath: normalizedRelativePath
|
|
499
|
-
}),
|
|
500
|
-
surfaceId: surfaceMatch.surfaceId,
|
|
501
|
-
surfacePagesRoot: surfaceMatch.pagesRoot,
|
|
502
|
-
surfaceRequiresAuth: surfaceMatch.requiresAuth === true,
|
|
503
|
-
surfaceRelativeFilePath: surfaceMatch.surfaceRelativeFilePath,
|
|
504
|
-
...routeInfo
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
function deriveDefaultSubpagesHost(pageTarget = {}) {
|
|
509
|
-
const visibleRouteSegments = Array.isArray(pageTarget?.visibleRouteSegments)
|
|
510
|
-
? pageTarget.visibleRouteSegments
|
|
511
|
-
: [];
|
|
512
|
-
const hostSegments = visibleRouteSegments
|
|
513
|
-
.map((segment) => normalizePlacementIdSegment(segment))
|
|
514
|
-
.filter(Boolean);
|
|
515
|
-
|
|
516
|
-
if (hostSegments.length > 0) {
|
|
517
|
-
return hostSegments.join("-");
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return normalizePlacementIdSegment(pageTarget?.surfaceId || "page") || "page";
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
async function resolveNearestParentSubpagesHost({
|
|
524
|
-
appRoot,
|
|
525
|
-
pageTarget = {},
|
|
526
|
-
context = "page target"
|
|
527
|
-
} = {}) {
|
|
528
|
-
const resolvedAppRoot = resolveRequiredAppRoot(appRoot, { context });
|
|
529
|
-
const ancestorRoutes = buildAncestorRouteContexts(pageTarget);
|
|
530
|
-
if (ancestorRoutes.length < 1) {
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
for (const ancestorRoute of ancestorRoutes) {
|
|
535
|
-
const candidatePages = buildParentPageFileCandidates(pageTarget, ancestorRoute);
|
|
536
|
-
|
|
537
|
-
for (const candidatePage of candidatePages) {
|
|
538
|
-
const candidatePath = path.resolve(resolvedAppRoot, candidatePage.relativePath);
|
|
539
|
-
let source = "";
|
|
540
|
-
try {
|
|
541
|
-
source = await readFile(candidatePath, "utf8");
|
|
542
|
-
} catch {
|
|
543
|
-
continue;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
const target = resolveSubpagesHostTargetFromPageSource(source);
|
|
547
|
-
if (!target) {
|
|
548
|
-
continue;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
return Object.freeze({
|
|
552
|
-
...target,
|
|
553
|
-
pageFile: toPosixPath(path.relative(resolvedAppRoot, candidatePath)),
|
|
554
|
-
pageShape: candidatePage.pageShape,
|
|
555
|
-
visibleRouteSegments: ancestorRoute.visibleRouteSegments,
|
|
556
|
-
routeUrlSuffix: buildRouteUrlSuffixFromVisibleSegments(ancestorRoute.visibleRouteSegments)
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
return null;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
function normalizePlacementTargetId(target = {}) {
|
|
565
|
-
return normalizeShellOutletTargetId(target?.id || target?.target || target);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function resolveConcreteTargetOwner(target = "") {
|
|
569
|
-
const normalizedTarget = normalizeShellOutletTargetId(target);
|
|
570
|
-
if (!normalizedTarget) {
|
|
571
|
-
return "";
|
|
572
|
-
}
|
|
573
|
-
return normalizedTarget.slice(0, normalizedTarget.indexOf(":"));
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
function topologyPlacementTargetsConcreteOutlet(placement = {}, target = "") {
|
|
577
|
-
const normalizedTarget = normalizeShellOutletTargetId(target);
|
|
578
|
-
if (!normalizedTarget) {
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
const variants = placement?.variants && typeof placement.variants === "object" ? placement.variants : {};
|
|
582
|
-
return Object.values(variants).some((variant) => normalizeShellOutletTargetId(variant?.outlet) === normalizedTarget);
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
async function resolveSemanticPlacementTargetForConcreteOutlet({
|
|
586
|
-
appRoot,
|
|
587
|
-
concreteTarget = "",
|
|
588
|
-
surface = "",
|
|
589
|
-
context = "page target"
|
|
590
|
-
} = {}) {
|
|
591
|
-
const normalizedConcreteTarget = normalizeShellOutletTargetId(concreteTarget);
|
|
592
|
-
if (!normalizedConcreteTarget) {
|
|
593
|
-
return null;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
const topology = await discoverPlacementTopologyFromApp({ appRoot });
|
|
597
|
-
const owner = resolveConcreteTargetOwner(normalizedConcreteTarget);
|
|
598
|
-
const normalizedSurface = normalizeSurfaceId(surface);
|
|
599
|
-
const candidates = (Array.isArray(topology.placements) ? topology.placements : []).filter((placement) => {
|
|
600
|
-
if (!topologyPlacementTargetsConcreteOutlet(placement, normalizedConcreteTarget)) {
|
|
601
|
-
return false;
|
|
602
|
-
}
|
|
603
|
-
const surfaces = Array.isArray(placement.surfaces) ? placement.surfaces : ["*"];
|
|
604
|
-
return !normalizedSurface || surfaces.includes("*") || surfaces.includes(normalizedSurface);
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
const exactOwnerMatches = candidates.filter((placement) => placement.owner && placement.owner === owner);
|
|
608
|
-
const globalMatches = candidates.filter((placement) => !placement.owner);
|
|
609
|
-
const selectedMatches = exactOwnerMatches.length > 0 ? exactOwnerMatches : globalMatches;
|
|
610
|
-
if (selectedMatches.length < 1) {
|
|
611
|
-
return null;
|
|
612
|
-
}
|
|
613
|
-
if (selectedMatches.length === 1) {
|
|
614
|
-
return selectedMatches[0];
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
const targetLabels = selectedMatches.map((placement) =>
|
|
618
|
-
placement.owner ? `${placement.id} [owner:${placement.owner}]` : placement.id
|
|
619
|
-
);
|
|
620
|
-
throw new Error(
|
|
621
|
-
`${context} found multiple semantic placements mapped to concrete outlet "${normalizedConcreteTarget}": ` +
|
|
622
|
-
`${targetLabels.join(", ")}. Pass --link-placement or make the topology mapping unambiguous.`
|
|
623
|
-
);
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
function resolveRelativeLinkToFromParent(pageTarget = {}, parentHost = null) {
|
|
627
|
-
const childSegments = Array.isArray(pageTarget?.visibleRouteSegments) ? pageTarget.visibleRouteSegments : [];
|
|
628
|
-
const parentSegments = Array.isArray(parentHost?.visibleRouteSegments) ? parentHost.visibleRouteSegments : [];
|
|
629
|
-
if (parentSegments.length < 1 || childSegments.length <= parentSegments.length) {
|
|
630
|
-
return "";
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
const relativeSegments = childSegments.slice(parentSegments.length);
|
|
634
|
-
if (relativeSegments.length < 1) {
|
|
635
|
-
return "";
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
return `./${relativeSegments.join("/")}`;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
function resolveRelativeLinkToFromNearestIndexOwner(pageTarget = {}) {
|
|
642
|
-
const routeSegments = Array.isArray(pageTarget?.routeSegments) ? pageTarget.routeSegments : [];
|
|
643
|
-
const deepestIndexOwnerIndex = routeSegments.findLastIndex((segment) => isIndexRouteSegment(segment));
|
|
644
|
-
if (deepestIndexOwnerIndex < 0 || deepestIndexOwnerIndex >= routeSegments.length - 1) {
|
|
645
|
-
return "";
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
const relativeSegments = routeSegments
|
|
649
|
-
.slice(deepestIndexOwnerIndex + 1)
|
|
650
|
-
.filter((segment) => !isPathlessRouteSegment(segment));
|
|
651
|
-
if (relativeSegments.length < 1) {
|
|
652
|
-
return "";
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
return `./${relativeSegments.join("/")}`;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
function resolveInferredPageLinkTo({
|
|
659
|
-
explicitLinkTo = "",
|
|
660
|
-
pageTarget = {},
|
|
661
|
-
parentHost = null,
|
|
662
|
-
preservesRelativeSubpageLinks = false,
|
|
663
|
-
suppressImplicitRelativeLinks = false
|
|
664
|
-
} = {}) {
|
|
665
|
-
const normalizedExplicitLinkTo = normalizeText(explicitLinkTo);
|
|
666
|
-
if (normalizedExplicitLinkTo) {
|
|
667
|
-
return normalizedExplicitLinkTo;
|
|
668
|
-
}
|
|
669
|
-
if (suppressImplicitRelativeLinks === true) {
|
|
670
|
-
return "";
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
if (preservesRelativeSubpageLinks === true && parentHost?.isSectionSubpagesHost === true) {
|
|
674
|
-
const inferredLinkTo = resolveRelativeLinkToFromParent(pageTarget, parentHost);
|
|
675
|
-
if (inferredLinkTo) {
|
|
676
|
-
return inferredLinkTo;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
const inferredLinkTo = resolveRelativeLinkToFromNearestIndexOwner(pageTarget);
|
|
681
|
-
if (inferredLinkTo) {
|
|
682
|
-
return inferredLinkTo;
|
|
683
|
-
}
|
|
684
|
-
return "";
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
function renderPageLinkWhenLine(pageTarget = {}) {
|
|
688
|
-
if (pageTarget?.surfaceRequiresAuth !== true) {
|
|
689
|
-
return "";
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
return " when: ({ auth }) => auth?.authenticated === true\n";
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
async function resolvePageLinkTargetDetails({
|
|
696
|
-
appRoot,
|
|
697
|
-
targetFile = "",
|
|
698
|
-
pageTarget = null,
|
|
699
|
-
placement = "",
|
|
700
|
-
componentToken = "",
|
|
701
|
-
linkTo = "",
|
|
702
|
-
context = "page target"
|
|
703
|
-
} = {}) {
|
|
704
|
-
const resolvedPageTarget = pageTarget || await resolvePageTargetDetails({
|
|
705
|
-
appRoot,
|
|
706
|
-
targetFile,
|
|
707
|
-
context
|
|
708
|
-
});
|
|
709
|
-
const parentHost = await resolveNearestParentSubpagesHost({
|
|
710
|
-
appRoot: resolvedPageTarget.appRoot,
|
|
711
|
-
pageTarget: resolvedPageTarget,
|
|
712
|
-
context
|
|
713
|
-
});
|
|
714
|
-
const parentTargetId = normalizePlacementTargetId(parentHost);
|
|
715
|
-
let placementTarget = null;
|
|
716
|
-
const explicitPlacement = normalizeText(placement);
|
|
717
|
-
if (explicitPlacement) {
|
|
718
|
-
placementTarget = await resolveSemanticPlacementTargetFromApp({
|
|
719
|
-
appRoot: resolvedPageTarget.appRoot,
|
|
720
|
-
context,
|
|
721
|
-
placement: explicitPlacement,
|
|
722
|
-
owner: parentTargetId ? resolveConcreteTargetOwner(parentTargetId) : "",
|
|
723
|
-
surface: resolvedPageTarget.surfaceId
|
|
724
|
-
});
|
|
725
|
-
} else if (parentTargetId) {
|
|
726
|
-
placementTarget = await resolveSemanticPlacementTargetForConcreteOutlet({
|
|
727
|
-
appRoot: resolvedPageTarget.appRoot,
|
|
728
|
-
concreteTarget: parentTargetId,
|
|
729
|
-
surface: resolvedPageTarget.surfaceId,
|
|
730
|
-
context
|
|
731
|
-
});
|
|
732
|
-
}
|
|
733
|
-
if (!placementTarget) {
|
|
734
|
-
placementTarget = await resolveSemanticPlacementTargetFromApp({
|
|
735
|
-
appRoot: resolvedPageTarget.appRoot,
|
|
736
|
-
context,
|
|
737
|
-
surface: resolvedPageTarget.surfaceId
|
|
738
|
-
});
|
|
739
|
-
}
|
|
740
|
-
const preservesRelativeSubpageLinks =
|
|
741
|
-
parentHost?.isSectionSubpagesHost === true &&
|
|
742
|
-
Boolean(parentTargetId) &&
|
|
743
|
-
topologyPlacementTargetsConcreteOutlet(placementTarget, parentTargetId);
|
|
744
|
-
|
|
745
|
-
return Object.freeze({
|
|
746
|
-
pageTarget: resolvedPageTarget,
|
|
747
|
-
parentHost,
|
|
748
|
-
placementTarget,
|
|
749
|
-
componentToken: normalizeText(componentToken),
|
|
750
|
-
whenLine: renderPageLinkWhenLine(resolvedPageTarget),
|
|
751
|
-
linkTo: resolveInferredPageLinkTo({
|
|
752
|
-
explicitLinkTo: linkTo,
|
|
753
|
-
pageTarget: resolvedPageTarget,
|
|
754
|
-
parentHost,
|
|
755
|
-
preservesRelativeSubpageLinks,
|
|
756
|
-
suppressImplicitRelativeLinks: preservesRelativeSubpageLinks !== true
|
|
757
|
-
})
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
export {
|
|
762
|
-
DEFAULT_PAGE_LINK_COMPONENT_TOKEN,
|
|
763
|
-
DEFAULT_SUBPAGE_LINK_COMPONENT_TOKEN,
|
|
764
|
-
listSurfacePageRoots,
|
|
765
|
-
normalizePagesRelativeTargetFile,
|
|
766
|
-
normalizePagesRelativeTargetRoot,
|
|
767
|
-
resolveBestSurfaceMatchFromPageFile,
|
|
768
|
-
resolvePageTargetDetails,
|
|
769
|
-
deriveDefaultSubpagesHost,
|
|
770
|
-
resolveNearestParentSubpagesHost,
|
|
771
|
-
resolvePageLinkTargetDetails
|
|
772
|
-
};
|