@stacksjs/stx 0.2.174 → 0.2.176
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/a11y.d.ts +72 -2
- package/dist/a11y.js +25 -10
- package/dist/cli.js +1045 -930
- package/dist/client-script.js +1 -0
- package/dist/component-renderer.js +17 -0
- package/dist/craft.js +561 -453
- package/dist/includes.js +8 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/process.js +2 -1
- package/dist/props.d.ts +51 -8
- package/dist/pwa.js +512 -404
- package/dist/resolve-stx-targets.d.ts +49 -0
- package/dist/resolve-stx-targets.js +38 -0
- package/dist/runtime-globals.d.ts +24 -0
- package/dist/runtime-globals.js +16 -0
- package/dist/runtime-injection.d.ts +36 -0
- package/dist/runtime-injection.js +15 -0
- package/dist/server-bindings.js +3 -0
- package/dist/signal-processing.js +1 -1
- package/dist/signals.js +30 -27
- package/dist/ssg.d.ts +23 -0
- package/dist/ssg.js +509 -397
- package/dist/stx-virtual-ts.d.ts +27 -3
- package/dist/stx-virtual-ts.js +36 -0
- package/dist/typecheck.js +96 -62
- package/dist/types/config-types.d.ts +24 -0
- package/dist/utils.js +5 -4
- package/package.json +5 -5
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve whatever a user typed — a directory, a file, or a glob — to `.stx` files.
|
|
3
|
+
*
|
|
4
|
+
* The CLI commands disagreed about which of those they took, and each was silent
|
|
5
|
+
* about the shape it did not accept. `stx a11y` joined its argument into a scan
|
|
6
|
+
* pattern (`path.join(arg, '**' + '/*.stx')`), so a FILE path became
|
|
7
|
+
* `file.stx/**` + `/*.stx` and matched nothing, and a glob became
|
|
8
|
+
* `'x/**' + '/*.stx/**' + '/*.stx'` and also matched nothing. Both then took the
|
|
9
|
+
* empty branch, which printed
|
|
10
|
+
*
|
|
11
|
+
* ✓ No accessibility issues found!
|
|
12
|
+
*
|
|
13
|
+
* and exited 0 — on a file with three SERIOUS findings. Meanwhile `typecheck`
|
|
14
|
+
* globbed and, handed a directory, said it matched nothing. Both halves
|
|
15
|
+
* inverted, and inverted silently in the direction that costs you: the natural
|
|
16
|
+
* way to add a checker to CI is to copy the line that already works, so
|
|
17
|
+
*
|
|
18
|
+
* - run: stx a11y 'resources/**' + '/*.stx'
|
|
19
|
+
*
|
|
20
|
+
* passes on every commit for the life of the project, indistinguishable from a
|
|
21
|
+
* project with no accessibility problems (stacksjs/stx#1918).
|
|
22
|
+
*
|
|
23
|
+
* So there is one resolver and every command uses it. The separate half of that
|
|
24
|
+
* fix lives at the call sites and matters more: **an empty match set is not a
|
|
25
|
+
* pass.** A run that read no files has verified nothing, and has to say so.
|
|
26
|
+
*
|
|
27
|
+
* @module resolve-stx-targets
|
|
28
|
+
*/
|
|
29
|
+
/** Is this argument a glob pattern rather than a plain path? */
|
|
30
|
+
export declare function looksLikeGlob(target: string): boolean;
|
|
31
|
+
export interface ResolveStxTargetsOptions {
|
|
32
|
+
/** Directory to resolve relative targets against. Defaults to the cwd. */
|
|
33
|
+
cwd?: string;
|
|
34
|
+
/** Recurse into subdirectories when the target is a directory. Default true. */
|
|
35
|
+
recursive?: boolean;
|
|
36
|
+
/** Substrings that exclude a matched path. */
|
|
37
|
+
ignorePaths?: readonly string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Expand targets to absolute `.stx` file paths, de-duplicated and sorted.
|
|
41
|
+
*
|
|
42
|
+
* A named FILE is returned whether or not it ends in `.stx`: naming one is an
|
|
43
|
+
* explicit request, and silently dropping it is the failure this module exists
|
|
44
|
+
* to remove. Directories and globs are filtered to `.stx`.
|
|
45
|
+
*
|
|
46
|
+
* `node_modules` and `dist` are always excluded — a glob like `**` + `/*.stx`
|
|
47
|
+
* otherwise sweeps up every template in every installed package.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveStxTargets(targets: readonly string[], options?: ResolveStxTargetsOptions): Promise<string[]>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const GLOB_MAGIC = /[*?[\]{}]/;
|
|
4
|
+
export function looksLikeGlob(target) {
|
|
5
|
+
return GLOB_MAGIC.test(target);
|
|
6
|
+
}
|
|
7
|
+
export async function resolveStxTargets(targets, options = {}) {
|
|
8
|
+
const cwd = options.cwd ?? process.cwd(), recursive = options.recursive !== !1, ignorePaths = options.ignorePaths ?? [], Glob = globalThis.Bun.Glob, found = new Set, accept = (file) => {
|
|
9
|
+
if (file.includes(`${path.sep}node_modules${path.sep}`) || file.includes(`${path.sep}dist${path.sep}`))
|
|
10
|
+
return;
|
|
11
|
+
if (ignorePaths.some((ignore) => ignore && file.includes(path.normalize(ignore))))
|
|
12
|
+
return;
|
|
13
|
+
found.add(file);
|
|
14
|
+
}, scan = async (pattern) => {
|
|
15
|
+
try {
|
|
16
|
+
for await (const file of new Glob(pattern).scan({ cwd, absolute: !0 }))
|
|
17
|
+
accept(file);
|
|
18
|
+
} catch {}
|
|
19
|
+
};
|
|
20
|
+
for (const target of targets) {
|
|
21
|
+
if (!target)
|
|
22
|
+
continue;
|
|
23
|
+
if (looksLikeGlob(target)) {
|
|
24
|
+
await scan(target);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const absolute = path.resolve(cwd, target);
|
|
28
|
+
if (!existsSync(absolute))
|
|
29
|
+
continue;
|
|
30
|
+
if (statSync(absolute).isDirectory()) {
|
|
31
|
+
for await (const file of new Glob(recursive ? "**/*.stx" : "*.stx").scan({ cwd: absolute, absolute: !0 }))
|
|
32
|
+
accept(file);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
accept(absolute);
|
|
36
|
+
}
|
|
37
|
+
return [...found].sort();
|
|
38
|
+
}
|
|
@@ -168,6 +168,30 @@ export declare function templateHasReactiveContext(template: string): boolean;
|
|
|
168
168
|
* signal-processing.ts would close a cycle through client-script.ts.
|
|
169
169
|
*/
|
|
170
170
|
export declare function templateNeedsRuntime(template: string): boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Colon attributes that are DIRECTIVES, not attribute bindings.
|
|
173
|
+
*
|
|
174
|
+
* `:href` and `:disabled` name a real HTML attribute and can be resolved to one.
|
|
175
|
+
* `:if`, `:for` and `:text` do not — they are instructions to the conditional
|
|
176
|
+
* processor, the loop runtime and the text binder, and the element carries no
|
|
177
|
+
* attribute of that name at any point.
|
|
178
|
+
*
|
|
179
|
+
* The distinction had never been written down, so `processServerBindings`
|
|
180
|
+
* evaluated every `:name="expr"` alike. It went unnoticed because its tag regex
|
|
181
|
+
* required each attribute chunk to start with whitespace and be a single
|
|
182
|
+
* character, so it never matched a real tag with a real attribute — the pass was
|
|
183
|
+
* effectively dead. Fixing that regex (0.2.173) switched it on for everything at
|
|
184
|
+
* once, and `<p :if="error">` started rendering as `<p if="Bad creds">`: the
|
|
185
|
+
* attribute leaked into the markup AND the conditional stopped applying, so a
|
|
186
|
+
* falsy condition no longer removed the element. Same for `:show`, `:text`,
|
|
187
|
+
* `:html`, `:model` and `:key`.
|
|
188
|
+
*
|
|
189
|
+
* `:class` and `:style` are deliberately absent: they DO resolve to real
|
|
190
|
+
* attributes, and `processServerBindings` has specific handling for them.
|
|
191
|
+
*/
|
|
192
|
+
export declare const RUNTIME_OWNED_COLON_ATTRS: readonly string[];
|
|
193
|
+
/** Is this colon attribute a directive rather than something to resolve? */
|
|
194
|
+
export declare function isRuntimeOwnedColonAttr(name: string): boolean;
|
|
171
195
|
/**
|
|
172
196
|
* `x-` attributes the signals runtime consumes itself.
|
|
173
197
|
*
|
package/dist/runtime-globals.js
CHANGED
|
@@ -143,6 +143,22 @@ export function templateNeedsRuntime(template) {
|
|
|
143
143
|
return !1;
|
|
144
144
|
return HAS_EVENT_HANDLER.test(blankInertHtmlRegions(template)) || templateHasReactiveContext(template);
|
|
145
145
|
}
|
|
146
|
+
export const RUNTIME_OWNED_COLON_ATTRS = [
|
|
147
|
+
"if",
|
|
148
|
+
"else-if",
|
|
149
|
+
"elseif",
|
|
150
|
+
"else",
|
|
151
|
+
"for",
|
|
152
|
+
"show",
|
|
153
|
+
"key",
|
|
154
|
+
"text",
|
|
155
|
+
"html",
|
|
156
|
+
"model",
|
|
157
|
+
"ref"
|
|
158
|
+
];
|
|
159
|
+
export function isRuntimeOwnedColonAttr(name) {
|
|
160
|
+
return RUNTIME_OWNED_COLON_ATTRS.includes(name.toLowerCase());
|
|
161
|
+
}
|
|
146
162
|
export const RUNTIME_HANDLED_X_ATTRS = [
|
|
147
163
|
"x-text",
|
|
148
164
|
"x-html",
|
|
@@ -72,6 +72,42 @@ export declare function outputNeedsSignalsRuntime(html: string): boolean;
|
|
|
72
72
|
* The runtime provides client-side reactivity.
|
|
73
73
|
*/
|
|
74
74
|
export declare function injectSignalsRuntime(template: string, options: StxOptions): Promise<string>;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the finished page has an element carrying `x-tooltip`.
|
|
77
|
+
*
|
|
78
|
+
* Asked of the OUTPUT rather than the source, for the reason
|
|
79
|
+
* `outputNeedsSignalsRuntime` is: both the attribute and every rewrite that
|
|
80
|
+
* could have produced it have happened by then, so no processing order can hide
|
|
81
|
+
* the answer.
|
|
82
|
+
*
|
|
83
|
+
* Anchored on `<` … so the name has to sit inside a tag: documentation prose
|
|
84
|
+
* that merely names the attribute does not pull a runtime onto the page. The
|
|
85
|
+
* attribute value is allowed to contain `>` — a tooltip reading `a > b` is
|
|
86
|
+
* ordinary — so the scan walks to the quote rather than to the first `>`.
|
|
87
|
+
*/
|
|
88
|
+
export declare function outputNeedsTooltipRuntime(html: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Ship the `x-tooltip` runtime on any page that uses the attribute.
|
|
91
|
+
*
|
|
92
|
+
* `getTooltipRuntime()` was written, exported from `builtins/index.ts`, and
|
|
93
|
+
* called by nothing — two definitions and zero call sites, in stx and in
|
|
94
|
+
* `bun-plugin-stx`. `registerBuiltins()` registers ten builtins and tooltip is
|
|
95
|
+
* not one of them, so the attribute reached the DOM and nothing ever acted on
|
|
96
|
+
* it. Hovering showed the native `title` tooltip, which would have shown anyway
|
|
97
|
+
* (stacksjs/stx#1922).
|
|
98
|
+
*
|
|
99
|
+
* The dead export was not merely unused: the codemod's largest and only
|
|
100
|
+
* auto-fixable rule rewrites `title=` into `x-tooltip=`, so every consuming
|
|
101
|
+
* codebase was being pointed at an attribute that had never worked. It read as
|
|
102
|
+
* an adoption problem — `codemod.d.ts` records `x-tooltip` as "delivered and
|
|
103
|
+
* used zero times" — when the cause was that there was nothing to adopt.
|
|
104
|
+
*
|
|
105
|
+
* Not a registered builtin, because it is not a component: it is one delegated
|
|
106
|
+
* listener pair on `document`, so it costs nothing when no element matches and
|
|
107
|
+
* covers elements added later without per-element wiring. Injected only when the
|
|
108
|
+
* attribute is present, and before the CSP pass so a nonce still reaches it.
|
|
109
|
+
*/
|
|
110
|
+
export declare function injectTooltipRuntime(html: string): string;
|
|
75
111
|
/**
|
|
76
112
|
* Inject the SPA router script into the template.
|
|
77
113
|
* The router is provided by the canonical router in packages/router/src/client.ts.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getOwnedRouteMatchers } from "./owned-routes.js";
|
|
2
2
|
import { toScriptJson } from "./script-json.js";
|
|
3
3
|
import { findBodyOpenTag, replaceBodyOpenTag } from "./find-body-tag.js";
|
|
4
|
+
import { getTooltipRuntime } from "./builtins/tooltip.js";
|
|
4
5
|
export function injectBrowserRuntime(template) {
|
|
5
6
|
if (template.includes("window.StacksBrowser") || template.includes("StacksBrowser ="))
|
|
6
7
|
return template;
|
|
@@ -32,6 +33,7 @@ export function injectBrowserRuntime(template) {
|
|
|
32
33
|
"clamp",
|
|
33
34
|
"rand",
|
|
34
35
|
"readableSize",
|
|
36
|
+
"useActiveElement",
|
|
35
37
|
"useDocumentVisibility",
|
|
36
38
|
"useIntervalFn"
|
|
37
39
|
].some((sym) => {
|
|
@@ -108,6 +110,19 @@ export async function injectSignalsRuntime(template, options) {
|
|
|
108
110
|
const { getCachedSignalsRuntime } = await import("./caching.js"), runtime = await getCachedSignalsRuntime(options.debug);
|
|
109
111
|
return placeRuntimeTag(template, `<script data-stx-scoped data-stx-runtime>${runtime}</script>`);
|
|
110
112
|
}
|
|
113
|
+
export function outputNeedsTooltipRuntime(html) {
|
|
114
|
+
return /<[a-z][^>]*?\sx-tooltip\s*=/i.test(html);
|
|
115
|
+
}
|
|
116
|
+
export function injectTooltipRuntime(html) {
|
|
117
|
+
if (html.includes("data-stx-tooltip-runtime") || !outputNeedsTooltipRuntime(html))
|
|
118
|
+
return html;
|
|
119
|
+
const tag = `<script data-stx-scoped data-stx-tooltip-runtime>${getTooltipRuntime()}</script>`, bodyIdx = html.lastIndexOf("</body>");
|
|
120
|
+
if (bodyIdx === -1)
|
|
121
|
+
return `${html}
|
|
122
|
+
${tag}`;
|
|
123
|
+
return `${html.slice(0, bodyIdx)}${tag}
|
|
124
|
+
${html.slice(bodyIdx)}`;
|
|
125
|
+
}
|
|
111
126
|
export async function injectRouterScript(template, options) {
|
|
112
127
|
if (!template.includes("</body>"))
|
|
113
128
|
return template;
|
package/dist/server-bindings.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRuntimeOwnedColonAttr } from "./runtime-globals.js";
|
|
1
2
|
const BOOLEAN_ATTRS = new Set([
|
|
2
3
|
"disabled",
|
|
3
4
|
"checked",
|
|
@@ -96,6 +97,8 @@ export function processServerBindings(template, context) {
|
|
|
96
97
|
let attrMatch, newAttrs = attrs, hadReplacement = !1;
|
|
97
98
|
while ((attrMatch = bindingRegex.exec(attrs)) !== null) {
|
|
98
99
|
const attrName = attrMatch[1], expression = attrMatch[2];
|
|
100
|
+
if (isRuntimeOwnedColonAttr(attrName))
|
|
101
|
+
continue;
|
|
99
102
|
if (expression.includes("()") && !expression.includes(".get(") || expression.includes("$store") || expression.includes("$ref"))
|
|
100
103
|
continue;
|
|
101
104
|
try {
|
|
@@ -801,7 +801,7 @@ export function extractExports(setupContent) {
|
|
|
801
801
|
}, checkDeclaration = () => {
|
|
802
802
|
if (depth !== 0)
|
|
803
803
|
return;
|
|
804
|
-
const declMatch = code.slice(i).match(/^(const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s
|
|
804
|
+
const declMatch = code.slice(i).match(/^(const|let|var)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?:[!:;,\n]|=(?!=)|$)/);
|
|
805
805
|
if (declMatch) {
|
|
806
806
|
const varName = declMatch[2];
|
|
807
807
|
if (!seen.has(varName)) {
|
package/dist/signals.js
CHANGED
|
@@ -1183,7 +1183,7 @@ else if (immediate) {
|
|
|
1183
1183
|
var ownerScope = currentLifecycleScope() || componentScope;
|
|
1184
1184
|
return {
|
|
1185
1185
|
get current() {
|
|
1186
|
-
return ownerScope.$refs
|
|
1186
|
+
return (ownerScope.$refs && ownerScope.$refs[name]) || null;
|
|
1187
1187
|
},
|
|
1188
1188
|
get value() {
|
|
1189
1189
|
return this.current;
|
|
@@ -2769,12 +2769,16 @@ else if (name === 'ref' || name === ':ref' || name === 'x-ref' || name === 'data
|
|
|
2769
2769
|
? event.detail
|
|
2770
2770
|
: event;
|
|
2771
2771
|
|
|
2772
|
-
// Skip
|
|
2773
|
-
//
|
|
2772
|
+
// Skip an opener click that reaches UI which just became visible in
|
|
2773
|
+
// this frame. A click whose target is inside the revealed subtree is
|
|
2774
|
+
// a real interaction and must not be discarded, especially for
|
|
2775
|
+
// async lists whose controls are usable as soon as they render.
|
|
2774
2776
|
if (eventName === 'click') {
|
|
2775
2777
|
var ancestor = el;
|
|
2776
2778
|
while (ancestor) {
|
|
2777
|
-
if (ancestor.__stx_shown_at
|
|
2779
|
+
if (ancestor.__stx_shown_at
|
|
2780
|
+
&& (performance.now() - ancestor.__stx_shown_at) < 50
|
|
2781
|
+
&& !(ancestor.contains && ancestor.contains(event.target))) return;
|
|
2778
2782
|
ancestor = ancestor.parentElement;
|
|
2779
2783
|
}
|
|
2780
2784
|
}
|
|
@@ -4367,33 +4371,30 @@ catch (e2) {
|
|
|
4367
4371
|
}
|
|
4368
4372
|
|
|
4369
4373
|
// Helper to evaluate with captured scope (auto-unwraps signals).
|
|
4370
|
-
//
|
|
4371
|
-
//
|
|
4372
|
-
//
|
|
4373
|
-
//
|
|
4374
|
-
//
|
|
4375
|
-
//
|
|
4376
|
-
//
|
|
4377
|
-
// for EVERY comparison/boolean expression. bindIf was the only
|
|
4378
|
-
// directive missing this retry.
|
|
4374
|
+
// A with-scope resolves only identifiers the expression actually references,
|
|
4375
|
+
// so the conditional subscribes narrowly instead of reading every signal
|
|
4376
|
+
// in a component scope. That broad subscription made an unrelated ref
|
|
4377
|
+
// update re-enter structural removal while the real condition was already
|
|
4378
|
+
// removing the same subtree. First try the auto-unwrap proxy (so a bare
|
|
4379
|
+
// comparison like count > 5 reads the signal value), then retry with the
|
|
4380
|
+
// raw scope so call syntax like count() === 0 still works (#1733).
|
|
4379
4381
|
const evalExpr = (expression) => {
|
|
4380
4382
|
// Skip placeholder expressions like __TITLE__ (build-time placeholders)
|
|
4381
4383
|
if (/^__[A-Z_]+__$/.test(expression.trim())) {
|
|
4382
4384
|
return expression;
|
|
4383
4385
|
}
|
|
4384
4386
|
try {
|
|
4385
|
-
// Use captured componentScope (with @for vars) merged with element scope
|
|
4386
4387
|
const scope = { ...globalHelpers, ...capturedComponentScope, ...(capturedElementScope || {}) };
|
|
4387
4388
|
const unwrapScope = createExpressionAutoUnwrapProxy(scope, expression);
|
|
4388
|
-
const fn = new Function(
|
|
4389
|
-
return fn(
|
|
4389
|
+
const fn = new Function('__scope__', 'with(__scope__) { return ' + expression + ' }');
|
|
4390
|
+
return fn(unwrapScope);
|
|
4390
4391
|
}
|
|
4391
4392
|
catch (e1) {
|
|
4392
4393
|
try {
|
|
4393
4394
|
// Retry without the unwrap proxy so call-syntax (signal()) works.
|
|
4394
4395
|
const scope2 = { ...globalHelpers, ...capturedComponentScope, ...(capturedElementScope || {}) };
|
|
4395
|
-
const fn2 = new Function(
|
|
4396
|
-
return fn2(
|
|
4396
|
+
const fn2 = new Function('__scope__', 'with(__scope__) { return ' + expression + ' }');
|
|
4397
|
+
return fn2(scope2);
|
|
4397
4398
|
}
|
|
4398
4399
|
catch (e2) {
|
|
4399
4400
|
if (!(e2 instanceof ReferenceError) && !(e2 instanceof TypeError)) console.warn('[STX] Expression error:', expression, e2);
|
|
@@ -4450,11 +4451,6 @@ catch (e2) {
|
|
|
4450
4451
|
value = directSignal();
|
|
4451
4452
|
console.log('[stx] bindIf effect (direct):', expr, '\u2192', value, 'isInserted:', isInserted);
|
|
4452
4453
|
} else {
|
|
4453
|
-
// Complex expression: read all signals first for tracking, then evaluate
|
|
4454
|
-
for (var sk in fullScope) {
|
|
4455
|
-
var sv = fullScope[sk];
|
|
4456
|
-
if (sv && typeof sv === 'function' && (sv._isSignal || sv._isDerived)) sv();
|
|
4457
|
-
}
|
|
4458
4454
|
value = evalExpr(expr);
|
|
4459
4455
|
}
|
|
4460
4456
|
|
|
@@ -4892,12 +4888,19 @@ else if (timer === null) {
|
|
|
4892
4888
|
};
|
|
4893
4889
|
}
|
|
4894
4890
|
|
|
4895
|
-
// Queue work after the current synchronous signal/effect flush
|
|
4896
|
-
//
|
|
4897
|
-
//
|
|
4891
|
+
// Queue work after the current synchronous signal/effect flush and after
|
|
4892
|
+
// structural directives finish their deferred subtree hydration. The
|
|
4893
|
+
// microtask schedules this timer only after every subscriber has run, so a
|
|
4894
|
+
// :if/:for timer created later in the same signal flush runs first and its
|
|
4895
|
+
// template refs are available to the callback.
|
|
4898
4896
|
function nextTick(fn) {
|
|
4899
4897
|
return Promise.resolve().then(function() {
|
|
4900
|
-
|
|
4898
|
+
return new Promise(function(resolve) {
|
|
4899
|
+
setTimeout(function() {
|
|
4900
|
+
if (fn) fn();
|
|
4901
|
+
resolve();
|
|
4902
|
+
}, 0);
|
|
4903
|
+
});
|
|
4901
4904
|
});
|
|
4902
4905
|
}
|
|
4903
4906
|
|
package/dist/ssg.d.ts
CHANGED
|
@@ -46,6 +46,29 @@
|
|
|
46
46
|
export interface SSGConfig {
|
|
47
47
|
/** Directory containing pages (default: 'pages') */
|
|
48
48
|
pagesDir?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Directory `@include` resolves against. Defaults to the config's
|
|
51
|
+
* `partialsDir`.
|
|
52
|
+
*
|
|
53
|
+
* `pagesDir`, `publicDir` and `outputDir` were all overridable here and these
|
|
54
|
+
* two were not, so a caller could point the build at one directory layout and
|
|
55
|
+
* silently get another for its partials (stacksjs/stx#1921).
|
|
56
|
+
*/
|
|
57
|
+
partialsDir?: string;
|
|
58
|
+
/** Directory components resolve against. Defaults to the config's `componentsDir`. */
|
|
59
|
+
componentsDir?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Fail the build when an `@include` cannot be resolved (default: true).
|
|
62
|
+
*
|
|
63
|
+
* A failed include renders the error into the page and, before this, left the
|
|
64
|
+
* build reporting `Failed: 0` with exit 0 — so the only way to find it was to
|
|
65
|
+
* read the emitted HTML, which is exactly what nobody does when the build says
|
|
66
|
+
* success. An unresolvable include is not a recoverable condition in a build:
|
|
67
|
+
* it produces a file you would never knowingly deploy.
|
|
68
|
+
*
|
|
69
|
+
* Set `false` for the old behaviour.
|
|
70
|
+
*/
|
|
71
|
+
failOnIncludeError?: boolean;
|
|
49
72
|
/** Output directory for generated files (default: 'dist') */
|
|
50
73
|
outputDir?: string;
|
|
51
74
|
/** Base URL for the site (default: '/') */
|