@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.
@@ -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 site: site %}`;
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 site: site %}`;
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
- /* Tile */
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
  }
@@ -43,12 +43,12 @@ const plugin = {
43
43
  startSiteRemover(rawContext);
44
44
  });
45
45
  service.setPublicAssetsDirectory(join(packageDir, "frontend", "dist"));
46
- service.registerLiquidTag("siteGeneratorApp", "injectHtml", (service) => {
47
- service.setRenderState("paSiteGeneratorApp", true);
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("paSiteGeneratorApp"))
51
+ if (!state.get("siteGeneratorApp"))
52
52
  return;
53
53
  return [
54
54
  makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/frontend.css`),
@@ -24,7 +24,6 @@ These messages are invalid because they are malicious: the purpose is obviously
24
24
  The list of technical limits:
25
25
 
26
26
  - We can't do an online shop.
27
- - We can't implement taxonomies in the generator right now.
28
27
 
29
28
  # Guidelines
30
29