@silexlabs/silex 3.5.0 → 3.5.1-2

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.
Files changed (95) hide show
  1. package/.silex.js +0 -3
  2. package/dist/client/client/config.d.ts +8 -0
  3. package/dist/client/client/grapesjs/PublicationManager.d.ts +43 -0
  4. package/dist/client/client/grapesjs/cms/DataSource.d.ts +43 -0
  5. package/dist/client/client/grapesjs/cms/blocks.d.ts +2 -0
  6. package/dist/client/client/grapesjs/cms/buttons.d.ts +2 -0
  7. package/dist/client/client/grapesjs/cms/collection-pages.d.ts +4 -0
  8. package/dist/client/client/grapesjs/cms/config.d.ts +9 -0
  9. package/dist/client/client/grapesjs/cms/filters.d.ts +3 -0
  10. package/dist/client/client/grapesjs/cms/index.d.ts +44 -0
  11. package/dist/client/client/grapesjs/cms/liquid.d.ts +59 -0
  12. package/dist/client/client/grapesjs/cms/page-settings.d.ts +6 -0
  13. package/dist/client/client/grapesjs/cms/publication.d.ts +60 -0
  14. package/dist/client/client/grapesjs/cms/site-settings.d.ts +3 -0
  15. package/dist/client/client/grapesjs/cms/states.d.ts +8 -0
  16. package/dist/client/client/grapesjs/cms/traits.d.ts +8 -0
  17. package/dist/client/client/grapesjs/settings.d.ts +12 -3
  18. package/dist/client/client/grapesjs/view-buttons.d.ts +2 -1
  19. package/dist/client/client/utils.d.ts +1 -0
  20. package/dist/client/constants.d.ts +2 -1
  21. package/dist/client/css/admin.css +117 -19
  22. package/dist/client/index.html +2 -2
  23. package/dist/client/js/main.js +1974 -267
  24. package/dist/client/types.d.ts +3 -1
  25. package/dist/plugins/client/plugins/client/template.js +1 -1
  26. package/dist/plugins/client/plugins/client/template.js.map +1 -1
  27. package/dist/plugins/client/types.d.ts +3 -1
  28. package/dist/plugins/client/types.js +11 -8
  29. package/dist/plugins/client/types.js.map +1 -1
  30. package/dist/plugins/server/constants.d.ts +2 -1
  31. package/dist/plugins/server/constants.js +3 -2
  32. package/dist/plugins/server/constants.js.map +1 -1
  33. package/dist/plugins/server/plugins/server/FtpConnector.js +15 -20
  34. package/dist/plugins/server/plugins/server/FtpConnector.js.map +1 -1
  35. package/dist/plugins/server/plugins/server/GitlabConnector.js +34 -7
  36. package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
  37. package/dist/plugins/server/server/connectors/FsStorage.js +16 -20
  38. package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
  39. package/dist/plugins/server/server/utils/websiteDataSerialization.d.ts +4 -0
  40. package/dist/plugins/server/server/utils/websiteDataSerialization.js +21 -12
  41. package/dist/plugins/server/server/utils/websiteDataSerialization.js.map +1 -1
  42. package/dist/plugins/server/types.d.ts +3 -1
  43. package/dist/plugins/server/types.js +12 -9
  44. package/dist/plugins/server/types.js.map +1 -1
  45. package/dist/server/constants.js +3 -2
  46. package/dist/server/server/connectors/FsStorage.js +14 -18
  47. package/dist/server/server/utils/websiteDataSerialization.js +16 -11
  48. package/dist/server/types.js +6 -2
  49. package/package.json +16 -11
  50. package/src/css/_variables.scss +2 -1
  51. package/src/css/grapesjs-plugins.scss +31 -0
  52. package/src/css/grapesjs.scss +20 -0
  53. package/src/css/page-panel.scss +25 -6
  54. package/src/css/silex.scss +64 -5
  55. package/src/ts/client/config.ts +23 -0
  56. package/src/ts/client/grapesjs/PublicationManager.ts +159 -1
  57. package/src/ts/client/grapesjs/breadcrumbs.ts +3 -2
  58. package/src/ts/client/grapesjs/cms/DataSource.ts +333 -0
  59. package/src/ts/client/grapesjs/cms/blocks.ts +124 -0
  60. package/src/ts/client/grapesjs/cms/buttons.ts +163 -0
  61. package/src/ts/client/grapesjs/cms/collection-pages.ts +214 -0
  62. package/src/ts/client/grapesjs/cms/config.ts +47 -0
  63. package/src/ts/client/grapesjs/cms/filters.ts +53 -0
  64. package/src/ts/client/grapesjs/cms/index.ts +130 -0
  65. package/src/ts/client/grapesjs/cms/liquid.mock.ts +181 -0
  66. package/src/ts/client/grapesjs/cms/liquid.test.ts +239 -0
  67. package/src/ts/client/grapesjs/cms/liquid.ts +325 -0
  68. package/src/ts/client/grapesjs/cms/page-settings.ts +285 -0
  69. package/src/ts/client/grapesjs/cms/publication.test.ts +300 -0
  70. package/src/ts/client/grapesjs/cms/publication.ts +708 -0
  71. package/src/ts/client/grapesjs/cms/site-settings.ts +79 -0
  72. package/src/ts/client/grapesjs/cms/states.ts +125 -0
  73. package/src/ts/client/grapesjs/cms/traits.ts +95 -0
  74. package/src/ts/client/grapesjs/css-props.ts +15 -16
  75. package/src/ts/client/grapesjs/flex.ts +59 -39
  76. package/src/ts/client/grapesjs/img.ts +1 -1
  77. package/src/ts/client/grapesjs/index.ts +77 -4
  78. package/src/ts/client/grapesjs/internal-links.ts +4 -2
  79. package/src/ts/client/grapesjs/page-panel.ts +126 -11
  80. package/src/ts/client/grapesjs/sectors.ts +18 -10
  81. package/src/ts/client/grapesjs/semantic.ts +4 -0
  82. package/src/ts/client/grapesjs/settings.ts +252 -101
  83. package/src/ts/client/grapesjs/storage.ts +12 -3
  84. package/src/ts/client/grapesjs/view-buttons.ts +39 -3
  85. package/src/ts/client/utils.ts +15 -2
  86. package/src/ts/constants.ts +2 -1
  87. package/src/ts/plugins/client/template.ts +1 -1
  88. package/src/ts/plugins/server/FtpConnector.test.ts +1 -0
  89. package/src/ts/plugins/server/FtpConnector.ts +20 -23
  90. package/src/ts/plugins/server/GitlabConnector.ts +40 -10
  91. package/src/ts/server/connectors/FsStorage.test.ts +3 -2
  92. package/src/ts/server/connectors/FsStorage.ts +21 -23
  93. package/src/ts/server/utils/websiteDataSerialization.test.ts +45 -13
  94. package/src/ts/server/utils/websiteDataSerialization.ts +23 -14
  95. package/src/ts/types.ts +6 -2
@@ -60,11 +60,70 @@
60
60
  }
61
61
 
62
62
  // full screen settings
63
- .settings-dialog > div {
64
- max-width: none;
65
- width: 100%;
63
+ .settings-dialog {
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ width: 100vw;
66
68
  height: 100vh;
69
+ z-index: $z-dialog-inline;
70
+ pointer-events: auto;
67
71
  overflow: auto;
72
+ display: flex;
73
+ flex-direction: column;
74
+
75
+ .settings-content {
76
+ flex: 1;
77
+ display: flex;
78
+ flex-direction: column;
79
+ background-color: var(--primaryColor);
80
+ overflow: hidden;
81
+ }
82
+ .settings-header {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: space-between;
86
+ padding: 16px 20px;
87
+ border-bottom: 1px solid var(--gjs-border-color, #ddd);
88
+ }
89
+ .settings-header h3 {
90
+ margin: 0;
91
+ font-size: 18px;
92
+ }
93
+ .settings-close {
94
+ color: inherit;
95
+ background: none;
96
+ border: none;
97
+ font-size: 24px;
98
+ cursor: pointer;
99
+ padding: 0;
100
+ width: 30px;
101
+ height: 30px;
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ }
106
+ .settings-body {
107
+ flex: 1;
108
+ overflow: auto;
109
+ padding: 0;
110
+ }
111
+ .settings-body .silex-form {
112
+ height: 100%;
113
+ display: flex;
114
+ flex-direction: column;
115
+ }
116
+ .settings-body .silex-sidebar-dialog {
117
+ flex: 1;
118
+ }
119
+ footer {
120
+ position: fixed;
121
+ z-index: 10;
122
+ bottom: 0;
123
+ left: 0;
124
+ width: 100%;
125
+ padding: 20px 0;
126
+ }
68
127
  form.silex-form {
69
128
  padding-bottom: 100px; // leave space for fixed footer
70
129
  textarea {
@@ -91,7 +150,7 @@
91
150
  .silex-version {
92
151
  float: left;
93
152
  padding: 0 15px;
94
- font-size: x-small;
153
+ font-size: small;
95
154
  }
96
155
  }
97
156
  .CodeMirror {
@@ -164,7 +223,7 @@ input.silex-button[type="submit"] {
164
223
  margin: 5px;
165
224
  }
166
225
  main {
167
- width: 100%;
226
+ width: 93%;
168
227
  }
169
228
  }
170
229
 
@@ -29,6 +29,7 @@ import { addSection, removeSection } from './grapesjs/settings'
29
29
  // Plugins
30
30
  import publishCustomCodeBlock from './publish-custom-code-block'
31
31
  import publishFonts from './publish-fonts'
32
+ import { EleventyPluginOptions } from './grapesjs/cms'
32
33
 
33
34
  /**
34
35
  * @fileoverview Silex client side config
@@ -118,6 +119,27 @@ export class ClientConfig extends Config {
118
119
  fontsServerUrl = 'https://fonts.googleapis.com'
119
120
  fontsApiUrl = 'https://www.googleapis.com'
120
121
 
122
+ /**
123
+ * CMS configuration options
124
+ * @default Default CMS configuration with enabled: true
125
+ */
126
+ cmsConfig: Partial<EleventyPluginOptions> & { enabled?: boolean } = {
127
+ enabled: true,
128
+ enable11ty: true,
129
+ cacheBuster: false,
130
+ dataSources: [],
131
+ dir: {
132
+ input: '',
133
+ html: '',
134
+ assets: 'assets',
135
+ css: 'css',
136
+ },
137
+ urls: {
138
+ css: '/css',
139
+ assets: '/assets',
140
+ },
141
+ }
142
+
121
143
  /**
122
144
  * Init GrapesJS config which depend on the config file properties
123
145
  */
@@ -179,6 +201,7 @@ export class ClientConfig extends Config {
179
201
  * Add a section to the settings dialog
180
202
  */
181
203
  addSettings(section: SettingsSection, siteOrPage: 'site' | 'page', position: 'first' | 'last' | number = 'last') {
204
+ console.warn('addSettings API is deprecated, use the command instead:')
182
205
  addSection(section, siteOrPage, position)
183
206
  }
184
207
 
@@ -20,7 +20,7 @@ import { ApiConnectorLoggedInPostMessage, ApiConnectorLoginQuery, ApiPublication
20
20
  import { Editor } from 'grapesjs'
21
21
  import { PublicationUi } from './PublicationUi'
22
22
  import { getUser, logout, publicationStatus, publish } from '../api'
23
- import { API_CONNECTOR_LOGIN, API_CONNECTOR_PATH, API_PATH } from '../../constants'
23
+ import { API_CONNECTOR_LOGIN, API_CONNECTOR_PATH, API_PATH, SILEX_VERSION } from '../../constants'
24
24
  import { ClientEvent } from '../events'
25
25
  import { resetRenderComponents, resetRenderCssRules, transformPermalink, transformFiles, transformPath, renderComponents, renderCssRules } from '../publication-transformers'
26
26
  import { hashString } from '../utils'
@@ -288,6 +288,8 @@ export class PublicationManager {
288
288
  // Get the data to publish, clone the objects because plugins can change it
289
289
  const projectData = { ...this.editor.getProjectData() as WebsiteData }
290
290
  const siteSettings = { ...this.editor.getModel().get('settings') as WebsiteSettings }
291
+ // Check for missing SEO tags and warn user
292
+ this.checkSeoTags(siteSettings)
291
293
  let preventDefaultStart = false
292
294
  this.editor.trigger(ClientEvent.PUBLISH_START, {projectData, siteSettings, preventDefault: () => preventDefaultStart = true, publicationManager: this })
293
295
  if(preventDefaultStart) {
@@ -354,6 +356,158 @@ export class PublicationManager {
354
356
  return files
355
357
  }
356
358
 
359
+ /**
360
+ * Helper function to check if a viewport meta tag exists in the head content
361
+ * @param headContent - HTML content from head settings
362
+ * @returns true if viewport meta tag is found
363
+ */
364
+ private hasViewportMeta(headContent: string): boolean {
365
+ if (!headContent) return false
366
+ // Check for viewport meta tag with various formats
367
+ const viewportPattern = /<meta[^>]*name\s*=\s*["']viewport["'][^>]*>/i
368
+ return viewportPattern.test(headContent)
369
+ }
370
+
371
+ /**
372
+ * Get the default viewport meta tag if no viewport is present
373
+ * @param siteHead - Head content from site settings
374
+ * @param pageHead - Head content from page settings
375
+ * @returns viewport meta tag or empty string if already present
376
+ */
377
+ private ensureViewportMeta(siteHead: string, pageHead: string): string {
378
+ if (this.hasViewportMeta(siteHead) || this.hasViewportMeta(pageHead)) {
379
+ return ''
380
+ }
381
+ return '<meta name="viewport" content="width=device-width, initial-scale=1.0">'
382
+ }
383
+
384
+ /**
385
+ * Helper function to check if a generator meta tag exists in the head content
386
+ * @param headContent - HTML content from head settings
387
+ * @returns true if generator meta tag is found
388
+ */
389
+ private hasGeneratorMeta(headContent: string): boolean {
390
+ if (!headContent) return false
391
+ // Check for generator meta tag with various formats
392
+ const generatorPattern = /<meta[^>]*name\s*=\s*["']generator["'][^>]*>/i
393
+ return generatorPattern.test(headContent)
394
+ }
395
+
396
+ /**
397
+ * Get the default generator meta tag if no generator is present
398
+ * @param siteHead - Head content from site settings
399
+ * @param pageHead - Head content from page settings
400
+ * @returns generator meta tag or empty string if already present
401
+ */
402
+ private ensureGeneratorMeta(siteHead: string, pageHead: string): string {
403
+ if (this.hasGeneratorMeta(siteHead) || this.hasGeneratorMeta(pageHead)) {
404
+ return ''
405
+ }
406
+ return `<meta name="generator" content="Silex v${ SILEX_VERSION }">`
407
+ }
408
+
409
+ /**
410
+ * Helper function to check if a canonical link exists in the head content
411
+ * @param headContent - HTML content from head settings
412
+ * @returns true if canonical link is found
413
+ */
414
+ private hasCanonicalLink(headContent: string): boolean {
415
+ if (!headContent) return false
416
+ const canonicalPattern = /<link[^>]*rel\s*=\s*["']canonical["'][^>]*>/i
417
+ return canonicalPattern.test(headContent)
418
+ }
419
+
420
+ /**
421
+ * Helper function to check if alternate links exist in the head content
422
+ * @param headContent - HTML content from head settings
423
+ * @returns true if alternate links are found
424
+ */
425
+ private hasAlternateLinks(headContent: string): boolean {
426
+ if (!headContent) return false
427
+ const alternatePattern = /<link[^>]*rel\s*=\s*["']alternate["'][^>]*>/i
428
+ return alternatePattern.test(headContent)
429
+ }
430
+
431
+ /**
432
+ * Check for missing SEO tags and emit warnings
433
+ * @param siteSettings - Site settings
434
+ */
435
+ private checkSeoTags(siteSettings: WebsiteSettings): void {
436
+ const pages = this.editor.Pages.getAll()
437
+
438
+ // Utility function to get a setting from the page or the site settings
439
+ const getSetting = (pageSettings: WebsiteSettings, name: string) =>
440
+ (pageSettings || {})[name] || (siteSettings || {})[name] || ''
441
+
442
+ for (const page of pages) {
443
+ const pageSettings = page.get('settings') as WebsiteSettings || {}
444
+ const siteHead = siteSettings?.head || ''
445
+ const pageHead = pageSettings?.head || ''
446
+ const pageName = page.get('name') || 'Unnamed page'
447
+ const bodyComponent = page.getMainComponent()
448
+ const componentId = bodyComponent?.getId()
449
+ const pageId = page.getId()
450
+
451
+ // Check for lang attribute
452
+ const lang = getSetting(pageSettings, 'lang')
453
+ if (!lang || lang.trim() === '') {
454
+ this.editor.runCommand('notifications:add', {
455
+ id: `seo-validation-lang-${pageId}`,
456
+ type: 'warning',
457
+ message: `Page "${pageName}": Missing lang attribute on &lt;html&gt; tag. This is important for accessibility and SEO.`,
458
+ componentId,
459
+ group: 'seo-validation'
460
+ })
461
+ }
462
+
463
+ // Check for title
464
+ const title = getSetting(pageSettings, 'title')
465
+ if (!title || title.trim() === '') {
466
+ this.editor.runCommand('notifications:add', {
467
+ id: `seo-validation-title-${pageId}`,
468
+ type: 'warning',
469
+ message: `Page "${pageName}": Missing &lt;title&gt; tag. This is critical for SEO.`,
470
+ componentId,
471
+ group: 'seo-validation'
472
+ })
473
+ }
474
+
475
+ // Check for description
476
+ const description = getSetting(pageSettings, 'description')
477
+ if (!description || description.trim() === '') {
478
+ this.editor.runCommand('notifications:add', {
479
+ id: `seo-validation-description-${pageId}`,
480
+ type: 'warning',
481
+ message: `Page "${pageName}": Missing meta description. This is important for SEO and search results display.`,
482
+ componentId,
483
+ group: 'seo-validation'
484
+ })
485
+ }
486
+
487
+ // Check for canonical link
488
+ if (!this.hasCanonicalLink(siteHead) && !this.hasCanonicalLink(pageHead)) {
489
+ this.editor.runCommand('notifications:add', {
490
+ id: `seo-validation-canonical-${pageId}`,
491
+ type: 'warning',
492
+ message: `Page "${pageName}": Missing canonical link. This helps prevent duplicate content issues.`,
493
+ componentId,
494
+ group: 'seo-validation'
495
+ })
496
+ }
497
+
498
+ // Check for alternate links (hreflang for multilingual sites)
499
+ if (!this.hasAlternateLinks(siteHead) && !this.hasAlternateLinks(pageHead)) {
500
+ this.editor.runCommand('notifications:add', {
501
+ id: `seo-validation-alternate-${pageId}`,
502
+ type: 'warning',
503
+ message: `Page "${pageName}": Missing alternate links (hreflang). Consider adding these for multilingual sites.`,
504
+ componentId,
505
+ group: 'seo-validation'
506
+ })
507
+ }
508
+ }
509
+ }
510
+
357
511
  async *getHtmlFilesYield(siteSettings: WebsiteSettings, preventDefault): AsyncGenerator<WebsiteFile | undefined> {
358
512
  for (const page of this.editor.Pages.getAll()) {
359
513
  // Clone the settings because plugins can change them
@@ -395,6 +549,8 @@ export class PublicationManager {
395
549
  // Useful data for HTML result
396
550
  const title = getSetting('title')
397
551
  const favicon = getSetting('favicon')
552
+ const viewportMeta = this.ensureViewportMeta(clonedSiteSettings?.head || '', pageSettings?.head || '')
553
+ const generatorMeta = this.ensureGeneratorMeta(clonedSiteSettings?.head || '', pageSettings?.head || '')
398
554
 
399
555
  // Return the HTML file
400
556
  yield {
@@ -402,6 +558,8 @@ export class PublicationManager {
402
558
  <html lang="${getSetting('lang')}">
403
559
  <head>
404
560
  <meta charset="UTF-8">
561
+ ${viewportMeta}
562
+ ${generatorMeta}
405
563
  <link rel="stylesheet" href="${cssPermalink}" />
406
564
  ${clonedSiteSettings?.head || ''}
407
565
  ${pageSettings?.head || ''}
@@ -47,9 +47,10 @@ export default function (editor, options) {
47
47
 
48
48
  editor.on('component:selected style:target component:drag:end', () => renderBreadcrumbs())
49
49
  function renderBreadcrumbs() {
50
- let component = editor.getSelected() ?? editor.Pages.getSelected().getMainComponent()
50
+ const selectedPage = editor.Pages?.getSelected()
51
+ let component = editor.getSelected() ?? selectedPage?.getMainComponent()
51
52
 
52
- if(!breadcrumbsContainer) return
53
+ if(!breadcrumbsContainer || !component) return
53
54
 
54
55
  // Clear the breadcrumbs container
55
56
  breadcrumbsContainer.innerHTML = ''
@@ -0,0 +1,333 @@
1
+ import { DataSourceType, Field, IDataSource, Type, addDataSource, addFilters, removeFilters } from '@silexlabs/grapesjs-data-source'
2
+ import { EleventyPluginOptions, Silex11tyPluginWebsiteSettings } from './index'
3
+ import { Editor } from 'grapesjs'
4
+ import { i18nFilters } from './filters'
5
+ import { ClientEvent } from '../../events'
6
+
7
+ //import { cmdPauseAutoSave } from '@silexlabs/silex/src/ts/client/grapesjs/storage'
8
+ const cmdPauseAutoSave = 'pause-auto-save'
9
+
10
+ export default function(editor: Editor, opts: EleventyPluginOptions): void {
11
+ editor.on(`
12
+ ${ ClientEvent.SETTINGS_SAVE_END }
13
+ storage:after:load
14
+ `, () => {
15
+ updateFilters(editor, opts)
16
+ })
17
+ updateFilters(editor, opts)
18
+ if(opts.enable11ty) {
19
+ // Add the 11ty data source using the new functional API
20
+ const ds = new EleventyDataSource()
21
+ editor.runCommand(cmdPauseAutoSave)
22
+
23
+ // Add the data source
24
+ addDataSource(ds)
25
+
26
+ // Wait for the next tick to avoid triggering a save
27
+ setTimeout(() => {
28
+ editor.stopCommand(cmdPauseAutoSave)
29
+ })
30
+ }
31
+ }
32
+
33
+ function updateFilters(editor: Editor, opts: EleventyPluginOptions) {
34
+ const settings = (editor.getModel().get('settings') || {}) as Silex11tyPluginWebsiteSettings
35
+ if(settings.eleventyI18n) {
36
+ addFilters(i18nFilters)
37
+ } else if (!opts.i18nPlugin) {
38
+ removeFilters(i18nFilters)
39
+ }
40
+ }
41
+
42
+ export const EleventyDataSourceId = 'eleventy'
43
+
44
+ export class EleventyDataSource implements IDataSource {
45
+ /**
46
+ * Unique identifier of the data source
47
+ * This is used to retrieve the data source from the editor
48
+ */
49
+ public id = EleventyDataSourceId
50
+ public label = 'Eleventy'
51
+ public url = ''
52
+ public type = 'graphql' as DataSourceType
53
+ public method = 'POST'
54
+ public headers = {}
55
+ public hidden = true
56
+ public readonly = true
57
+
58
+ private eventListeners: Record<string, ((...args: unknown[]) => void)[]> = {}
59
+
60
+ // Simple event handling
61
+ on(event: string, callback: (...args: unknown[]) => void): void {
62
+ if (!this.eventListeners[event]) {
63
+ this.eventListeners[event] = []
64
+ }
65
+ this.eventListeners[event].push(callback)
66
+ }
67
+
68
+ off(event: string, callback?: (...args: unknown[]) => void): void {
69
+ if (!this.eventListeners[event]) return
70
+ if (callback) {
71
+ this.eventListeners[event] = this.eventListeners[event].filter(cb => cb !== callback)
72
+ } else {
73
+ this.eventListeners[event] = []
74
+ }
75
+ }
76
+
77
+ trigger(event: string, ...args: unknown[]): void {
78
+ if (!this.eventListeners[event]) return
79
+ this.eventListeners[event].forEach(callback => callback(...args))
80
+ }
81
+
82
+ /**
83
+ * Implement IDatasource
84
+ */
85
+ async connect(): Promise<void> {}
86
+ isConnected(): boolean { return true }
87
+
88
+ /**
89
+ * Implement IDatasource
90
+ */
91
+ getQuery(/*expressions: Expression[]*/): string { return '' }
92
+
93
+ /**
94
+ * Implement IDatasource
95
+ */
96
+ getTypes(): Type[] {
97
+ return [{
98
+ id: 'string',
99
+ label: 'String',
100
+ dataSourceId: 'eleventy',
101
+ fields: [],
102
+ }, {
103
+ id: 'number',
104
+ label: 'Number',
105
+ dataSourceId: 'eleventy',
106
+ fields: [],
107
+ }, {
108
+ id: 'date',
109
+ label: 'Date',
110
+ dataSourceId: 'eleventy',
111
+ fields: [],
112
+ }, {
113
+ id: 'page',
114
+ label: 'page',
115
+ dataSourceId: 'eleventy',
116
+ fields: [{
117
+ id: 'url',
118
+ label: 'url',
119
+ typeIds: ['string'],
120
+ kind: 'scalar',
121
+ dataSourceId: 'eleventy',
122
+ }, {
123
+ id: 'fileSlug',
124
+ label: 'fileSlug',
125
+ typeIds: ['string'],
126
+ kind: 'scalar',
127
+ dataSourceId: 'eleventy',
128
+ }, {
129
+ id: 'filePathStem',
130
+ label: 'filePathStem',
131
+ typeIds: ['string'],
132
+ kind: 'scalar',
133
+ dataSourceId: 'eleventy',
134
+ }, {
135
+ id: 'date',
136
+ label: 'date',
137
+ typeIds: ['date'],
138
+ kind: 'scalar',
139
+ dataSourceId: 'eleventy',
140
+ }, {
141
+ id: 'inputPath',
142
+ label: 'inputPath',
143
+ typeIds: ['string'],
144
+ kind: 'scalar',
145
+ dataSourceId: 'eleventy',
146
+ }, {
147
+ id: 'outputPath',
148
+ label: 'outputPath',
149
+ typeIds: ['string'],
150
+ kind: 'scalar',
151
+ dataSourceId: 'eleventy',
152
+ }, {
153
+ id: 'outputFileExtension',
154
+ label: 'outputFileExtension',
155
+ typeIds: ['string'],
156
+ kind: 'scalar',
157
+ dataSourceId: 'eleventy',
158
+ }, {
159
+ id: 'lang',
160
+ label: 'lang',
161
+ typeIds: ['string'],
162
+ kind: 'scalar',
163
+ dataSourceId: 'eleventy',
164
+ }],
165
+ }, {
166
+ id: 'pagination',
167
+ label: 'pagination',
168
+ dataSourceId: 'eleventy',
169
+ fields: [{
170
+ id: 'hrefs',
171
+ label: 'hrefs',
172
+ typeIds: ['string'],
173
+ kind: 'list',
174
+ dataSourceId: 'eleventy',
175
+ }, {
176
+ id: 'href',
177
+ label: 'href',
178
+ typeIds: ['paginationHref'],
179
+ kind: 'object',
180
+ dataSourceId: 'eleventy',
181
+ }, {
182
+ id: 'pageNumber',
183
+ label: 'pageNumber',
184
+ typeIds: ['number'],
185
+ kind: 'scalar',
186
+ dataSourceId: 'eleventy',
187
+ }, {
188
+ id: 'pages',
189
+ label: 'pages',
190
+ typeIds: ['page'],
191
+ kind: 'list',
192
+ dataSourceId: 'eleventy',
193
+ }],
194
+ }, {
195
+ id: 'paginationHref',
196
+ label: 'paginationHref',
197
+ dataSourceId: 'eleventy',
198
+ fields: [{
199
+ id: 'next',
200
+ label: 'next',
201
+ typeIds: ['string'],
202
+ kind: 'scalar',
203
+ dataSourceId: 'eleventy',
204
+ }, {
205
+ id: 'previous',
206
+ label: 'previous',
207
+ typeIds: ['string'],
208
+ kind: 'scalar',
209
+ dataSourceId: 'eleventy',
210
+ }, {
211
+ id: 'first',
212
+ label: 'first',
213
+ typeIds: ['string'],
214
+ kind: 'scalar',
215
+ dataSourceId: 'eleventy',
216
+ }, {
217
+ id: 'last',
218
+ label: 'last',
219
+ typeIds: ['string'],
220
+ kind: 'scalar',
221
+ dataSourceId: 'eleventy',
222
+ }],
223
+ }, {
224
+ id: 'eleventy',
225
+ label: 'eleventy',
226
+ dataSourceId: 'eleventy',
227
+ fields: [{
228
+ id: 'version',
229
+ label: 'version',
230
+ typeIds: ['string'],
231
+ kind: 'scalar',
232
+ dataSourceId: 'eleventy',
233
+ }, {
234
+ id: 'generator',
235
+ label: 'generator',
236
+ typeIds: ['string'],
237
+ kind: 'scalar',
238
+ dataSourceId: 'eleventy',
239
+ }, {
240
+ id: 'env',
241
+ label: 'env',
242
+ typeIds: ['env'],
243
+ kind: 'object',
244
+ dataSourceId: 'eleventy',
245
+ }]
246
+ }, {
247
+ id: 'env',
248
+ label: 'env',
249
+ dataSourceId: 'eleventy',
250
+ fields: [{
251
+ id: 'root',
252
+ label: 'root',
253
+ typeIds: ['string'],
254
+ kind: 'scalar',
255
+ dataSourceId: 'eleventy',
256
+ }, {
257
+ id: 'config',
258
+ label: 'config',
259
+ typeIds: ['string'],
260
+ kind: 'scalar',
261
+ dataSourceId: 'eleventy',
262
+ }, {
263
+ id: 'source',
264
+ label: 'source',
265
+ typeIds: ['string'],
266
+ kind: 'scalar',
267
+ dataSourceId: 'eleventy',
268
+ }, {
269
+ id: 'runMode',
270
+ label: 'runMode',
271
+ typeIds: ['string'],
272
+ kind: 'scalar',
273
+ dataSourceId: 'eleventy',
274
+ }],
275
+ }, {
276
+ id: 'locale_link',
277
+ label: 'locale_link',
278
+ dataSourceId: 'eleventy',
279
+ fields: [{
280
+ id: 'url',
281
+ label: 'url',
282
+ typeIds: ['string'],
283
+ kind: 'scalar',
284
+ dataSourceId: 'eleventy',
285
+ }, {
286
+ id: 'lang',
287
+ label: 'lang',
288
+ typeIds: ['string'],
289
+ kind: 'scalar',
290
+ dataSourceId: 'eleventy',
291
+ }, {
292
+ id: 'label',
293
+ label: 'label',
294
+ typeIds: ['string'],
295
+ kind: 'scalar',
296
+ dataSourceId: 'eleventy',
297
+ }],
298
+ }]
299
+ }
300
+
301
+ /**
302
+ * Implement IDatasource
303
+ */
304
+ getQueryables(): Field[] {
305
+ return [{
306
+ id: 'page',
307
+ label: 'page',
308
+ typeIds: ['page'],
309
+ kind: 'object',
310
+ dataSourceId: 'eleventy',
311
+ //}, {
312
+ // id: 'eleventy',
313
+ // label: 'eleventy',
314
+ // typeIds: ['eleventy'],
315
+ // kind: 'object',
316
+ // dataSourceId: 'eleventy',
317
+ //}, {
318
+ // id: 'env',
319
+ // label: 'env',
320
+ // typeIds: ['env'],
321
+ // kind: 'object',
322
+ // dataSourceId: 'eleventy',
323
+ }]
324
+ }
325
+
326
+ fetchValues(query: string): Promise<unknown> {
327
+ console.log('fetch', {query})
328
+ throw new Error('not implemented yet')
329
+ }
330
+ }
331
+
332
+ export class EleventyDataSourceTest extends EleventyDataSource {
333
+ }