anentrypoint-design 0.0.104 → 0.0.106
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.
- package/dist/247420.css +11 -11
- package/dist/247420.js +62 -15
- package/package.json +1 -1
- package/src/page-html.js +117 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.106",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
package/src/page-html.js
CHANGED
|
@@ -1,27 +1,129 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Static-site page HTML renderer. Consumes structured page YAML
|
|
2
|
+
// (hero/sections/examples/body) and emits a complete <!doctype html>
|
|
3
|
+
// scaffold with rail-coloured sections and SDK styles loaded from unpkg.
|
|
4
|
+
// Used by 247420-flavoured doc sites (e.g. flatspace consumers).
|
|
3
5
|
|
|
4
|
-
const
|
|
6
|
+
const RAILS = ['rail-green', 'rail-purple', 'rail-mascot', 'rail-sun', 'rail-flame', 'rail-sky'];
|
|
7
|
+
const DOTS = ['green', 'purple', 'mascot', 'sun', 'flame', 'sky'];
|
|
5
8
|
|
|
6
|
-
export function
|
|
9
|
+
export function escape(s) {
|
|
10
|
+
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function inlineMd(s) {
|
|
14
|
+
return s
|
|
15
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
16
|
+
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
|
17
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function renderMarkdown(md) {
|
|
21
|
+
const lines = String(md || '').split('\n');
|
|
22
|
+
const out = [];
|
|
23
|
+
let inCode = false, inList = false;
|
|
24
|
+
for (const line of lines) {
|
|
25
|
+
if (line.startsWith('```')) { if (inCode) { out.push('</pre>'); inCode = false; } else { out.push('<pre>'); inCode = true; } continue; }
|
|
26
|
+
if (inCode) { out.push(escape(line)); continue; }
|
|
27
|
+
if (line.startsWith('# ')) out.push(`<h1>${escape(line.slice(2))}</h1>`);
|
|
28
|
+
else if (line.startsWith('## ')) out.push(`<h2>${escape(line.slice(3))}</h2>`);
|
|
29
|
+
else if (line.startsWith('### ')) out.push(`<h3>${escape(line.slice(4))}</h3>`);
|
|
30
|
+
else if (line.startsWith('- ')) { if (!inList) { out.push('<ul>'); inList = true; } out.push(`<li>${inlineMd(escape(line.slice(2)))}</li>`); }
|
|
31
|
+
else { if (inList) { out.push('</ul>'); inList = false; } if (line.trim()) out.push(`<p>${inlineMd(escape(line))}</p>`); }
|
|
32
|
+
}
|
|
33
|
+
if (inList) out.push('</ul>');
|
|
34
|
+
if (inCode) out.push('</pre>');
|
|
35
|
+
return out.join('\n');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function heroBlock(hero, title) {
|
|
39
|
+
if (!hero) return '';
|
|
40
|
+
const badges = Array.isArray(hero.badges) && hero.badges.length
|
|
41
|
+
? `<div class="ds-hero-badges">${hero.badges.map(b => `<span class="chip"><strong>${escape(b.label || '')}</strong>${b.desc ? `<span class="dim"> ${escape(b.desc)}</span>` : ''}</span>`).join(' ')}</div>` : '';
|
|
42
|
+
const ctas = Array.isArray(hero.ctas) && hero.ctas.length
|
|
43
|
+
? `<div class="ds-hero-ctas">${hero.ctas.map((c, i) => `<a class="${i === 0 ? 'btn-primary' : 'btn'}" href="${escape(c.href || '#')}">${escape(c.label || c.cta || 'go')}</a>`).join('')}</div>` : '';
|
|
44
|
+
return `<div class="ds-hero">
|
|
45
|
+
<h1 class="ds-hero-title">${escape(hero.heading || hero.title || title)}</h1>
|
|
46
|
+
${hero.subheading ? `<p class="ds-hero-body">${escape(hero.subheading)}${hero.accent ? ` <span class="ds-hero-accent">${escape(hero.accent)}</span>` : ''}</p>` : ''}
|
|
47
|
+
${hero.body ? `<p class="ds-hero-body">${escape(hero.body)}</p>` : ''}
|
|
48
|
+
${badges}
|
|
49
|
+
${ctas}
|
|
50
|
+
</div>`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sectionBlocks(sections) {
|
|
54
|
+
return (Array.isArray(sections) ? sections : []).map((sec, idx) => {
|
|
55
|
+
const rail = RAILS[idx % RAILS.length];
|
|
56
|
+
const dot = DOTS[idx % DOTS.length];
|
|
57
|
+
const items = (sec.features || sec.items || []).map((f) => {
|
|
58
|
+
const benefit = f.benefit ? `<div class="row-benefit">${escape(f.benefit)}</div>` : '';
|
|
59
|
+
return `<div class="row ${rail}">
|
|
60
|
+
<span class="dot dot-${dot}" aria-hidden="true"></span>
|
|
61
|
+
<span class="title">${escape(f.name)}</span>
|
|
62
|
+
${f.desc ? `<div class="sub">${inlineMd(escape(f.desc))}</div>` : ''}
|
|
63
|
+
${benefit}
|
|
64
|
+
</div>`;
|
|
65
|
+
}).join('\n');
|
|
66
|
+
const lede = sec.lede || (sec.body && sec.body.length < 240 ? sec.body : '');
|
|
67
|
+
return `<section class="ds-section ${rail}" id="${escape(sec.id || '')}">
|
|
68
|
+
<h2 class="ds-section-title">${escape(sec.name || sec.title || sec.id)}</h2>
|
|
69
|
+
${lede ? `<p class="ds-lede">${escape(lede)}</p>` : ''}
|
|
70
|
+
${items}
|
|
71
|
+
${sec.body && sec.body.length >= 240 ? renderMarkdown(sec.body) : ''}
|
|
72
|
+
</section>`;
|
|
73
|
+
}).join('\n');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function examplesBlock(examples) {
|
|
77
|
+
if (!Array.isArray(examples) || !examples.length) return '';
|
|
78
|
+
return `<section class="ds-section">
|
|
79
|
+
<h2 class="ds-section-title">explore</h2>
|
|
80
|
+
${examples.map((e, i) => {
|
|
81
|
+
const rail = RAILS[(i + 1) % RAILS.length];
|
|
82
|
+
return `<a class="row ${rail}" href="${escape(e.href || '#')}">
|
|
83
|
+
<span class="code">${String(i + 1).padStart(2, '0')}</span>
|
|
84
|
+
<span class="title">${escape(e.label || e.name || e.href)}</span>
|
|
85
|
+
${e.desc ? `<span class="meta dim"> — ${escape(e.desc)}</span>` : ''}
|
|
86
|
+
<span class="ds-row-arrow">↗</span>
|
|
87
|
+
</a>`;
|
|
88
|
+
}).join('\n')}
|
|
89
|
+
</section>`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function renderPageHtml({ title = '247420', slug = 'index', hero, sections, examples, body, navItems = [], siteName = '247420', theme = 'auto', cssHref, headExtra = '' } = {}) {
|
|
93
|
+
const main = heroBlock(hero, title) + sectionBlocks(sections) + examplesBlock(examples)
|
|
94
|
+
+ (body ? `<section class="ds-section page-body">${renderMarkdown(body)}</section>` : '');
|
|
7
95
|
const cssLink = cssHref
|
|
8
96
|
? `<link rel="stylesheet" href="${cssHref}">`
|
|
9
97
|
: `<link rel="stylesheet" href="https://unpkg.com/anentrypoint-design@latest/dist/247420.css">`;
|
|
10
98
|
return `<!doctype html>
|
|
11
|
-
<html lang="en" class="
|
|
99
|
+
<html lang="en" class="ds-247420" data-theme="${theme}">
|
|
12
100
|
<head>
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
101
|
+
<meta charset="utf-8">
|
|
102
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
103
|
+
<title>${escape(title)} — ${escape(siteName)}</title>
|
|
104
|
+
${cssLink}
|
|
105
|
+
<script type="importmap">
|
|
106
|
+
{ "imports": { "anentrypoint-design": "https://unpkg.com/anentrypoint-design@latest/dist/247420.js" } }
|
|
107
|
+
</script>
|
|
108
|
+
<style>
|
|
109
|
+
.app-stage { max-width: 1100px; margin: 0 auto; padding: 24px }
|
|
110
|
+
.page-body h1 { margin-top: 0 } .page-body h2 { margin-top: 32px } .page-body h3 { margin-top: 24px }
|
|
111
|
+
.page-body pre { margin: 12px 0; background: var(--panel-2); padding: 12px; border-radius: 8px; overflow-x: auto }
|
|
112
|
+
</style>
|
|
113
|
+
${headExtra}
|
|
18
114
|
</head>
|
|
19
115
|
<body>
|
|
20
|
-
|
|
116
|
+
<div id="app"></div>
|
|
117
|
+
<script type="module">
|
|
118
|
+
import { mount, components as C } from 'anentrypoint-design';
|
|
119
|
+
const navItems = ${JSON.stringify(navItems)};
|
|
120
|
+
mount(document.getElementById('app'), () => C.AppShell({
|
|
121
|
+
topbar: C.Topbar({ brand: ${JSON.stringify(siteName)}, items: navItems, active: ${JSON.stringify(title)} }),
|
|
122
|
+
crumb: C.Crumb({ leaf: ${JSON.stringify(title)} }),
|
|
123
|
+
main: C.h('div', { class: 'app-stage', innerHTML: ${JSON.stringify(main)} }),
|
|
124
|
+
status: C.Status({ left: [${JSON.stringify(siteName.toLowerCase())}, ${JSON.stringify(slug)}], right: ['live'] })
|
|
125
|
+
}));
|
|
126
|
+
</script>
|
|
21
127
|
</body>
|
|
22
128
|
</html>`;
|
|
23
129
|
}
|
|
24
|
-
|
|
25
|
-
function escapeHtml(s) {
|
|
26
|
-
return String(s).replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' })[c]);
|
|
27
|
-
}
|