@analogjs/platform 3.0.0-alpha.12 → 3.0.0-alpha.14
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/package.json +9 -7
- package/src/index.d.ts +2 -1
- package/src/index.js +2 -1
- package/src/index.js.map +1 -1
- package/src/lib/content/shiki/shiki-highlighter.d.ts +2 -2
- package/src/lib/content/shiki/shiki-highlighter.js +2 -2
- package/src/lib/content/shiki/shiki-highlighter.js.map +1 -1
- package/src/lib/json-ld-manifest-plugin.d.ts +41 -0
- package/src/lib/json-ld-manifest-plugin.js +84 -0
- package/src/lib/json-ld-manifest-plugin.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular/vite.config.ts__template__ +6 -0
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v17/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v18/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/files/template-angular-v19/vite.config.ts__template__ +0 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js +0 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-config.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.d.ts +0 -2
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js +1 -26
- package/src/lib/nx-plugin/src/generators/app/lib/add-tailwind-helpers.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.d.ts +7 -9
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js +2 -4
- package/src/lib/nx-plugin/src/generators/app/versions/nx_18_X/versions.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.d.ts +1 -1
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js +1 -2
- package/src/lib/nx-plugin/src/generators/app/versions/tailwind-dependencies.js.map +1 -1
- package/src/lib/nx-plugin/src/generators/preset/__snapshots__/generator.spec.ts.snap +3 -1
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.d.ts +5 -5
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js +5 -5
- package/src/lib/nx-plugin/src/utils/versions/ng_19_X/versions.js.map +1 -1
- package/src/lib/options.d.ts +78 -4
- package/src/lib/platform-plugin.js +10 -2
- package/src/lib/platform-plugin.js.map +1 -1
- package/src/lib/route-file-discovery.d.ts +23 -0
- package/src/lib/route-file-discovery.js +114 -0
- package/src/lib/route-file-discovery.js.map +1 -0
- package/src/lib/route-generation-plugin.d.ts +3 -0
- package/src/lib/route-generation-plugin.js +34 -0
- package/src/lib/route-generation-plugin.js.map +1 -0
- package/src/lib/route-manifest.d.ts +104 -0
- package/src/lib/route-manifest.js +363 -0
- package/src/lib/route-manifest.js.map +1 -0
- package/src/lib/typed-routes-plugin.d.ts +50 -0
- package/src/lib/typed-routes-plugin.js +204 -0
- package/src/lib/typed-routes-plugin.js.map +1 -0
- package/src/lib/nx-plugin/src/generators/app/files/tailwind/v4/.postcssrc.json +0 -5
- package/src/lib/nx-plugin/src/generators/app/files/tailwind/v4/tailwind.config.ts__template__ +0 -14
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { detectSchemaExports, filenameToRoutePath, formatManifestSummary, generateRouteManifest, generateRouteTableDeclaration, generateRouteTreeDeclaration } from "./route-manifest.js";
|
|
2
|
+
import { detectJsonLdModuleExports, extractMarkdownJsonLd, generateJsonLdManifestSource } from "./json-ld-manifest-plugin.js";
|
|
3
|
+
import { createRouteFileDiscovery } from "./route-file-discovery.js";
|
|
4
|
+
import { normalizePath } from "vite";
|
|
5
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
|
+
//#region packages/platform/src/lib/typed-routes-plugin.ts
|
|
8
|
+
var DEFAULT_OUT_FILE = "src/routeTree.gen.ts";
|
|
9
|
+
function resolvePluginOptions(options = {}) {
|
|
10
|
+
return {
|
|
11
|
+
outFile: options.outFile ?? DEFAULT_OUT_FILE,
|
|
12
|
+
workspaceRoot: options.workspaceRoot ?? process.cwd(),
|
|
13
|
+
additionalPagesDirs: options.additionalPagesDirs ?? [],
|
|
14
|
+
additionalContentDirs: options.additionalContentDirs ?? [],
|
|
15
|
+
jsonLdManifest: options.jsonLdManifest ?? true,
|
|
16
|
+
verify: options.verify ?? false,
|
|
17
|
+
verifyOnBuild: options.verifyOnBuild ?? true
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Vite plugin that generates a single typed route module for Analog file routes.
|
|
22
|
+
*/
|
|
23
|
+
function typedRoutes(options = {}) {
|
|
24
|
+
const resolvedOptions = resolvePluginOptions(options);
|
|
25
|
+
const workspaceRoot = normalizePath(resolvedOptions.workspaceRoot);
|
|
26
|
+
let root = "";
|
|
27
|
+
let command = "serve";
|
|
28
|
+
let discovery;
|
|
29
|
+
function isFreshnessCheck() {
|
|
30
|
+
return resolvedOptions.verify || command === "build" && resolvedOptions.verifyOnBuild;
|
|
31
|
+
}
|
|
32
|
+
function resolveDiscoveredFile(filename) {
|
|
33
|
+
const fromRoot = join(root, filename);
|
|
34
|
+
if (existsSync(fromRoot)) return fromRoot;
|
|
35
|
+
return join(workspaceRoot, filename);
|
|
36
|
+
}
|
|
37
|
+
function detectSchemas(relativeFilename) {
|
|
38
|
+
if (!relativeFilename.endsWith(".ts")) return {
|
|
39
|
+
hasParamsSchema: false,
|
|
40
|
+
hasQuerySchema: false
|
|
41
|
+
};
|
|
42
|
+
try {
|
|
43
|
+
return detectSchemaExports(readFileSync(resolveDiscoveredFile(relativeFilename), "utf-8"));
|
|
44
|
+
} catch {
|
|
45
|
+
return {
|
|
46
|
+
hasParamsSchema: false,
|
|
47
|
+
hasQuerySchema: false
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Ensures the generated route file is imported from an app entry file
|
|
53
|
+
* so the module augmentation is always part of the TypeScript program.
|
|
54
|
+
*/
|
|
55
|
+
function ensureEntryImport() {
|
|
56
|
+
const entryFiles = ["src/main.ts", "src/main.server.ts"];
|
|
57
|
+
function importSpecifierFor(entryFile) {
|
|
58
|
+
const rel = relative(dirname(entryFile), resolvedOptions.outFile).replace(/\.ts$/, "").replace(/\\/g, "/");
|
|
59
|
+
return rel.startsWith(".") ? rel : "./" + rel;
|
|
60
|
+
}
|
|
61
|
+
for (const entryFile of entryFiles) {
|
|
62
|
+
const entryPath = join(root, entryFile);
|
|
63
|
+
if (!existsSync(entryPath)) continue;
|
|
64
|
+
const content = readFileSync(entryPath, "utf-8");
|
|
65
|
+
const specifier = importSpecifierFor(entryFile);
|
|
66
|
+
const escaped = specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
67
|
+
if (new RegExp(`import\\s+['"]${escaped}(\\.ts|\\.js)?['"]`).test(content)) return;
|
|
68
|
+
if (isFreshnessCheck()) return;
|
|
69
|
+
const importLine = `import '${specifier}';`;
|
|
70
|
+
const lines = content.split("\n");
|
|
71
|
+
let lastImportLine = -1;
|
|
72
|
+
for (let i = 0; i < lines.length; i++) if (/^import\s/.test(lines[i])) lastImportLine = i;
|
|
73
|
+
if (lastImportLine >= 0) lines.splice(lastImportLine + 1, 0, importLine);
|
|
74
|
+
else lines.unshift(importLine);
|
|
75
|
+
writeFileSync(entryPath, lines.join("\n"), "utf-8");
|
|
76
|
+
console.log(`[analog] Added route tree import to ${entryFile}`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const specifier = importSpecifierFor("src/main.ts");
|
|
80
|
+
if (isFreshnessCheck()) return;
|
|
81
|
+
console.warn(`[analog] Could not find an entry file (src/main.ts or src/main.server.ts) to add the route tree import. Add \`import '${specifier}';\` to your app entry file to ensure typed routing is active.`);
|
|
82
|
+
}
|
|
83
|
+
function generate() {
|
|
84
|
+
const routeFiles = discovery.getRouteFiles();
|
|
85
|
+
const contentFiles = discovery.getContentFiles();
|
|
86
|
+
const manifest = generateRouteManifest([...routeFiles, ...contentFiles], detectSchemas, (filename) => discovery.isAppLocal(filename) ? 0 : 1);
|
|
87
|
+
const declaration = generateRouteTableDeclaration(manifest);
|
|
88
|
+
const canonicalFiles = new Set(manifest.routes.map((route) => route.filename));
|
|
89
|
+
const jsonLdEntries = buildJsonLdEntries(resolveDiscoveredFile, routeFiles.filter((filename) => canonicalFiles.has(filename)), contentFiles.filter((filename) => canonicalFiles.has(filename)));
|
|
90
|
+
const output = combineGeneratedModules(declaration, generateRouteTreeDeclaration(manifest, { jsonLdPaths: jsonLdEntries.map((entry) => entry.routePath) }), resolvedOptions.jsonLdManifest && jsonLdEntries.length > 0 ? generateJsonLdManifestSource(jsonLdEntries, resolvedOptions.outFile) : "");
|
|
91
|
+
if (manifest.routes.length > 0) console.log(formatManifestSummary(manifest));
|
|
92
|
+
const outPath = join(root, resolvedOptions.outFile);
|
|
93
|
+
const outDir = dirname(outPath);
|
|
94
|
+
const hadExistingOutput = existsSync(outPath);
|
|
95
|
+
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
|
|
96
|
+
let existing = "";
|
|
97
|
+
try {
|
|
98
|
+
existing = readFileSync(outPath, "utf-8");
|
|
99
|
+
} catch {}
|
|
100
|
+
if (output.includes(root)) console.warn(`[analog] Generated route output contains an absolute path prefix (${root}). Route keys and sourceFile values should be workspace-relative.`);
|
|
101
|
+
const normalizeEndings = (s) => s.replace(/\r\n/g, "\n");
|
|
102
|
+
if (normalizeEndings(existing) !== normalizeEndings(output)) {
|
|
103
|
+
if (resolvedOptions.verify) throw new Error(`[analog] Stale route file detected: ${resolvedOptions.outFile}\nThe checked-in generated route file does not match the current route sources.\nRegenerate route files and commit the updated output.`);
|
|
104
|
+
writeFileSync(outPath, output, "utf-8");
|
|
105
|
+
if (command === "build" && resolvedOptions.verifyOnBuild && hadExistingOutput) throw new Error(`[analog] Stale route file detected during build: ${resolvedOptions.outFile}\nThe generated route file was updated to match the current route sources.\nReview the updated output, commit it if it is checked in, and rerun the build.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
name: "analog-typed-routes",
|
|
110
|
+
config(config, env) {
|
|
111
|
+
command = env.command;
|
|
112
|
+
root = normalizePath(resolve(workspaceRoot, config.root || ".") || ".");
|
|
113
|
+
discovery = createRouteFileDiscovery({
|
|
114
|
+
root,
|
|
115
|
+
workspaceRoot,
|
|
116
|
+
additionalPagesDirs: resolvedOptions.additionalPagesDirs,
|
|
117
|
+
additionalContentDirs: resolvedOptions.additionalContentDirs
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
buildStart() {
|
|
121
|
+
generate();
|
|
122
|
+
if (!isFreshnessCheck()) ensureEntryImport();
|
|
123
|
+
},
|
|
124
|
+
configureServer(server) {
|
|
125
|
+
const regenerate = (path, event) => {
|
|
126
|
+
if (!discovery.getDiscoveredFileKind(path)) return;
|
|
127
|
+
discovery.updateDiscoveredFile(path, event);
|
|
128
|
+
generate();
|
|
129
|
+
};
|
|
130
|
+
server.watcher.on("add", (path) => regenerate(path, "add"));
|
|
131
|
+
server.watcher.on("change", (path) => regenerate(path, "change"));
|
|
132
|
+
server.watcher.on("unlink", (path) => regenerate(path, "unlink"));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function buildJsonLdEntries(resolveFile, routeFiles, contentFiles) {
|
|
137
|
+
const entries = [];
|
|
138
|
+
let importIndex = 0;
|
|
139
|
+
routeFiles.forEach((filename) => {
|
|
140
|
+
try {
|
|
141
|
+
if (!detectJsonLdModuleExports(readFileSync(resolveFile(filename), "utf-8"))) return;
|
|
142
|
+
entries.push({
|
|
143
|
+
kind: "module",
|
|
144
|
+
routePath: filenameToRoutePath(filename),
|
|
145
|
+
sourceFile: filename,
|
|
146
|
+
importAlias: `routeModule${importIndex++}`
|
|
147
|
+
});
|
|
148
|
+
} catch {}
|
|
149
|
+
});
|
|
150
|
+
contentFiles.forEach((filename) => {
|
|
151
|
+
try {
|
|
152
|
+
const jsonLd = extractMarkdownJsonLd(readFileSync(resolveFile(filename), "utf-8"));
|
|
153
|
+
if (jsonLd.length === 0) return;
|
|
154
|
+
entries.push({
|
|
155
|
+
kind: "content",
|
|
156
|
+
routePath: filenameToRoutePath(filename),
|
|
157
|
+
sourceFile: filename,
|
|
158
|
+
jsonLd
|
|
159
|
+
});
|
|
160
|
+
} catch {}
|
|
161
|
+
});
|
|
162
|
+
return entries.sort((a, b) => a.routePath.localeCompare(b.routePath));
|
|
163
|
+
}
|
|
164
|
+
function combineGeneratedModules(...sources) {
|
|
165
|
+
const imports = [];
|
|
166
|
+
const seenImports = /* @__PURE__ */ new Set();
|
|
167
|
+
const bodies = [];
|
|
168
|
+
for (const source of sources) {
|
|
169
|
+
const { body, importLines } = splitGeneratedModule(source);
|
|
170
|
+
for (const importLine of importLines) if (!seenImports.has(importLine)) {
|
|
171
|
+
seenImports.add(importLine);
|
|
172
|
+
imports.push(importLine);
|
|
173
|
+
}
|
|
174
|
+
if (body.trim()) bodies.push(body.trim());
|
|
175
|
+
}
|
|
176
|
+
return [
|
|
177
|
+
"// This file is auto-generated by @analogjs/platform",
|
|
178
|
+
"// Do not edit manually",
|
|
179
|
+
"",
|
|
180
|
+
...imports.length > 0 ? [...imports, ""] : [],
|
|
181
|
+
bodies.join("\n\n"),
|
|
182
|
+
""
|
|
183
|
+
].join("\n");
|
|
184
|
+
}
|
|
185
|
+
function splitGeneratedModule(source) {
|
|
186
|
+
const lines = source.split("\n");
|
|
187
|
+
let index = 0;
|
|
188
|
+
while (index < lines.length && lines[index].startsWith("//")) index++;
|
|
189
|
+
while (index < lines.length && lines[index] === "") index++;
|
|
190
|
+
const importLines = [];
|
|
191
|
+
while (index < lines.length && lines[index].startsWith("import ")) {
|
|
192
|
+
importLines.push(lines[index]);
|
|
193
|
+
index++;
|
|
194
|
+
}
|
|
195
|
+
while (index < lines.length && lines[index] === "") index++;
|
|
196
|
+
return {
|
|
197
|
+
importLines,
|
|
198
|
+
body: lines.slice(index).join("\n")
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { typedRoutes };
|
|
203
|
+
|
|
204
|
+
//# sourceMappingURL=typed-routes-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typed-routes-plugin.js","names":[],"sources":["../../../../../packages/platform/src/lib/typed-routes-plugin.ts"],"sourcesContent":["import { normalizePath, type Plugin } from 'vite';\nimport { resolve, join, dirname, relative } from 'node:path';\nimport { writeFileSync, mkdirSync, existsSync, readFileSync } from 'node:fs';\n\nimport {\n generateRouteManifest,\n generateRouteTableDeclaration,\n generateRouteTreeDeclaration,\n detectSchemaExports,\n formatManifestSummary,\n filenameToRoutePath,\n} from './route-manifest.js';\nimport type { RouteSchemaInfo } from './route-manifest.js';\nimport {\n detectJsonLdModuleExports,\n extractMarkdownJsonLd,\n generateJsonLdManifestSource,\n type JsonLdManifestEntry,\n} from './json-ld-manifest-plugin.js';\nimport {\n createRouteFileDiscovery,\n type RouteFileDiscovery,\n} from './route-file-discovery.js';\n\nconst DEFAULT_OUT_FILE = 'src/routeTree.gen.ts';\n\nexport interface TypedRoutesPluginOptions {\n /**\n * Output path for the single generated route module,\n * relative to the app root.\n *\n * @default 'src/routeTree.gen.ts'\n */\n outFile?: string;\n /**\n * Workspace root used to resolve additional route/content directories.\n *\n * @default process.cwd()\n */\n workspaceRoot?: string;\n /**\n * Additional page directories to scan for `.page.ts` files.\n */\n additionalPagesDirs?: string[];\n /**\n * Additional content directories to scan for `.md` files.\n */\n additionalContentDirs?: string[];\n /**\n * Include generated `routeJsonLdManifest` exports in the generated route file.\n *\n * @default true\n */\n jsonLdManifest?: boolean;\n /**\n * When true, compare generated output against the existing file and\n * throw an error if they differ instead of writing. Useful for CI to\n * detect stale checked-in route files.\n *\n * @default false\n */\n verify?: boolean;\n /**\n * When true, production builds fail after regenerating a stale checked-in\n * route file. This preserves self-healing writes in development while making\n * build-time freshness issues visible by default.\n *\n * @default true\n */\n verifyOnBuild?: boolean;\n}\n\nfunction resolvePluginOptions(\n options: TypedRoutesPluginOptions = {},\n): Required<TypedRoutesPluginOptions> {\n return {\n outFile: options.outFile ?? DEFAULT_OUT_FILE,\n workspaceRoot: options.workspaceRoot ?? process.cwd(),\n additionalPagesDirs: options.additionalPagesDirs ?? [],\n additionalContentDirs: options.additionalContentDirs ?? [],\n jsonLdManifest: options.jsonLdManifest ?? true,\n verify: options.verify ?? false,\n verifyOnBuild: options.verifyOnBuild ?? true,\n };\n}\n\n/**\n * Vite plugin that generates a single typed route module for Analog file routes.\n */\nexport function typedRoutes(options: TypedRoutesPluginOptions = {}): Plugin {\n const resolvedOptions = resolvePluginOptions(options);\n const workspaceRoot = normalizePath(resolvedOptions.workspaceRoot);\n let root = '';\n let command: 'build' | 'serve' = 'serve';\n let discovery: RouteFileDiscovery;\n\n function isFreshnessCheck(): boolean {\n return (\n resolvedOptions.verify ||\n (command === 'build' && resolvedOptions.verifyOnBuild)\n );\n }\n\n function resolveDiscoveredFile(filename: string): string {\n const fromRoot = join(root, filename);\n if (existsSync(fromRoot)) return fromRoot;\n return join(workspaceRoot, filename);\n }\n\n function detectSchemas(relativeFilename: string): RouteSchemaInfo {\n if (!relativeFilename.endsWith('.ts')) {\n return { hasParamsSchema: false, hasQuerySchema: false };\n }\n\n try {\n const absPath = resolveDiscoveredFile(relativeFilename);\n const content = readFileSync(absPath, 'utf-8');\n return detectSchemaExports(content);\n } catch {\n return { hasParamsSchema: false, hasQuerySchema: false };\n }\n }\n\n /**\n * Ensures the generated route file is imported from an app entry file\n * so the module augmentation is always part of the TypeScript program.\n */\n function ensureEntryImport(): void {\n const entryFiles = ['src/main.ts', 'src/main.server.ts'];\n\n // Compute the import specifier relative to the entry file\n function importSpecifierFor(entryFile: string): string {\n const rel = relative(dirname(entryFile), resolvedOptions.outFile)\n .replace(/\\.ts$/, '')\n .replace(/\\\\/g, '/');\n return rel.startsWith('.') ? rel : './' + rel;\n }\n\n for (const entryFile of entryFiles) {\n const entryPath = join(root, entryFile);\n if (!existsSync(entryPath)) continue;\n\n const content = readFileSync(entryPath, 'utf-8');\n const specifier = importSpecifierFor(entryFile);\n\n // Check if any variation of the import already exists\n const escaped = specifier.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`import\\\\s+['\"]${escaped}(\\\\.ts|\\\\.js)?['\"]`);\n if (pattern.test(content)) {\n return;\n }\n\n if (isFreshnessCheck()) {\n return;\n }\n\n // Insert the import after the last existing import line\n const importLine = `import '${specifier}';`;\n const lines = content.split('\\n');\n let lastImportLine = -1;\n\n for (let i = 0; i < lines.length; i++) {\n if (/^import\\s/.test(lines[i])) {\n lastImportLine = i;\n }\n }\n\n if (lastImportLine >= 0) {\n lines.splice(lastImportLine + 1, 0, importLine);\n } else {\n lines.unshift(importLine);\n }\n\n writeFileSync(entryPath, lines.join('\\n'), 'utf-8');\n console.log(`[analog] Added route tree import to ${entryFile}`);\n return;\n }\n\n // No suitable entry file found\n const specifier = importSpecifierFor('src/main.ts');\n if (isFreshnessCheck()) {\n return;\n }\n console.warn(\n `[analog] Could not find an entry file (src/main.ts or src/main.server.ts) ` +\n `to add the route tree import. Add \\`import '${specifier}';\\` ` +\n `to your app entry file to ensure typed routing is active.`,\n );\n }\n\n function generate(): void {\n const routeFiles = discovery.getRouteFiles();\n const contentFiles = discovery.getContentFiles();\n const allFiles = [...routeFiles, ...contentFiles];\n const manifest = generateRouteManifest(\n allFiles,\n detectSchemas,\n (filename) => (discovery.isAppLocal(filename) ? 0 : 1),\n );\n const declaration = generateRouteTableDeclaration(manifest);\n const canonicalFiles = new Set(\n manifest.routes.map((route) => route.filename),\n );\n const jsonLdEntries = buildJsonLdEntries(\n resolveDiscoveredFile,\n routeFiles.filter((filename) => canonicalFiles.has(filename)),\n contentFiles.filter((filename) => canonicalFiles.has(filename)),\n );\n const routeTree = generateRouteTreeDeclaration(manifest, {\n jsonLdPaths: jsonLdEntries.map((entry) => entry.routePath),\n });\n const output = combineGeneratedModules(\n declaration,\n routeTree,\n resolvedOptions.jsonLdManifest && jsonLdEntries.length > 0\n ? generateJsonLdManifestSource(jsonLdEntries, resolvedOptions.outFile)\n : '',\n );\n\n if (manifest.routes.length > 0) {\n console.log(formatManifestSummary(manifest));\n }\n\n const outPath = join(root, resolvedOptions.outFile);\n const outDir = dirname(outPath);\n const hadExistingOutput = existsSync(outPath);\n\n if (!existsSync(outDir)) {\n mkdirSync(outDir, { recursive: true });\n }\n\n let existing = '';\n\n try {\n existing = readFileSync(outPath, 'utf-8');\n } catch {\n // file does not exist yet\n }\n\n // Build-time guard: detect absolute path leaks in generated output.\n // Machine-specific prefixes must never appear in route keys or sourceFile values.\n if (output.includes(root)) {\n console.warn(\n `[analog] Generated route output contains an absolute path prefix (${root}). ` +\n `Route keys and sourceFile values should be workspace-relative.`,\n );\n }\n\n // Normalize line endings before comparison so that files checked in\n // with LF don't appear stale on Windows where readFileSync may return CRLF.\n const normalizeEndings = (s: string) => s.replace(/\\r\\n/g, '\\n');\n if (normalizeEndings(existing) !== normalizeEndings(output)) {\n if (resolvedOptions.verify) {\n throw new Error(\n `[analog] Stale route file detected: ${resolvedOptions.outFile}\\n` +\n `The checked-in generated route file does not match the current route sources.\\n` +\n `Regenerate route files and commit the updated output.`,\n );\n }\n\n writeFileSync(outPath, output, 'utf-8');\n\n if (\n command === 'build' &&\n resolvedOptions.verifyOnBuild &&\n hadExistingOutput\n ) {\n throw new Error(\n `[analog] Stale route file detected during build: ${resolvedOptions.outFile}\\n` +\n `The generated route file was updated to match the current route sources.\\n` +\n `Review the updated output, commit it if it is checked in, and rerun the build.`,\n );\n }\n }\n }\n\n return {\n name: 'analog-typed-routes',\n config(config, env) {\n command = env.command;\n root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.');\n discovery = createRouteFileDiscovery({\n root,\n workspaceRoot,\n additionalPagesDirs: resolvedOptions.additionalPagesDirs,\n additionalContentDirs: resolvedOptions.additionalContentDirs,\n });\n },\n buildStart() {\n generate();\n if (!isFreshnessCheck()) {\n ensureEntryImport();\n }\n },\n configureServer(server) {\n const regenerate = (path: string, event: 'add' | 'change' | 'unlink') => {\n // Reuse the discovery matcher so watch-time updates stay in sync with\n // the initial scan and don't pull Nitro server routes into routeTree.gen.ts.\n if (!discovery.getDiscoveredFileKind(path)) {\n return;\n }\n\n discovery.updateDiscoveredFile(path, event);\n generate();\n };\n\n server.watcher.on('add', (path) => regenerate(path, 'add'));\n server.watcher.on('change', (path) => regenerate(path, 'change'));\n server.watcher.on('unlink', (path) => regenerate(path, 'unlink'));\n },\n };\n}\n\nfunction buildJsonLdEntries(\n resolveFile: (filename: string) => string,\n routeFiles: string[],\n contentFiles: string[],\n): JsonLdManifestEntry[] {\n const entries: JsonLdManifestEntry[] = [];\n let importIndex = 0;\n\n routeFiles.forEach((filename) => {\n try {\n const source = readFileSync(resolveFile(filename), 'utf-8');\n if (!detectJsonLdModuleExports(source)) {\n return;\n }\n\n entries.push({\n kind: 'module',\n routePath: filenameToRoutePath(filename),\n sourceFile: filename,\n importAlias: `routeModule${importIndex++}`,\n });\n } catch {\n // ignore unreadable route file\n }\n });\n\n contentFiles.forEach((filename) => {\n try {\n const source = readFileSync(resolveFile(filename), 'utf-8');\n const jsonLd = extractMarkdownJsonLd(source);\n\n if (jsonLd.length === 0) {\n return;\n }\n\n entries.push({\n kind: 'content',\n routePath: filenameToRoutePath(filename),\n sourceFile: filename,\n jsonLd,\n });\n } catch {\n // ignore unreadable content file\n }\n });\n\n return entries.sort((a, b) => a.routePath.localeCompare(b.routePath));\n}\n\nfunction combineGeneratedModules(...sources: string[]): string {\n const imports: string[] = [];\n const seenImports = new Set<string>();\n const bodies: string[] = [];\n\n for (const source of sources) {\n const { body, importLines } = splitGeneratedModule(source);\n for (const importLine of importLines) {\n if (!seenImports.has(importLine)) {\n seenImports.add(importLine);\n imports.push(importLine);\n }\n }\n if (body.trim()) {\n bodies.push(body.trim());\n }\n }\n\n return [\n '// This file is auto-generated by @analogjs/platform',\n '// Do not edit manually',\n '',\n ...(imports.length > 0 ? [...imports, ''] : []),\n bodies.join('\\n\\n'),\n '',\n ].join('\\n');\n}\n\nfunction splitGeneratedModule(source: string): {\n importLines: string[];\n body: string;\n} {\n const lines = source.split('\\n');\n let index = 0;\n\n while (index < lines.length && lines[index].startsWith('//')) {\n index++;\n }\n\n while (index < lines.length && lines[index] === '') {\n index++;\n }\n\n const importLines: string[] = [];\n while (index < lines.length && lines[index].startsWith('import ')) {\n importLines.push(lines[index]);\n index++;\n }\n\n while (index < lines.length && lines[index] === '') {\n index++;\n }\n\n return {\n importLines,\n body: lines.slice(index).join('\\n'),\n };\n}\n"],"mappings":"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"}
|
package/src/lib/nx-plugin/src/generators/app/files/tailwind/v4/tailwind.config.ts__template__
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'tailwindcss';
|
|
2
|
-
import { createGlobPatternsForDependencies } from '@nx/angular/tailwind';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
content: [
|
|
7
|
-
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html,md,analog,ag}'),
|
|
8
|
-
...createGlobPatternsForDependencies(__dirname),
|
|
9
|
-
],
|
|
10
|
-
theme: {
|
|
11
|
-
extend: {},
|
|
12
|
-
},
|
|
13
|
-
plugins: [],
|
|
14
|
-
} satisfies Config;
|