@paroicms/site-generator-plugin 0.24.2 → 0.25.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/backend/dist/generator/fake-content-generator/create-node-contents.js +13 -2
- package/backend/dist/generator/fake-content-generator/generate-fake-content.js +2 -1
- package/backend/dist/generator/lib/calling-llm-mistral.js +2 -2
- package/backend/dist/generator/lib/debug-utils.js +2 -2
- package/backend/dist/generator/llm-queries/invoke-new-site-analysis.js +2 -1
- package/backend/dist/generator/site-generator/common-template-creator.js +15 -16
- package/backend/dist/generator/site-generator/document-card-template-creator.js +40 -0
- package/backend/dist/generator/site-generator/document-template-creator.js +69 -90
- package/backend/dist/generator/site-generator/id-key-provider.js +1 -1
- package/backend/dist/generator/site-generator/jt-site-schema-helpers.js +16 -0
- package/backend/dist/generator/site-generator/labeled-list-template-creator.js +56 -0
- package/backend/dist/generator/site-generator/theme-creator-context.js +109 -0
- package/backend/dist/generator/site-generator/theme-creator.js +3 -67
- package/backend/dist/generator/site-generator/theme-css.js +58 -1
- package/backend/dist/index.js +4 -4
- package/backend/prompts/message-guard.md +0 -1
- package/frontend/dist/frontend.mjs +61 -57
- package/package.json +10 -10
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { getPredefinedFields } from "../lib/create-prompt.js";
|
|
2
|
+
export function createThemeCreatorContext(siteSchema) {
|
|
3
|
+
const languages = siteSchema.languages ?? [];
|
|
4
|
+
const liquidFiles = new Map();
|
|
5
|
+
const localeFiles = new Map();
|
|
6
|
+
const otherFiles = new Map();
|
|
7
|
+
const issues = [];
|
|
8
|
+
const getParentTypes = makeGetParentTypes(siteSchema);
|
|
9
|
+
return {
|
|
10
|
+
siteSchema,
|
|
11
|
+
labeledDocuments: getLabeledDocuments(siteSchema, getParentTypes),
|
|
12
|
+
getParentTypes,
|
|
13
|
+
predefinedFields: new Map(getPredefinedFields().map((f) => [f.fieldName, f])),
|
|
14
|
+
setLocalizedLabel(label) {
|
|
15
|
+
for (const language of languages) {
|
|
16
|
+
const value = label[language];
|
|
17
|
+
if (!value)
|
|
18
|
+
continue;
|
|
19
|
+
let f = localeFiles.get(language);
|
|
20
|
+
if (!f) {
|
|
21
|
+
f = {};
|
|
22
|
+
localeFiles.set(language, f);
|
|
23
|
+
}
|
|
24
|
+
f[language] = value;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
hasLiquidFile(directory, filename) {
|
|
28
|
+
const path = directory === "root" ? `templates/${filename}` : `templates/${directory}/${filename}`;
|
|
29
|
+
return liquidFiles.has(path);
|
|
30
|
+
},
|
|
31
|
+
addLiquidFile(directory, filename, content, { skipIfExists = false } = {}) {
|
|
32
|
+
const path = directory === "root" ? `templates/${filename}` : `templates/${directory}/${filename}`;
|
|
33
|
+
if (liquidFiles.has(path)) {
|
|
34
|
+
if (skipIfExists)
|
|
35
|
+
return;
|
|
36
|
+
issues.push(`Liquid file already exists, overwrite: "${path}"`);
|
|
37
|
+
}
|
|
38
|
+
liquidFiles.set(path, content);
|
|
39
|
+
},
|
|
40
|
+
addFile(path, content) {
|
|
41
|
+
if (otherFiles.has(path))
|
|
42
|
+
throw new Error(`File already exists: "${path}"`);
|
|
43
|
+
otherFiles.set(path, content);
|
|
44
|
+
},
|
|
45
|
+
toFiles() {
|
|
46
|
+
const files = [
|
|
47
|
+
...Array.from(liquidFiles.entries()).map(([path, content]) => ({ path, content })),
|
|
48
|
+
...Array.from(localeFiles.entries()).map(([language, content]) => ({
|
|
49
|
+
path: `locales/${language}.json`,
|
|
50
|
+
content: JSON.stringify(content, null, 2),
|
|
51
|
+
})),
|
|
52
|
+
...Array.from(otherFiles.entries()).map(([path, content]) => ({ path, content })),
|
|
53
|
+
];
|
|
54
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
55
|
+
return { files, issues: issues.length > 0 ? issues : undefined };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function makeGetParentTypes(siteSchema) {
|
|
60
|
+
const parentsByChild = new Map();
|
|
61
|
+
const nodeTypes = siteSchema.nodeTypes ?? [];
|
|
62
|
+
for (const type of nodeTypes) {
|
|
63
|
+
if (type.kind !== "document")
|
|
64
|
+
continue;
|
|
65
|
+
if (type.documentKind === "routing") {
|
|
66
|
+
for (const childName of type.routingChildren ?? []) {
|
|
67
|
+
const list = parentsByChild.get(childName) ?? [];
|
|
68
|
+
list.push(type);
|
|
69
|
+
parentsByChild.set(childName, list);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const childName of type.regularChildren ?? []) {
|
|
73
|
+
const list = parentsByChild.get(childName) ?? [];
|
|
74
|
+
list.push(type);
|
|
75
|
+
parentsByChild.set(childName, list);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return (documentType) => parentsByChild.get(documentType.typeName) ?? [];
|
|
79
|
+
}
|
|
80
|
+
function getLabeledDocuments(siteSchema, getParentTypes) {
|
|
81
|
+
const result = [];
|
|
82
|
+
for (const documentType of siteSchema.nodeTypes ?? []) {
|
|
83
|
+
if (documentType.kind !== "document" || documentType.documentKind !== "regular")
|
|
84
|
+
continue;
|
|
85
|
+
for (const field of documentType.fields ?? []) {
|
|
86
|
+
if (typeof field === "string" || field.storedAs !== "labeling")
|
|
87
|
+
continue;
|
|
88
|
+
const taxonomyType = siteSchema.nodeTypes?.find((nt) => nt.typeName === field.taxonomy);
|
|
89
|
+
if (!taxonomyType ||
|
|
90
|
+
taxonomyType.kind !== "document" ||
|
|
91
|
+
taxonomyType.documentKind !== "routing") {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
for (const parentDocumentType of getParentTypes(documentType)) {
|
|
95
|
+
if (parentDocumentType.kind !== "document" ||
|
|
96
|
+
parentDocumentType.documentKind !== "routing") {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
result.push({
|
|
100
|
+
documentType,
|
|
101
|
+
parentDocumentType,
|
|
102
|
+
field,
|
|
103
|
+
taxonomyType,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { isObj } from "@paroicms/public-anywhere-lib";
|
|
2
2
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import { getPredefinedFields } from "../lib/create-prompt.js";
|
|
5
4
|
import { camelToKebabCase } from "../lib/utils.js";
|
|
6
5
|
import { templateOfSiteFooter, templateOfSiteHeader } from "./common-template-creator.js";
|
|
7
6
|
import { templateOfDocumentType } from "./document-template-creator.js";
|
|
8
7
|
import { isMultilingual } from "./jt-site-schema-helpers.js";
|
|
8
|
+
import { createThemeCreatorContext } from "./theme-creator-context.js";
|
|
9
9
|
import { getThemeCssContent } from "./theme-css.js";
|
|
10
10
|
export async function createTheme(ctx, siteDir, siteSchema) {
|
|
11
11
|
const themeContext = createThemeCreatorContext(siteSchema);
|
|
@@ -38,70 +38,6 @@ export async function createTheme(ctx, siteDir, siteSchema) {
|
|
|
38
38
|
ctx.logger.warn(`Issues in "${siteDir}":`, issues);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
function createThemeCreatorContext(siteSchema) {
|
|
42
|
-
const languages = siteSchema.languages ?? [];
|
|
43
|
-
const liquidFiles = new Map();
|
|
44
|
-
const localeFiles = new Map();
|
|
45
|
-
const otherFiles = new Map();
|
|
46
|
-
const issues = [];
|
|
47
|
-
return {
|
|
48
|
-
siteSchema,
|
|
49
|
-
predefinedFields: new Map(getPredefinedFields().map((f) => [f.fieldName, f])),
|
|
50
|
-
setLocalizedLabel(label) {
|
|
51
|
-
for (const language of languages) {
|
|
52
|
-
const value = label[language];
|
|
53
|
-
if (!value)
|
|
54
|
-
continue;
|
|
55
|
-
let f = localeFiles.get(language);
|
|
56
|
-
if (!f) {
|
|
57
|
-
f = {};
|
|
58
|
-
localeFiles.set(language, f);
|
|
59
|
-
}
|
|
60
|
-
f[language] = value;
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
hasLiquidFile(directory, filename) {
|
|
64
|
-
const path = directory === "root" ? `templates/${filename}` : `templates/${directory}/${filename}`;
|
|
65
|
-
return liquidFiles.has(path);
|
|
66
|
-
},
|
|
67
|
-
addLiquidFile(directory, filename, content, { skipIfExists = false } = {}) {
|
|
68
|
-
const path = directory === "root" ? `templates/${filename}` : `templates/${directory}/${filename}`;
|
|
69
|
-
if (liquidFiles.has(path)) {
|
|
70
|
-
if (skipIfExists)
|
|
71
|
-
return;
|
|
72
|
-
issues.push(`Liquid file already exists, overwrite: "${path}"`);
|
|
73
|
-
}
|
|
74
|
-
liquidFiles.set(path, content);
|
|
75
|
-
},
|
|
76
|
-
addFile(path, content) {
|
|
77
|
-
if (otherFiles.has(path))
|
|
78
|
-
throw new Error(`File already exists: "${path}"`);
|
|
79
|
-
otherFiles.set(path, content);
|
|
80
|
-
},
|
|
81
|
-
toFiles() {
|
|
82
|
-
const files = [
|
|
83
|
-
...Array.from(liquidFiles.entries()).map(([path, content]) => ({ path, content })),
|
|
84
|
-
...Array.from(localeFiles.entries()).map(([language, content]) => ({
|
|
85
|
-
path: `locales/${language}.json`,
|
|
86
|
-
content: JSON.stringify(content, null, 2),
|
|
87
|
-
})),
|
|
88
|
-
...Array.from(otherFiles.entries()).map(([path, content]) => ({ path, content })),
|
|
89
|
-
];
|
|
90
|
-
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
91
|
-
return { files, issues: issues.length > 0 ? issues : undefined };
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
// function getDefaultLiquidContent() {
|
|
96
|
-
// return `{% layout "layouts/main-layout.liquid" doc: doc site: site %}
|
|
97
|
-
// {% block %}
|
|
98
|
-
// <div class="Container">
|
|
99
|
-
// <div class="Page">
|
|
100
|
-
// {{ doc | info }}
|
|
101
|
-
// </div>
|
|
102
|
-
// </div>
|
|
103
|
-
// {% endblock %}`;
|
|
104
|
-
// }
|
|
105
41
|
function templateOf404(ctx) {
|
|
106
42
|
const { siteSchema } = ctx;
|
|
107
43
|
const rawParam = isMultilingual(siteSchema) ? " raw: true" : "";
|
|
@@ -132,13 +68,13 @@ function templateOfLayout(ctx) {
|
|
|
132
68
|
const multilingual = isMultilingual(siteSchema);
|
|
133
69
|
ctx.addLiquidFile("partials", "site-header.liquid", templateOfSiteHeader(ctx));
|
|
134
70
|
ctx.addLiquidFile("partials", "site-footer.liquid", templateOfSiteFooter(ctx));
|
|
135
|
-
const renderHeader = `{% render "partials/site-header" doc: doc
|
|
71
|
+
const renderHeader = `{% render "partials/site-header" doc: doc %}`;
|
|
136
72
|
const headerTemplate = multilingual
|
|
137
73
|
? `{% unless raw %}
|
|
138
74
|
${renderHeader}
|
|
139
75
|
{% endunless %}`
|
|
140
76
|
: renderHeader;
|
|
141
|
-
const renderFooter = `{% render "partials/site-footer" doc: doc
|
|
77
|
+
const renderFooter = `{% render "partials/site-footer" doc: doc %}`;
|
|
142
78
|
const footerTemplate = multilingual
|
|
143
79
|
? `{% unless raw %}
|
|
144
80
|
${renderFooter}
|
|
@@ -69,7 +69,7 @@ footer {
|
|
|
69
69
|
text-align: center;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
/*
|
|
72
|
+
/* Card */
|
|
73
73
|
|
|
74
74
|
a > article {
|
|
75
75
|
background-color: #fff;
|
|
@@ -270,6 +270,10 @@ nav a.active::after {
|
|
|
270
270
|
|
|
271
271
|
.Field {
|
|
272
272
|
margin: 20px 0;
|
|
273
|
+
|
|
274
|
+
a {
|
|
275
|
+
text-decoration: underline;
|
|
276
|
+
}
|
|
273
277
|
}
|
|
274
278
|
|
|
275
279
|
.Field:has(> .Field-img) {
|
|
@@ -300,5 +304,58 @@ nav a.active::after {
|
|
|
300
304
|
.Row.center {
|
|
301
305
|
align-items: center;
|
|
302
306
|
}
|
|
307
|
+
|
|
308
|
+
.LanguageSelector {
|
|
309
|
+
list-style: none;
|
|
310
|
+
margin: 0;
|
|
311
|
+
padding: 0;
|
|
312
|
+
|
|
313
|
+
li {
|
|
314
|
+
display: inline-block;
|
|
315
|
+
margin: 0 5px;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
li:not(:last-child)::after {
|
|
319
|
+
content: " - ";
|
|
320
|
+
margin-left: 5px;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
a {
|
|
324
|
+
text-decoration: underline;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
span {
|
|
328
|
+
font-weight: bold;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.FlexWrap {
|
|
333
|
+
display: flex;
|
|
334
|
+
flex-wrap: wrap;
|
|
335
|
+
gap: 5px;
|
|
336
|
+
list-style: none;
|
|
337
|
+
margin: 0;
|
|
338
|
+
padding: 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.Label {
|
|
342
|
+
background-color: #e9ecef;
|
|
343
|
+
border: 1px solid #dee2e6;
|
|
344
|
+
border-radius: 12px;
|
|
345
|
+
color: #495057;
|
|
346
|
+
display: inline-block;
|
|
347
|
+
font-size: 12px;
|
|
348
|
+
font-weight: 500;
|
|
349
|
+
margin: 0;
|
|
350
|
+
padding: 4px 8px;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
a.Label {
|
|
354
|
+
background-color: #bedefeff;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
a.Label:hover {
|
|
358
|
+
background-color: #8bc0f5ff;
|
|
359
|
+
}
|
|
303
360
|
`;
|
|
304
361
|
}
|
package/backend/dist/index.js
CHANGED
|
@@ -43,12 +43,12 @@ const plugin = {
|
|
|
43
43
|
startSiteRemover(rawContext);
|
|
44
44
|
});
|
|
45
45
|
service.setPublicAssetsDirectory(join(packageDir, "frontend", "dist"));
|
|
46
|
-
service.
|
|
47
|
-
service.setRenderState("
|
|
46
|
+
service.registerOutLiquidTagFunction("siteGeneratorApp", (service) => {
|
|
47
|
+
service.setRenderState("siteGeneratorApp", true);
|
|
48
48
|
return `<div id="site-generator-app"></div>`;
|
|
49
|
-
});
|
|
49
|
+
}, { raw: true });
|
|
50
50
|
service.registerHeadTags(({ state }) => {
|
|
51
|
-
if (!state.get("
|
|
51
|
+
if (!state.get("siteGeneratorApp"))
|
|
52
52
|
return;
|
|
53
53
|
return [
|
|
54
54
|
makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/frontend.css`),
|