@jxsuite/compiler 1.4.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +564 -230
- package/dist/compiler.js +334 -133
- package/package.json +11 -9
- package/src/compiler.ts +1 -1
- package/src/shadow.ts +65 -0
- package/src/shared.ts +461 -51
- package/src/site/bundler.ts +149 -18
- package/src/site/client-runtime.ts +374 -0
- package/src/site/context-injection.ts +45 -2
- package/src/site/csp.ts +224 -0
- package/src/site/head-merger.ts +57 -13
- package/src/site/headers-emitter.ts +232 -0
- package/src/site/i18n.ts +365 -0
- package/src/site/image-optimizer.ts +7 -0
- package/src/site/image-transform.ts +269 -118
- package/src/site/img-loading.ts +55 -0
- package/src/site/link-relations.ts +251 -0
- package/src/site/locale-negotiation.ts +258 -0
- package/src/site/pages-discovery.ts +149 -0
- package/src/site/preview-server.ts +9 -1
- package/src/site/schema-command.ts +138 -87
- package/src/site/service-worker.ts +294 -0
- package/src/site/site-build.ts +956 -109
- package/src/site/site-loader.ts +1 -0
- package/src/site/validate-command.ts +134 -38
- package/src/site/well-known.ts +221 -0
- package/src/targets/compile-client.ts +144 -81
- package/src/targets/compile-element.ts +620 -58
- package/src/targets/compile-server.ts +19 -2
- package/src/targets/compile-static.ts +12 -3
- package/src/types.ts +2 -0
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import { dereference } from "@apidevtools/json-schema-ref-parser";
|
|
9
9
|
import { collectServerEntries } from "../shared.ts";
|
|
10
|
+
import { localeNegotiationMiddleware } from "../site/locale-negotiation.ts";
|
|
11
|
+
import type { ResolvedI18n } from "../site/i18n.ts";
|
|
10
12
|
import type { JxElement } from "@jxsuite/schema/types";
|
|
11
13
|
|
|
12
14
|
/**
|
|
@@ -97,6 +99,7 @@ export interface SiteConnectorSpec {
|
|
|
97
99
|
* `"cloudflare-pages"`, `"node"`, `"bun"`
|
|
98
100
|
* @param {SiteMountSpec[]} [opts.mounts] - Extension server mounts, already sorted by order
|
|
99
101
|
* @param {SiteConnectorSpec[]} [opts.connectors] - Connector classes used by the mounts
|
|
102
|
+
* @param {ResolvedI18n | null} [opts.i18n] - Locale routing; drives the `/` negotiation middleware
|
|
100
103
|
* @returns {string | null} Complete worker/server source string, or null
|
|
101
104
|
*/
|
|
102
105
|
export function compileSiteServer(
|
|
@@ -106,9 +109,16 @@ export function compileSiteServer(
|
|
|
106
109
|
adapter?: string | null;
|
|
107
110
|
mounts?: SiteMountSpec[];
|
|
108
111
|
connectors?: SiteConnectorSpec[];
|
|
112
|
+
i18n?: ResolvedI18n | null;
|
|
109
113
|
} = {},
|
|
110
114
|
) {
|
|
111
|
-
const {
|
|
115
|
+
const {
|
|
116
|
+
baseUrl = "/_jx/server",
|
|
117
|
+
adapter = null,
|
|
118
|
+
mounts = [],
|
|
119
|
+
connectors = [],
|
|
120
|
+
i18n = null,
|
|
121
|
+
} = opts;
|
|
112
122
|
if (entries.length === 0 && mounts.length === 0 && !adapter) {
|
|
113
123
|
return null;
|
|
114
124
|
}
|
|
@@ -128,12 +138,19 @@ export function compileSiteServer(
|
|
|
128
138
|
? "\napp.all('*', (c) => c.env.ASSETS.fetch(c.req.raw))\n"
|
|
129
139
|
: "\n";
|
|
130
140
|
|
|
141
|
+
/*
|
|
142
|
+
* Negotiation is middleware and it is registered FIRST, before any route and before the ASSETS
|
|
143
|
+
* fallthrough. It has to be: on `/` it either redirects or hands the request straight back to
|
|
144
|
+
* whatever would have served it, and it cannot do the second from behind a terminal handler.
|
|
145
|
+
*/
|
|
146
|
+
const localeBlock = localeNegotiationMiddleware(i18n);
|
|
147
|
+
|
|
131
148
|
return `// Generated by @jxsuite/compiler — do not edit manually
|
|
132
149
|
import { Hono } from 'hono'
|
|
133
150
|
${imports}${mountBlock.imports}
|
|
134
151
|
|
|
135
152
|
const app = new Hono()
|
|
136
|
-
${mountBlock.routes}${routes}
|
|
153
|
+
${localeBlock}${mountBlock.routes}${routes}
|
|
137
154
|
${adapterBlock}
|
|
138
155
|
export default app
|
|
139
156
|
`;
|
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
buildAttrs,
|
|
10
|
+
childSeparator,
|
|
10
11
|
colorSchemePrePaintScript,
|
|
11
12
|
compileStyles,
|
|
12
13
|
createCompileContext,
|
|
13
14
|
escapeHtml,
|
|
14
15
|
isNodeDynamic,
|
|
16
|
+
PREFORMATTED_TAGS,
|
|
15
17
|
pureSchemeOf,
|
|
18
|
+
resolveStaticTagName,
|
|
16
19
|
resolveStaticValue,
|
|
17
20
|
SELF_CLOSING,
|
|
18
21
|
} from "../shared.ts";
|
|
@@ -127,6 +130,7 @@ function compileNode(
|
|
|
127
130
|
scope: Record<string, unknown> | null;
|
|
128
131
|
scopeDefs: Record<string, unknown>;
|
|
129
132
|
media: Record<string, string>;
|
|
133
|
+
preformatted?: boolean;
|
|
130
134
|
},
|
|
131
135
|
islands: { def: JxMutableNode; tagName: string; className: string }[],
|
|
132
136
|
): string {
|
|
@@ -157,7 +161,9 @@ function compileNode(
|
|
|
157
161
|
return `<${tagName}></${tagName}>`;
|
|
158
162
|
}
|
|
159
163
|
|
|
160
|
-
|
|
164
|
+
// Resolved against the same scope the attributes are, so the prerendered element and its
|
|
165
|
+
// Attributes come from one decision rather than two.
|
|
166
|
+
const tag = resolveStaticTagName(def.tagName, nextContext.scope);
|
|
161
167
|
const attrs = buildAttrs(def, nextContext.scope);
|
|
162
168
|
|
|
163
169
|
// Void elements (br, hr, img, …) have no closing tag.
|
|
@@ -166,7 +172,9 @@ function compileNode(
|
|
|
166
172
|
return `<${tag}${attrs}>`;
|
|
167
173
|
}
|
|
168
174
|
|
|
169
|
-
|
|
175
|
+
// `white-space` inherits, so once inside a <pre> the whole subtree stays whitespace-significant.
|
|
176
|
+
const preformatted = context.preformatted === true || PREFORMATTED_TAGS.has(tag);
|
|
177
|
+
const inner = buildInnerWithIslands(def, raw, { ...nextContext, preformatted }, islands);
|
|
170
178
|
|
|
171
179
|
return `<${tag}${attrs}>${inner}</${tag}>`;
|
|
172
180
|
}
|
|
@@ -188,6 +196,7 @@ function buildInnerWithIslands(
|
|
|
188
196
|
scope: Record<string, unknown> | null;
|
|
189
197
|
scopeDefs: Record<string, unknown>;
|
|
190
198
|
media: Record<string, string>;
|
|
199
|
+
preformatted?: boolean;
|
|
191
200
|
},
|
|
192
201
|
islands: { def: JxMutableNode; tagName: string; className: string }[],
|
|
193
202
|
): string {
|
|
@@ -209,7 +218,7 @@ function buildInnerWithIslands(
|
|
|
209
218
|
const childRaw = (rawChildren?.[i] ?? c) as JxMutableNode;
|
|
210
219
|
return compileNode(child, childDynamic, childRaw, context, islands);
|
|
211
220
|
})
|
|
212
|
-
.join(
|
|
221
|
+
.join(childSeparator(context.preformatted));
|
|
213
222
|
}
|
|
214
223
|
return "";
|
|
215
224
|
}
|
package/src/types.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface HeadMergeContext {
|
|
|
6
6
|
url?: string;
|
|
7
7
|
siteUrl?: string;
|
|
8
8
|
pageUrl?: string;
|
|
9
|
+
/** `rel="alternate"` links for this page's translations (site-architecture.md §13.5). */
|
|
10
|
+
alternates?: readonly { hreflang: string; href: string }[];
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export interface SiteRoute {
|