diff --git a/README.md b/README.md index bccc82078..3e389eb2f 100644 --- a/README.md +++ b/README.md @@ -55,18 +55,28 @@ See the [setup guide][setup] for partials, layouts, caching, and other options.

- Eleventy - GitHub Docs - Kibana - Power Pages, Azure API Management developer portal - Shopify CLI, Checkout Blocks - Directus - Builder.io, Mitosis + Eleventy + Opensense + Power Pages, Azure API Management developer portal + GitHub Docs + Kibana + Shopify CLI, Checkout Blocks + Customer IO
- Pattern Lab - Rock RMS - WISMOlabs - Dropkiq + Syntax Podcast + TestMu AI + Chudovo + Dailycontributors + PakStyle.pk + EscortA.com + Touchless +
+ Dropkiq + Directus + Builder.io, Mitosis + Pattern Lab + Rock RMS + WISMOlabs Freshet

diff --git a/docs/package.json b/docs/package.json index 3539ba4fb..71fbcf87a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -6,8 +6,6 @@ "version": "7.3.0" }, "scripts": { - "prebuild": "npm --prefix .. run build:docs-liquid && npm --prefix .. run build:contributors", - "prestart": "npm --prefix .. run build:docs-liquid && npm --prefix .. run build:contributors", "build": "hexo generate", "start": "hexo serve", "lint": "eslint .", diff --git a/docs/themes/navy/layout/index.swig b/docs/themes/navy/layout/index.swig index 0c480f400..ee2be8f2c 100644 --- a/docs/themes/navy/layout/index.swig +++ b/docs/themes/navy/layout/index.swig @@ -14,19 +14,6 @@ -
-
-
-
-

{{__('index.contributors.title')}}

-

{{__('index.contributors.description')}}

-
-
- {{ partial('partial/all-contributors') }} -
-
-
-
@@ -53,3 +40,16 @@
+
+
+
+
+

{{__('index.contributors.title')}}

+

{{__('index.contributors.description')}}

+
+
+ {{ partial('partial/all-contributors') }} +
+
+
+
diff --git a/docs/themes/navy/layout/partial/after_footer.swig b/docs/themes/navy/layout/partial/after_footer.swig index 1e77922b0..77d091c46 100644 --- a/docs/themes/navy/layout/partial/after_footer.swig +++ b/docs/themes/navy/layout/partial/after_footer.swig @@ -3,6 +3,7 @@ + {% endif %} diff --git a/docs/themes/navy/layout/playground.swig b/docs/themes/navy/layout/playground.swig index 2d4d07e3b..6aad969d6 100644 --- a/docs/themes/navy/layout/playground.swig +++ b/docs/themes/navy/layout/playground.swig @@ -12,7 +12,7 @@
- +

Template

@@ -21,7 +21,7 @@
- +

Context

@@ -30,13 +30,11 @@
- +

Output

-
-
{{__('playground.loading')}}
-
+
diff --git a/docs/themes/navy/source/css/_partial/index.styl b/docs/themes/navy/source/css/_partial/index.styl index ff59dea74..9a1ab78e3 100644 --- a/docs/themes/navy/source/css/_partial/index.styl +++ b/docs/themes/navy/source/css/_partial/index.styl @@ -166,7 +166,7 @@ &:hover color: var(--color-link-hover) -#used-by-wrap, #sponsors-wrap +#sponsors-wrap background: var(--color-content-bg) .inner h3 @@ -181,7 +181,7 @@ #contributors-wrap border: none - overflow: hidden; + overflow: hidden .contributors tr diff --git a/docs/themes/navy/source/css/_partial/playground.styl b/docs/themes/navy/source/css/_partial/playground.styl index 38d386311..7c56b759a 100644 --- a/docs/themes/navy/source/css/_partial/playground.styl +++ b/docs/themes/navy/source/css/_partial/playground.styl @@ -90,21 +90,18 @@ grid-row: 1 grid-column: 1 min-height: 0 - .pane-indicator - background: var(--color-link) + --pane-dot: var(--color-link) .area-data grid-row: 2 grid-column: 1 min-height: 0 - .pane-indicator - background: var(--highlight-orange) + --pane-dot: var(--highlight-orange) .area-output grid-column: 2 grid-row: 1 / -1 min-height: 0 min-width: 0 - .pane-indicator - background: var(--highlight-green) + --pane-dot: var(--highlight-green) @media mq-mobile grid-row: auto grid-column: 1 @@ -145,6 +142,66 @@ height: 8px border-radius: 50% flex-shrink: 0 + background: unquote('color-mix(in srgb, var(--pane-dot) 38%, var(--color-border))') + transition: background 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease + + &[data-state="active"] + background: var(--pane-dot) + animation: playground-dot-typing 0.85s ease-in-out infinite + + &[data-state="pending"] + background: var(--highlight-yellow) + + &[data-state="ok"] + background: var(--highlight-green) + animation: playground-dot-ok 0.45s ease-out + + &[data-state="error"] + background: var(--highlight-red) + animation: playground-dot-error 0.35s ease-out + + .area-output .pane-indicator + &[data-state="pending"] + animation: playground-dot-pending 0.55s ease-in-out infinite + + @keyframes playground-dot-typing + 0%, 100% + transform: scale(1) + box-shadow: 0 0 0 0 unquote('color-mix(in srgb, var(--pane-dot) 0%, transparent)') + 50% + transform: scale(1.2) + box-shadow: 0 0 0 4px unquote('color-mix(in srgb, var(--pane-dot) 28%, transparent)') + + @keyframes playground-dot-pending + 0%, 100% + transform: scale(1) + opacity: 0.75 + 50% + transform: scale(1.12) + opacity: 1 + + @keyframes playground-dot-ok + 0% + transform: scale(0.85) + box-shadow: 0 0 0 0 unquote('color-mix(in srgb, var(--highlight-green) 50%, transparent)') + 70% + transform: scale(1.15) + box-shadow: 0 0 0 5px unquote('color-mix(in srgb, var(--highlight-green) 0%, transparent)') + 100% + transform: scale(1) + box-shadow: none + + @keyframes playground-dot-error + 0%, 100% + transform: translateX(0) + 20% + transform: translateX(-2px) + 40% + transform: translateX(2px) + 60% + transform: translateX(-1px) + 80% + transform: translateX(1px) .pane-body flex: 1 1 auto @@ -156,27 +213,33 @@ background: var(--highlight-background) .area-tpl .pane-body, - .area-data .pane-body + .area-data .pane-body, + .area-output .pane-body padding: var(--playground-inset) box-sizing: border-box @media mq-mobile padding: 12px .area-tpl .ace_gutter, - .area-data .ace_gutter - display: none !important - width: 0 !important - min-width: 0 !important + .area-data .ace_gutter, + .area-output .ace_gutter + display: none + width: 0 + min-width: 0 .area-tpl .ace_editor, .area-data .ace_editor, + .area-output .ace_editor, .area-tpl .ace_scroller, .area-data .ace_scroller, + .area-output .ace_scroller, .area-tpl .ace_content, .area-data .ace_content, + .area-output .ace_content, .area-tpl .ace_text-layer, - .area-data .ace_text-layer - background: transparent !important + .area-data .ace_text-layer, + .area-output .ace_text-layer + background: transparent .editor flex: 1 1 auto @@ -186,45 +249,9 @@ @media mq-mobile min-height: 180px - .output-preview - flex: 1 1 auto - min-height: 0 - min-width: 0 - width: 100% - overflow: auto + .output-editor @media mq-mobile min-height: 120px - pre.highlight - margin: 0 - min-height: 100% - width: 100% - box-sizing: border-box - padding: var(--playground-inset) - border: none - box-shadow: none - border-radius: 0 - background: transparent - color: var(--highlight-foreground) - overflow-x: hidden - overflow-y: auto - white-space: pre-wrap - overflow-wrap: break-word - @media mq-mobile - padding: 12px - code - display: block - width: 100% - box-sizing: border-box - font-family: font-mono - font-size: 14px - line-height: 1.55 - color: var(--highlight-foreground) - background: transparent - padding: 0 - white-space: inherit - overflow-wrap: inherit - @media mq-mobile - font-size: 13px .ace_editor font-family: font-mono diff --git a/docs/themes/navy/source/js/main.js b/docs/themes/navy/source/js/main.js index 278e90e49..abd4484d3 100644 --- a/docs/themes/navy/source/js/main.js +++ b/docs/themes/navy/source/js/main.js @@ -48,11 +48,15 @@ const colorScheme = window.matchMedia('(prefers-color-scheme: dark)'); const editor = createEditor('editorEl', 'liquid'); const dataEditor = createEditor('dataEl', 'json'); - const previewCode = document.getElementById('previewCode'); + const previewEditor = createEditor('previewEl', 'html', { readOnly: true }); + const indicatorTpl = document.querySelector('.area-tpl .pane-indicator'); + const indicatorData = document.querySelector('.area-data .pane-indicator'); + const indicatorOutput = document.querySelector('.area-output .pane-indicator'); - const editors = [editor, dataEditor]; + const editors = [editor, dataEditor, previewEditor]; let previewValue = ''; - let hadPreview = false; + let renderTimer = null; + const RENDER_DELAY = 180; colorScheme.addEventListener('change', function() { editors.forEach(applyEditorTheme); if (previewValue) setPreview(previewValue); @@ -63,9 +67,11 @@ editor.setValue(init.tpl, 1); dataEditor.setValue(init.data, 1); } - editor.on('change', update); - dataEditor.on('change', update); - update(); + editor.on('change', onTemplateChange); + dataEditor.on('change', onContextChange); + editor.on('focus', function () { setIndicator(indicatorTpl, 'active'); }); + dataEditor.on('focus', function () { setIndicator(indicatorData, 'active'); }); + scheduleUpdate(); ready(); function ready() { @@ -91,7 +97,8 @@ editor.container.style.background = 'transparent'; } - function createEditor(id, lang) { + function createEditor(id, lang, options) { + options = options || {}; const editor = ace.edit(id); applyEditorTheme(editor); editor.setOptions({ @@ -110,6 +117,10 @@ editor.renderer.$gutter.style.display = 'none'; } editor.renderer.setScrollMargin(0, 0, 0, 0); + if (options.readOnly) { + editor.setReadOnly(true); + editor.getSession().setUseWrapMode(true); + } bindClipboard(editor); return editor; } @@ -166,23 +177,58 @@ return utoa(obj.tpl) + ',' + utoa(obj.data); } - function setPreview (value) { - previewValue = value - previewCode.textContent = value + function setPreview(value) { + previewValue = value; + previewEditor.setValue(value, -1); + previewEditor.clearSelection(); + } + + function setIndicator(indicator, state) { + if (indicator) indicator.dataset.state = state; + } + + function onTemplateChange() { + setIndicator(indicatorTpl, 'active'); + if (indicatorData.dataset.state !== 'error') setIndicator(indicatorData, 'idle'); + setIndicator(indicatorOutput, 'pending'); + scheduleUpdate(); + } + + function onContextChange() { + setIndicator(indicatorData, 'active'); + if (indicatorTpl.dataset.state !== 'error') setIndicator(indicatorTpl, 'idle'); + setIndicator(indicatorOutput, 'pending'); + scheduleUpdate(); + } + + function scheduleUpdate() { + clearTimeout(renderTimer); + renderTimer = setTimeout(update, RENDER_DELAY); } async function update() { const tpl = editor.getValue(); const data = dataEditor.getValue(); history.replaceState({}, '', '#' + serializeArgs({tpl, data})); + let parsed; try { - const html = await engine.parseAndRender(tpl, JSON.parse(data)); - if (html !== '' || !hadPreview) { - setPreview(html); - if (html !== '') hadPreview = true; - } + parsed = JSON.parse(data); } catch (err) { - // keep last successful output while template or context is invalid + setIndicator(indicatorData, 'error'); + setIndicator(indicatorTpl, 'idle'); + setIndicator(indicatorOutput, 'error'); + return; + } + try { + const html = await engine.parseAndRender(tpl, parsed); + setPreview(html); + setIndicator(indicatorTpl, 'idle'); + setIndicator(indicatorData, 'idle'); + setIndicator(indicatorOutput, 'ok'); + } catch (err) { + setIndicator(indicatorTpl, 'error'); + setIndicator(indicatorData, 'idle'); + setIndicator(indicatorOutput, 'error'); } } diff --git a/package.json b/package.json index 995de3f07..6bd02c13a 100644 --- a/package.json +++ b/package.json @@ -29,14 +29,15 @@ "build:min": "BUNDLES=min rollup -c rollup.config.mjs", "build:umd": "BUNDLES=umd rollup -c rollup.config.mjs", "build:charmap": "./bin/character-gen.js > src/util/character.ts", - "build:docs": "run-s build:apidoc build:changelog build:docs-hexo", + "prepare:docs": "run-s build:docs-liquid build:contributors build:apidoc build:changelog", + "build:docs": "run-s prepare:docs build:docs-hexo", "build:docs-liquid": "cross-env BUNDLES=min rollup -c rollup.config.mjs && shx cp dist/liquid.browser.min.js docs/themes/navy/source/js/", "build:contributors": "node bin/build-contributors.js", "build:apidoc": "shx rm -rf docs/source/api && typedoc --plugin typedoc-plugin-missing-exports ./src --gitRevision master --out docs/source/api", "build:changelog": "node bin/build-changelog.js", "build:docs-hexo": "cd docs && npm ci && npm run build && shx cp CNAME public/", - "docs:dev": "npm run docs:serve", - "docs:serve": "cd docs && npm run start" + "serve:docs": "cd docs && npm run start", + "dev:docs": "run-s prepare:docs serve:docs" }, "bin": { "liquidjs": "./bin/liquid.js",