@paroicms/site-generator-plugin 0.1.1 → 0.2.1

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.
@@ -75,14 +75,6 @@ async function updateSiteFields(ctx, options) {
75
75
  value: siteTitle,
76
76
  },
77
77
  ],
78
- [
79
- "contactEmail",
80
- {
81
- dataType: "string",
82
- localized: false,
83
- value: `${siteId}@yopmail.com`,
84
- },
85
- ],
86
78
  [
87
79
  "favicon",
88
80
  {
@@ -142,7 +134,7 @@ async function updateRoutingDocument(ctx, siteOptions, nodeOptions) {
142
134
  });
143
135
  await ctx.service.connector.updateDocumentContent(fqdn, {
144
136
  nodeId: routingIds.nodeId,
145
- content: toNcDocumentContent(content, nodeType),
137
+ content: toRiDocumentContent(content, nodeType),
146
138
  });
147
139
  }
148
140
  async function addRegularDocuments(ctx, siteOptions, nodeOptions) {
@@ -166,7 +158,7 @@ async function addRegularDocuments(ctx, siteOptions, nodeOptions) {
166
158
  }
167
159
  await ctx.service.connector.addMultipleDocumentContents(fqdn, {
168
160
  parentNodeId,
169
- contents: list.map((content) => toNcDocumentContent(content, nodeType)),
161
+ contents: list.map((content) => toRiDocumentContent(content, nodeType)),
170
162
  });
171
163
  }
172
164
  async function addParts(ctx, siteOptions, nodeOptions) {
@@ -190,10 +182,10 @@ async function addParts(ctx, siteOptions, nodeOptions) {
190
182
  }
191
183
  await ctx.service.connector.addMultiplePartContents(fqdn, {
192
184
  parentNodeId,
193
- contents: list.map((content) => toNcPartContent(content, nodeType)),
185
+ contents: list.map((content) => toRiPartContent(content, nodeType)),
194
186
  });
195
187
  }
196
- function toNcDocumentContent(content, nodeType) {
188
+ function toRiDocumentContent(content, nodeType) {
197
189
  const { title, fields, featuredImage } = content;
198
190
  return {
199
191
  kind: "document",
@@ -203,7 +195,7 @@ function toNcDocumentContent(content, nodeType) {
203
195
  fields,
204
196
  };
205
197
  }
206
- function toNcPartContent(content, nodeType) {
198
+ function toRiPartContent(content, nodeType) {
207
199
  const { fields } = content;
208
200
  return {
209
201
  kind: "part",
@@ -22,7 +22,7 @@ function createNodeContent(options) {
22
22
  const fieldTypes = nodeType.fields ?? [];
23
23
  if (nodeType.kind === "document") {
24
24
  const { title, ...generatedFields } = generatedContent;
25
- const fields = toNcFieldSetContent(generatedFields, outputTags, fieldTypes, language);
25
+ const fields = toRiFieldSetContent(generatedFields, outputTags, fieldTypes, language);
26
26
  const featuredImage = nodeType.withFeaturedImage
27
27
  ? {
28
28
  file: getRandomImagePath(),
@@ -34,16 +34,16 @@ function createNodeContent(options) {
34
34
  fields,
35
35
  };
36
36
  }
37
- const fields = toNcFieldSetContent(generatedContent, outputTags, fieldTypes, language);
37
+ const fields = toRiFieldSetContent(generatedContent, outputTags, fieldTypes, language);
38
38
  return { fields };
39
39
  }
40
- function toNcFieldSetContent(content, outputTags, fieldTypes, language) {
40
+ function toRiFieldSetContent(content, outputTags, fieldTypes, language) {
41
41
  const result = {};
42
42
  for (const fieldType of fieldTypes) {
43
43
  const isMarkdown = outputTags.find((tag) => tag.key === fieldType.name)?.format === "markdown";
44
44
  const localized = fieldType.localized;
45
45
  const value = content[fieldType.name];
46
- const fieldContent = toNcFieldContent({
46
+ const fieldContent = toRiFieldContent({
47
47
  fieldType,
48
48
  generatedValue: value,
49
49
  localized,
@@ -56,7 +56,7 @@ function toNcFieldSetContent(content, outputTags, fieldTypes, language) {
56
56
  }
57
57
  return result;
58
58
  }
59
- function toNcFieldContent(options) {
59
+ function toRiFieldContent(options) {
60
60
  const { fieldType, generatedValue, localized, language, isMarkdown } = options;
61
61
  if (generatedValue !== undefined && localized) {
62
62
  if (fieldType.dataType === "string") {
@@ -67,7 +67,7 @@ function toNcFieldContent(options) {
67
67
  };
68
68
  }
69
69
  if (fieldType.dataType === "quillDelta" && isMarkdown) {
70
- return toNcQuillDeltaContent(generatedValue);
70
+ return toRiQuillDeltaContent(generatedValue);
71
71
  }
72
72
  }
73
73
  if (fieldType.storedAs === "mediaHandle") {
@@ -124,7 +124,7 @@ function toNcFieldContent(options) {
124
124
  }
125
125
  }
126
126
  }
127
- function toNcQuillDeltaContent(content) {
127
+ function toRiQuillDeltaContent(content) {
128
128
  return {
129
129
  dataType: "quillDelta",
130
130
  localized: true,
@@ -21,6 +21,14 @@ export function templateOfSiteHeader(ctx) {
21
21
  <header class="Container Header">
22
22
  ${indent(content.filter(Boolean).join("\n"), 2, { skipFirst: true })}
23
23
  </header>
24
+ </div>
25
+ <div
26
+ class="_mobileMenu"
27
+ data-effect="paMobileMenu"
28
+ style="display: none"
29
+ >
30
+ <div data-inject="logo"></div>
31
+ <div data-inject="content"></div>
24
32
  </div>`;
25
33
  }
26
34
  function templateOfSiteLogoTitle(ctx) {
@@ -29,7 +37,7 @@ function templateOfSiteLogoTitle(ctx) {
29
37
  const content = [
30
38
  siteType.fields?.includes("logo")
31
39
  ? `{% if site.field.logo %}
32
- {% useImage logo uid: site.field.logo.uid size: "x50" %}
40
+ {% useImage logo uid: site.field.logo.uid size: "50x50" %}
33
41
  <img
34
42
  src="{{ logo.url }}"
35
43
  width="{{ logo.width }}"
@@ -43,7 +51,7 @@ function templateOfSiteLogoTitle(ctx) {
43
51
  return `<a
44
52
  class="Header-logo"
45
53
  href="{{ site.home.url }}"
46
- data-menu-item-id="{{ site.home.id }}">
54
+ data-mobile-menu-part="logo">
47
55
  ${indent(content.filter(Boolean).join("\n"), 1, { skipFirst: true })}
48
56
  </a>`;
49
57
  }
@@ -60,7 +68,10 @@ function templateOfMainMenu(ctx) {
60
68
  {{ ${typeName}.title }}
61
69
  </a>`);
62
70
  return `${variableTemplates.join("\n")}
63
- <nav data-activate-menu-items="{{ doc.id | activateMenuItemsData }}">
71
+ <nav
72
+ data-activate-menu-items="{{ doc.id | activateMenuItemsData }}"
73
+ data-mobile-menu-part="content"
74
+ data-mobile-menu-action="move">
64
75
  ${indent(itemTemplates.join("\n"), 1, { skipFirst: true })}
65
76
  </nav>`;
66
77
  }
@@ -70,11 +81,14 @@ function templateOfSearchOpener(ctx) {
70
81
  const typeName = homeType.routingChildren?.find((typeName) => typeName === "search" || typeName === "searchPage");
71
82
  if (!typeName)
72
83
  return;
73
- return `{% getDoc ${typeName} id: site.home.${typeName}.id %}
74
- <span
75
- data-effect="searchOpener"
76
- data-search-url="{{ ${typeName}.url }}"
77
- data-icon-color="#fff"></span>`;
84
+ return `<div class="Row center">
85
+ {% getDoc ${typeName} id: site.home.${typeName}.id %}
86
+ <span
87
+ data-effect="paSearchOpener"
88
+ data-search-url="{{ ${typeName}.url }}"
89
+ data-icon-color="#fff"></span>
90
+ <div data-mobile-menu="button"></div>
91
+ </div>`;
78
92
  }
79
93
  export function templateOfSiteFooter(ctx) {
80
94
  const content = [templateOfSiteFooterMention(ctx), templateOfLanguageSelector(ctx)];
@@ -26,7 +26,7 @@ export function templateOfDocumentType(ctx, documentType) {
26
26
  ].filter(Boolean);
27
27
  return `{% layout "layouts/main-layout.liquid" doc: doc site: site %}
28
28
  {% block %}
29
- ${blocks.map((block) => indent(block, 1)).join("\n\n")}
29
+ ${blocks.join("\n\n")}
30
30
  {% endblock %}`;
31
31
  }
32
32
  function templateOfTitleAndFields(ctx, documentType) {
@@ -54,7 +54,7 @@ function templateOfSpecialDocument(ctx, documentType) {
54
54
  addLiquidFile("partials", "result-item.public.liquid", templateOfDocumentTile("doc"));
55
55
  return `<div
56
56
  class="Container"
57
- data-effect="searchForm"
57
+ data-effect="paSearchApp"
58
58
  data-template="result-item"
59
59
  data-limit="10"></div>`;
60
60
  }
@@ -62,7 +62,7 @@ function templateOfSpecialDocument(ctx, documentType) {
62
62
  return `<div class="Container">
63
63
  <div class="TextWidth Pt">
64
64
  <div
65
- data-effect="contactForm"
65
+ data-effect="paContactForm"
66
66
  data-recaptcha-key="{{ site.recaptchaKey }}"
67
67
  data-home-url="{{ site.home.url }}"></div>
68
68
  </div>
@@ -145,7 +145,7 @@ function templateOfRegularDocumentTiles(ctx, parentType, parentIdKeyProvider, {
145
145
  <div class="Container">
146
146
  <div
147
147
  class="Page List"
148
- data-effect="infiniteLoading"
148
+ data-effect="paInfiniteLoading"
149
149
  data-parent-id="{{ ${idKey} }}"
150
150
  data-start="{{ ${childrenVariableName}.pageSize }}"
151
151
  data-limit="{{ ${childrenVariableName}.pageSize }}"
@@ -33,11 +33,19 @@ export async function generateSite(ctx, input) {
33
33
  if (withFakeContent) {
34
34
  await fillSiteWithFakeContent(ctx, { siteConf, siteId, siteTitle });
35
35
  }
36
+ const account = {
37
+ kind: "local",
38
+ email: `${siteId}@yopmail.com`,
39
+ name: "Admin",
40
+ password: Math.random().toString(36).substring(2, 6), // 4 random lowercase characters,
41
+ };
42
+ await ctx.service.connector.createAccount(siteConf.fqdn, account, { asContactEmail: true });
36
43
  const { siteUrl } = siteConf;
37
44
  return {
38
45
  siteId,
39
46
  url: siteUrl,
40
47
  boUrl: `${siteUrl}/adm`,
48
+ account,
41
49
  };
42
50
  }
43
51
  function getPackageJsonContent(options) {
@@ -58,11 +66,11 @@ function getPackageJsonContent(options) {
58
66
  "_pino-pretty": "pino-pretty -U false -x 'stats:25' -X 'stats:grey' -t 'yyyy-mm-dd HH:MM:ss.l' -i 'hostname,pid,fqdn'",
59
67
  },
60
68
  dependencies: {
61
- "@paroicms/contact-form-plugin": "0.18.0",
62
- "@paroicms/content-loading-plugin": "0.11.0",
63
- "@paroicms/public-menu-plugin": "0.8.0",
69
+ "@paroicms/contact-form-plugin": "*",
70
+ "@paroicms/content-loading-plugin": "*",
71
+ "@paroicms/public-menu-plugin": "*",
72
+ "@paroicms/quill-editor-plugin": "*",
64
73
  "@paroicms/server": "*",
65
- "@paroicms/quill-editor-plugin": "1.27.0",
66
74
  },
67
75
  devDependencies: {
68
76
  concurrently: "~9.1.2",
@@ -16,6 +16,7 @@ export async function createTheme(ctx, siteDir, siteSchema) {
16
16
  themeContext.addLiquidFile("root", `${camelToKebabCase(nodeType.typeName)}.liquid`, templateOfDocumentType(themeContext, nodeType));
17
17
  }
18
18
  themeContext.addFile("theme.json", getThemeJsonContent());
19
+ themeContext.addFile(".theme-check.yml", getLiquidLinterCheckContent());
19
20
  themeContext.addFile("assets/scss/theme.scss", getThemeCssContent());
20
21
  themeContext.addFile("assets/css/theme.css", getThemeCssContent());
21
22
  themeContext.addLiquidFile("layouts", "main-layout.liquid", templateOfLayout(themeContext));
@@ -169,6 +170,18 @@ function getThemeJsonContent() {
169
170
  pixelRatio: 1.5,
170
171
  }, null, 2);
171
172
  }
173
+ function getLiquidLinterCheckContent() {
174
+ return `UndefinedObject:
175
+ enabled: false
176
+ TranslationKeyExists:
177
+ enabled: false
178
+ MissingTemplate:
179
+ enabled: false
180
+ RemoteAsset:
181
+ enabled: false
182
+ UnknownFilter:
183
+ enabled: false`;
184
+ }
172
185
  async function ensureDirectory(dirPath, { recursive = false } = {}) {
173
186
  try {
174
187
  await mkdir(dirPath, { recursive });
@@ -1,5 +1,10 @@
1
1
  export function getThemeCssContent() {
2
- return `/* Reset */
2
+ return `/* Global */
3
+ :root {
4
+ --paInteractiveColor: #99f;
5
+ }
6
+
7
+ /* Reset */
3
8
  * {
4
9
  box-sizing: border-box;
5
10
  }
@@ -43,6 +48,21 @@ header {
43
48
  }
44
49
  }
45
50
 
51
+ .Header-logo {
52
+ display: flex;
53
+ align-items: center;
54
+ }
55
+
56
+ .Header-logo img {
57
+ margin-right: 10px;
58
+ border-radius: 50%;
59
+ }
60
+
61
+ .Header-title {
62
+ font-size: 20px;
63
+ font-weight: bold;
64
+ }
65
+
46
66
  footer {
47
67
  margin-top: 30px;
48
68
  padding: 20px;
@@ -100,18 +120,8 @@ nav {
100
120
  margin: 0 15px;
101
121
  }
102
122
 
103
- @media (max-width: 768px) {
104
- nav {
105
- flex-basis: 100%;
106
- order: 3;
107
- margin: 10px 0 5px;
108
- justify-content: flex-start;
109
- overflow-x: auto;
110
- padding-bottom: 5px;
111
- }
112
- }
113
-
114
- nav a {
123
+ nav a,
124
+ nav a:visited {
115
125
  color: rgba(255, 255, 255, 0.85);
116
126
  padding: 8px;
117
127
  margin: 0 4px;
@@ -142,6 +152,24 @@ nav a.active::after {
142
152
  border-radius: 1.5px;
143
153
  }
144
154
 
155
+ ._mobileMenu nav {
156
+ display: block;
157
+ margin-top: 40px;
158
+ }
159
+
160
+ ._mobileMenu nav a,
161
+ ._mobileMenu nav a:visited,
162
+ ._mobileMenu nav a:active,
163
+ ._mobileMenu nav a:hover {
164
+ color: #333;
165
+ }
166
+
167
+ ._mobileMenu nav a {
168
+ display: block;
169
+ margin: 0;
170
+ padding: 10px;
171
+ }
172
+
145
173
  /* Classes */
146
174
 
147
175
  ._bg2 {
@@ -182,21 +210,6 @@ nav a.active::after {
182
210
  padding-bottom: 50px;
183
211
  }
184
212
 
185
- .HeaderLogo {
186
- display: flex;
187
- align-items: center;
188
- }
189
-
190
- .HeaderLogo img {
191
- margin-right: 10px;
192
- border-radius: 50%;
193
- }
194
-
195
- .HeaderTitle {
196
- font-size: 20px;
197
- font-weight: bold;
198
- }
199
-
200
213
  .Text::after {
201
214
  clear: both;
202
215
  content: "";
@@ -240,17 +253,15 @@ nav a.active::after {
240
253
  width: 100%;
241
254
  }
242
255
 
243
- .InfiniteLoading-actionArea {
256
+ .PaInfiniteLoading-loadMore {
244
257
  align-items: center;
245
258
  display: flex;
246
259
  justify-content: center;
247
260
  }
248
261
 
249
- button,
250
262
  .Button,
251
- .SearchOpenerBtn,
252
- .InfiniteLoading-btn,
253
- .ContactForm-btn {
263
+ .PaButton,
264
+ .PaIconButton {
254
265
  background-color: #3498db;
255
266
  border: 1px solid #3498db;
256
267
  border-radius: 5px;
@@ -263,24 +274,20 @@ button,
263
274
  text-align: center;
264
275
  text-decoration: none;
265
276
  }
266
- button:hover,
277
+
267
278
  .Button:hover,
268
- .SearchOpenerBtn:hover,
269
- .InfiniteLoading-btn:hover,
270
- .ContactForm-btn:hover {
279
+ .PaButton:hover {
271
280
  background-color: #2980b9;
272
281
  border-color: #2980b9;
273
282
  }
274
- button:disabled,
283
+
275
284
  .Button:disabled,
276
- .SearchOpenerBtn:disabled,
277
- .InfiniteLoading-btn:disabled,
278
- .ContactForm-btn:disabled {
285
+ .PaButton:disabled {
279
286
  background-color: #ccc;
280
287
  border-color: #ccc;
281
288
  }
282
289
 
283
- .SearchOpenerBtn {
290
+ .PaSearchOpenerButton {
284
291
  display: flex;
285
292
  }
286
293
 
@@ -313,11 +320,7 @@ button:disabled,
313
320
  justify-content: space-between;
314
321
  }
315
322
 
316
- .SearchPageResponse,
317
- .SearchPageResponse div {
318
- display: flex;
319
- flex-direction: column;
323
+ .Row.center {
320
324
  align-items: center;
321
- gap: 20px;
322
325
  }`;
323
326
  }