mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 12:20:40 -07:00
* docs(readme): lead with quick start and scannable structure Restructure the README to match common OSS conventions: tagline and badges above the fold, copy-paste Quick start, Features list, and a compact Used by section. Remove the star plea, centered logo, and per-project marketing blurbs that pushed useful content down. Co-authored-by: Cursor <[email protected]> * docs(readme): playground GIF, used-by grid, and docs homepage sync Add data/used-by.json with build:used-by for README and docs homepage, playground demo capture, and shared home-section layout. Used by lists products with site logos; Financial Support keeps org and individual sponsors. Co-authored-by: Cursor <[email protected]> * chore: use .local for playground capture scratch files Co-authored-by: Cursor <[email protected]> * fix: satisfy eslint in build-used-by and capture scripts Co-authored-by: Cursor <[email protected]> * chore: drop one-off playground capture script Co-authored-by: Cursor <[email protected]> * refactor(docs): copy Used by from README like financial contributors Drop data/used-by.json and build-used-by.js; build-contributors.js now extracts USED-BY-BEGIN/END to used-by.swig. Co-authored-by: Cursor <[email protected]> * refactor(docs): inline Used by section, drop home-section partial Co-authored-by: Cursor <[email protected]> * fix(docs): drop redundant logo styles from .contributors Co-authored-by: Cursor <[email protected]> * fix(docs): build liquid bundle before hexo serve Co-authored-by: Cursor <[email protected]> * refactor(docs): drop playground window chrome from capture demo Co-authored-by: Cursor <[email protected]> * refactor(docs): revert playground capture changes to master behavior Restore Ace output pane, drop Prism and output-preview styling. Simplify docs:dev to rely on docs prestart. Co-authored-by: Cursor <[email protected]> * refactor(docs): rely on docs prebuild for liquid bundle and contributors Co-authored-by: Cursor <[email protected]> * feat(docs): show playground output as Prism-highlighted HTML code Co-authored-by: Cursor <[email protected]> * feat(docs): polish playground layout and regenerate README demo GIF * fix(docs): align playground GIF capture with live editor styling * fix(docs): unify playground pane padding and hold output on errors Match editor inset to the output panel, drop Prism from output preview, keep the last render while typing invalid template/context, and refresh the README demo GIF. * fix(docs): regenerate playground GIF with held output during typing * feat(docs): sync Used by logos and polish playground Inline README Used by grid on the docs homepage, refine playground layout and live output behavior, and drop the unused build-used-by script from package scripts. Co-authored-by: Cursor <[email protected]> * fix(docs): restore Rock RMS logo and remove duplicate entry Restore the official Rock RMS wordmark (GetImage.ashx?id=72534) instead of the SparkDevNetwork GitHub org avatar that was wrongly substituted for it. Co-authored-by: Cursor <[email protected]> * fix(docs): regenerate playground GIF with live indicator states Restore the capture script for the new pane-indicator layout so the README demo shows correct idle/active/pending/ok colors and pulsing animations while typing. * fix(docs): static playground GIF with correct indicator colors Capture one frame per keystroke with animations disabled so dot states (idle/active/pending/ok) match the live playground without pulsing. Co-authored-by: Cursor <[email protected]> * docs: use square Rock RMS icon in Used by section Co-authored-by: Cursor <[email protected]> * fix(docs): ensure capture indicator colors apply instantly Disable indicator transitions and cancel active animations before setting data-state so pending yellow is not stuck on the prior ok green. Co-authored-by: Cursor <[email protected]> * docs: point Microsoft Used by link to microsoft.com The merged tile title covers Power Pages and Azure API Management; href should go to Microsoft home, not Power Pages only. Co-authored-by: Cursor <[email protected]> * docs: remove Dailycontributors from Used by section No evidence they run on LiquidJS; they are an OpenCollective sponsor only. Co-authored-by: Cursor <[email protected]> * docs: reword intro to say Liquid, not Shopify Liquid Move Shopify into the compatibility list and drop the shopify/liquid link from README; align package.json description. Co-authored-by: Cursor <[email protected]> * fix(docs): restore playground output as Prism-highlighted HTML Co-authored-by: Cursor <[email protected]> * docs: add extensible to README intro and package description EOF Co-authored-by: Cursor <[email protected]> * chore: move playground capture script to .local Co-authored-by: Cursor <[email protected]> * fix(docs): drop unused Ace mode-html from playground Output pane uses Prism, not Ace; template and context editors still need liquid/json modes and basePath for themes. Co-authored-by: Cursor <[email protected]> * docs: sync intro sentence across package and site metadata Align package.json, docs config, manifest, llms.txt, and AGENTS.md tagline to the README canonical description. Co-authored-by: Cursor <[email protected]> * docs: trim verbose intro in intro-to-liquid tutorial Remove README tagline and repo-purpose copy duplicated by the recent metadata sync. Co-authored-by: Cursor <[email protected]> * docs: shorten homepage banner subtitle Trim docs site banner and short taglines after the em dash; keep full description for meta tags and npm/README. * docs: simplify playground GIF caption in README Co-authored-by: Cursor <[email protected]> * docs: dedupe homepage subtitle and description into _config.yml Remove redundant front matter from index.pug; theme falls back to site config for banner and meta tags. Co-authored-by: Cursor <[email protected]> --------- Co-authored-by: Cursor <[email protected]>
282 lines
8.1 KiB
JavaScript
282 lines
8.1 KiB
JavaScript
(function() {
|
|
// mobile nav
|
|
// var body = document.getElementsByTagName('body')[0];
|
|
var html = document.getElementsByTagName('html')[0];
|
|
var navToggle = document.getElementById('mobile-nav-toggle');
|
|
var dimmer = document.getElementById('mobile-nav-dimmer');
|
|
var CLASS_NAME = 'mobile-nav-on';
|
|
if (!navToggle) return;
|
|
|
|
navToggle.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
// body.classList.toggle(CLASS_NAME);
|
|
html.classList.toggle(CLASS_NAME);
|
|
});
|
|
|
|
dimmer.addEventListener('click', function(e) {
|
|
if (!html.classList.contains(CLASS_NAME)) return;
|
|
|
|
e.preventDefault();
|
|
html.classList.remove(CLASS_NAME);
|
|
});
|
|
}());
|
|
|
|
(function() {
|
|
// article toc
|
|
var tocList = document.getElementById('article-toc-inner-list');
|
|
if (!tocList) return;
|
|
|
|
window.addEventListener('resize', setMaxHeight);
|
|
setMaxHeight();
|
|
|
|
function setMaxHeight() {
|
|
var maxHeight = window.innerHeight - 45;
|
|
tocList.style['max-height'] = maxHeight + 'px';
|
|
}
|
|
}());
|
|
|
|
(function() {
|
|
// playground
|
|
/* global liquidjs, ace, Prism */
|
|
if (!/\/playground(?:\.html)?$/.test(location.pathname)) return;
|
|
updateVersion(liquidjs.version);
|
|
const engine = new liquidjs.Liquid({
|
|
memoryLimit: 1e5,
|
|
renderLimit: 1e5
|
|
});
|
|
const colorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
const editor = createEditor('editorEl', 'liquid');
|
|
const dataEditor = createEditor('dataEl', 'json');
|
|
const previewCode = document.getElementById('previewCode');
|
|
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];
|
|
let previewValue = '';
|
|
let hadPreview = false;
|
|
let renderTimer = null;
|
|
const RENDER_DELAY = 180;
|
|
colorScheme.addEventListener('change', function() {
|
|
editors.forEach(applyEditorTheme);
|
|
if (previewValue) setPreview(previewValue);
|
|
});
|
|
|
|
const init = parseArgs(location.hash.slice(1));
|
|
if (init) {
|
|
editor.setValue(init.tpl, 1);
|
|
dataEditor.setValue(init.data, 1);
|
|
}
|
|
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() {
|
|
const loader = document.querySelector('.loader');
|
|
loader.classList.add('hide');
|
|
loader.setAttribute('aria-busy', false);
|
|
|
|
const editorsEl = document.querySelector('#editors');
|
|
editorsEl.classList.remove('hide');
|
|
editorsEl.setAttribute('aria-hide', false);
|
|
editors.forEach(function(ed) { ed.resize(); });
|
|
}
|
|
|
|
function getEditorTheme() {
|
|
return colorScheme.matches
|
|
? 'ace/theme/tomorrow_night_eighties'
|
|
: 'ace/theme/github';
|
|
}
|
|
|
|
function applyEditorTheme(editor) {
|
|
editor.setTheme(getEditorTheme());
|
|
editor.renderer.setPadding(0);
|
|
editor.container.style.background = 'transparent';
|
|
}
|
|
|
|
function createEditor(id, lang) {
|
|
const editor = ace.edit(id);
|
|
applyEditorTheme(editor);
|
|
editor.setOptions({
|
|
fontFamily: '"Source Code Pro", ui-monospace, Monaco, Menlo, Consolas, monospace',
|
|
fontSize: '14px',
|
|
showPrintMargin: false,
|
|
showGutter: false,
|
|
highlightActiveLine: false,
|
|
tabSize: 2,
|
|
useSoftTabs: true,
|
|
scrollPastEnd: 0
|
|
});
|
|
editor.getSession().setMode('ace/mode/' + lang);
|
|
editor.renderer.setShowGutter(false);
|
|
if (editor.renderer.$gutter) {
|
|
editor.renderer.$gutter.style.display = 'none';
|
|
}
|
|
editor.renderer.setScrollMargin(0, 0, 0, 0);
|
|
bindClipboard(editor);
|
|
return editor;
|
|
}
|
|
|
|
function bindClipboard(editor) {
|
|
editor.commands.addCommand({
|
|
name: 'copy',
|
|
bindKey: {win: 'Ctrl-C', mac: 'Command-C'},
|
|
exec: function (ed) {
|
|
const text = ed.getCopyText();
|
|
if (!text) return;
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
navigator.clipboard.writeText(text);
|
|
}
|
|
},
|
|
readOnly: true
|
|
});
|
|
editor.commands.addCommand({
|
|
name: 'cut',
|
|
bindKey: {win: 'Ctrl-X', mac: 'Command-X'},
|
|
exec: function (ed) {
|
|
const text = ed.getCopyText();
|
|
if (!text) return;
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
navigator.clipboard.writeText(text).then(function () {
|
|
ed.insert('');
|
|
});
|
|
}
|
|
}
|
|
});
|
|
editor.commands.addCommand({
|
|
name: 'paste',
|
|
bindKey: {win: 'Ctrl-V', mac: 'Command-V'},
|
|
exec: function (ed) {
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
navigator.clipboard.readText().then(function (text) {
|
|
ed.insert(text);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function parseArgs(hash) {
|
|
if (!hash) return;
|
|
try {
|
|
let [tpl, data] = hash.split(',').map(atou);
|
|
data = data || '{}';
|
|
return { tpl, data };
|
|
} catch (e) {}
|
|
}
|
|
|
|
function serializeArgs(obj) {
|
|
return utoa(obj.tpl) + ',' + utoa(obj.data);
|
|
}
|
|
|
|
function setPreview(value) {
|
|
previewValue = value;
|
|
previewCode.textContent = value;
|
|
if (window.Prism) {
|
|
delete previewCode.dataset.highlighted;
|
|
window.Prism.highlightElement(previewCode);
|
|
}
|
|
}
|
|
|
|
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 {
|
|
parsed = JSON.parse(data);
|
|
} catch (err) {
|
|
setIndicator(indicatorData, 'error');
|
|
setIndicator(indicatorTpl, 'idle');
|
|
setIndicator(indicatorOutput, 'error');
|
|
return;
|
|
}
|
|
try {
|
|
const html = await engine.parseAndRender(tpl, parsed);
|
|
if (html !== '' || !hadPreview) {
|
|
setPreview(html);
|
|
if (html !== '') hadPreview = true;
|
|
}
|
|
setIndicator(indicatorTpl, 'idle');
|
|
setIndicator(indicatorData, 'idle');
|
|
setIndicator(indicatorOutput, 'ok');
|
|
} catch (err) {
|
|
setIndicator(indicatorTpl, 'error');
|
|
setIndicator(indicatorData, 'idle');
|
|
setIndicator(indicatorOutput, 'error');
|
|
}
|
|
}
|
|
|
|
function atou(str) {
|
|
return decodeURIComponent(escape(atob(str)));
|
|
}
|
|
|
|
function utoa(str) {
|
|
return btoa(unescape(encodeURIComponent(str)));
|
|
}
|
|
|
|
function updateVersion(version) {
|
|
document.querySelector('.version').innerHTML =
|
|
'liquidjs@<a target="_blank" rel="noopener noreferrer" href="https://www.npmjs.com/package/liquidjs/v/' + version + '">' + version + '</a>';
|
|
}
|
|
}());
|
|
|
|
(function() {
|
|
// GitHub star count
|
|
var el = document.getElementById('gh-star-count');
|
|
if (!el) return;
|
|
el.textContent = '1.8K';
|
|
if (!window.fetch) return;
|
|
|
|
fetch('https://api.github.com/repos/harttle/liquidjs')
|
|
.then(function(res) { return res.json(); })
|
|
.then(function(data) {
|
|
if (typeof data.stargazers_count === 'number') {
|
|
el.textContent = format(data.stargazers_count);
|
|
}
|
|
});
|
|
|
|
function format(n) {
|
|
if (n < 1000) return String(n);
|
|
var k = n / 1000;
|
|
return (k >= 10 ? Math.round(k) : Math.round(k * 10) / 10) + 'k';
|
|
}
|
|
}());
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', function() {
|
|
navigator.serviceWorker.register('/sw.js').then(function(reg) {
|
|
console.log('ServiceWorker registration successful with scope: ', reg.scope);
|
|
}).catch(function(err) {
|
|
console.log('ServiceWorker registration failed: ', err);
|
|
});
|
|
});
|
|
}
|