@beforesemicolon/builder 1.8.22 → 1.8.24
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/README.md +39 -3
- package/dist/cjs/docs/markdown-layout/marked-extension.js +1 -1
- package/dist/cjs/docs/markdown-layout/types.js +1 -1
- package/dist/cjs/docs/run.js +5 -5
- package/dist/cjs/docs/templates/fading-citrus/README.md +57 -32
- package/dist/cjs/docs/templates/fading-citrus/assets/favicon/site.webmanifest +2 -2
- package/dist/cjs/docs/templates/fading-citrus/layouts/_footer.js +53 -60
- package/dist/cjs/docs/templates/fading-citrus/layouts/_head-meta.js +0 -16
- package/dist/cjs/docs/templates/fading-citrus/layouts/_header.js +65 -20
- package/dist/cjs/docs/templates/fading-citrus/layouts/_layout-utils.js +20 -0
- package/dist/cjs/docs/templates/fading-citrus/layouts/document.js +8 -4
- package/dist/cjs/docs/templates/fading-citrus/layouts/landing-hero.js +11 -3
- package/dist/cjs/docs/templates/fading-citrus/layouts/landing.js +1 -0
- package/dist/cjs/docs/templates/fading-citrus/template.config.js +26 -4
- package/dist/cjs/docs/types.js +1 -1
- package/dist/esm/docs/markdown-layout/marked-extension.js +1 -1
- package/dist/esm/docs/run.js +5 -5
- package/dist/esm/docs/templates/fading-citrus/README.md +57 -32
- package/dist/esm/docs/templates/fading-citrus/assets/favicon/site.webmanifest +2 -2
- package/dist/esm/docs/templates/fading-citrus/layouts/_footer.js +53 -60
- package/dist/esm/docs/templates/fading-citrus/layouts/_head-meta.js +0 -16
- package/dist/esm/docs/templates/fading-citrus/layouts/_header.js +65 -20
- package/dist/esm/docs/templates/fading-citrus/layouts/_layout-utils.js +20 -0
- package/dist/esm/docs/templates/fading-citrus/layouts/document.js +8 -4
- package/dist/esm/docs/templates/fading-citrus/layouts/landing-hero.js +11 -3
- package/dist/esm/docs/templates/fading-citrus/layouts/landing.js +1 -0
- package/dist/esm/docs/templates/fading-citrus/template.config.js +26 -4
- package/dist/types/docs/markdown-layout/marked-extension.d.ts +2 -1
- package/dist/types/docs/markdown-layout/types.d.ts +1 -0
- package/dist/types/docs/types.d.ts +34 -0
- package/package.json +1 -1
- package/dist/cjs/docs/templates/fading-citrus/assets/client-server.svg +0 -4
- package/dist/cjs/docs/templates/fading-citrus/assets/fast.svg +0 -4
- package/dist/cjs/docs/templates/fading-citrus/assets/independent.svg +0 -23
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-banner.jpg +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-essentials-training.jpg +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-favicon.jpg +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-favicon.png +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-logo-name.svg +0 -10
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-logo-name@2x.png +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-logo.svg +0 -13
- package/dist/cjs/docs/templates/fading-citrus/assets/markup-logo@2x.png +0 -0
- package/dist/cjs/docs/templates/fading-citrus/assets/reactive.svg +0 -3
- package/dist/cjs/docs/templates/fading-citrus/assets/simple.svg +0 -8
- package/dist/cjs/docs/templates/fading-citrus/assets/small.svg +0 -8
- package/dist/esm/docs/templates/fading-citrus/assets/client-server.svg +0 -4
- package/dist/esm/docs/templates/fading-citrus/assets/fast.svg +0 -4
- package/dist/esm/docs/templates/fading-citrus/assets/independent.svg +0 -23
- package/dist/esm/docs/templates/fading-citrus/assets/markup-banner.jpg +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/markup-essentials-training.jpg +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/markup-favicon.jpg +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/markup-favicon.png +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/markup-logo-name.svg +0 -10
- package/dist/esm/docs/templates/fading-citrus/assets/markup-logo-name@2x.png +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/markup-logo.svg +0 -13
- package/dist/esm/docs/templates/fading-citrus/assets/markup-logo@2x.png +0 -0
- package/dist/esm/docs/templates/fading-citrus/assets/reactive.svg +0 -3
- package/dist/esm/docs/templates/fading-citrus/assets/simple.svg +0 -8
- package/dist/esm/docs/templates/fading-citrus/assets/small.svg +0 -8
package/README.md
CHANGED
|
@@ -304,8 +304,10 @@ A template config exports an object:
|
|
|
304
304
|
```js
|
|
305
305
|
export default {
|
|
306
306
|
meta: {},
|
|
307
|
+
site: {},
|
|
307
308
|
markedOptions: {},
|
|
308
309
|
markdownLayouts: {},
|
|
310
|
+
headScripts: {},
|
|
309
311
|
scripts: {},
|
|
310
312
|
theme: {
|
|
311
313
|
light: {},
|
|
@@ -319,8 +321,9 @@ Config from `docs/_template/template.config.js` is merged into the selected temp
|
|
|
319
321
|
Merge behavior:
|
|
320
322
|
|
|
321
323
|
- `markdownLayouts` are shallow-merged by layout name.
|
|
322
|
-
- `scripts` are shallow-merged by script name.
|
|
324
|
+
- `headScripts` and `scripts` are shallow-merged by script name.
|
|
323
325
|
- `meta` is shallow-merged by metadata field.
|
|
326
|
+
- `site` is shallow-merged by site field.
|
|
324
327
|
- `theme.light` and `theme.dark` are shallow-merged by CSS variable name.
|
|
325
328
|
- Other top-level config values use the docs source config value when provided.
|
|
326
329
|
|
|
@@ -336,6 +339,20 @@ export default {
|
|
|
336
339
|
description: 'Documentation for Example.',
|
|
337
340
|
image: '/assets/site-image.jpg',
|
|
338
341
|
},
|
|
342
|
+
site: {
|
|
343
|
+
name: 'Example',
|
|
344
|
+
packageName: '@example/docs',
|
|
345
|
+
repositoryUrl: 'https://github.com/example/docs',
|
|
346
|
+
repositoryLabel: 'Example GitHub repository',
|
|
347
|
+
docsEditUrl: 'https://github.com/example/docs/tree/main/docs',
|
|
348
|
+
footerDescription: 'Documentation for Example.',
|
|
349
|
+
footerGroups: [
|
|
350
|
+
{
|
|
351
|
+
title: 'Learning Resources',
|
|
352
|
+
links: [{ label: 'Documentation', href: '/documentation' }],
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
},
|
|
339
356
|
markdownLayouts: {
|
|
340
357
|
'pricing-cards': pricingCards,
|
|
341
358
|
},
|
|
@@ -350,6 +367,16 @@ export default {
|
|
|
350
367
|
}
|
|
351
368
|
```
|
|
352
369
|
|
|
370
|
+
Common `site` fields:
|
|
371
|
+
|
|
372
|
+
- `name`: display name used by shared layouts.
|
|
373
|
+
- `packageName`: package name used by templates that render install commands.
|
|
374
|
+
- `repositoryUrl` and `repositoryLabel`: repository link and accessible label.
|
|
375
|
+
- `docsEditUrl`: base URL for edit links, usually a repository `docs` folder URL.
|
|
376
|
+
- `navLinks` and `actionLinks`: landing header links.
|
|
377
|
+
- `footerDescription`, `footerGroups`, `socialLinks`, and `copyright`: footer content.
|
|
378
|
+
- `landingHeroVersionHref` and `landingHeroSecondaryLabel`: optional landing hero overrides.
|
|
379
|
+
|
|
353
380
|
## Markdown Layout Syntax
|
|
354
381
|
|
|
355
382
|
The docs renderer extends `marked` with a custom block syntax:
|
|
@@ -602,6 +629,8 @@ export default {
|
|
|
602
629
|
}
|
|
603
630
|
```
|
|
604
631
|
|
|
632
|
+
Use `headScripts` for scripts that must render in `<head>`, such as analytics bootstrap tags. Use `scripts` for scripts that can render near `</body>`, such as interaction handlers.
|
|
633
|
+
|
|
605
634
|
Script definitions:
|
|
606
635
|
|
|
607
636
|
```ts
|
|
@@ -632,12 +661,15 @@ Behavior:
|
|
|
632
661
|
- A function matcher receives the rendered page HTML and returns a boolean.
|
|
633
662
|
- A script can be disabled by setting its registry value to `false` in an extending config.
|
|
634
663
|
|
|
635
|
-
Layouts receive scripts through `props.
|
|
664
|
+
Layouts receive scripts through `props.headScripts` and `props.scripts`. Template layouts must insert them where appropriate.
|
|
636
665
|
|
|
637
666
|
```js
|
|
638
667
|
export default (props) => `
|
|
639
668
|
<!doctype html>
|
|
640
669
|
<html>
|
|
670
|
+
<head>
|
|
671
|
+
${props.headScripts?.join('') || ''}
|
|
672
|
+
</head>
|
|
641
673
|
<body>
|
|
642
674
|
${props.content}
|
|
643
675
|
${props.scripts?.join('') || ''}
|
|
@@ -802,8 +834,12 @@ export default {
|
|
|
802
834
|
markdownLayouts: {
|
|
803
835
|
'pricing-cards': pricingCards,
|
|
804
836
|
},
|
|
837
|
+
headScripts: {
|
|
838
|
+
analytics: () =>
|
|
839
|
+
`<script async src="https://example.com/analytics.js"></script>`,
|
|
840
|
+
},
|
|
805
841
|
scripts: {
|
|
806
|
-
|
|
842
|
+
pageView: {
|
|
807
843
|
match: '<main',
|
|
808
844
|
render: () => `<script>console.log('page viewed')</script>`,
|
|
809
845
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var k=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var w=(o,r)=>k(o,"name",{value:r,configurable:!0});var l=(o,r)=>{for(var t in r)k(o,t,{get:r[t],enumerable:!0})},c=(o,r,t,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of L(r))!m.call(o,n)&&n!==t&&k(o,n,{get:()=>r[n],enumerable:!(d=M(r,n))||d.enumerable});return o};var p=o=>c(k({},"__esModule",{value:!0}),o);var f={};l(f,{createMarkdownLayoutExtension:()=>x});module.exports=p(f);var u=require("./parser.js"),s=require("./renderer.js");const x=w(({marked:o,handlers:r={},renderMarkdown:t,templateConfig:d})=>({extensions:[{name:"markdownLayout",level:"block",start(n){return n.match(/^::: layout /m)?.index},tokenizer(n){const a=(0,u.readLayoutBlock)(n);if(a)return{...(0,u.parseLayoutBlock)(a),type:"markdownLayout",raw:a}},renderer(n){const a=n,i={marked:o,templateConfig:d,renderMarkdown(e){return t?t(e):o.parse(e)},renderDefault(e){return(0,s.renderDefaultMarkdownLayout)(e,i)},renderParts(e){return e.items.map(y=>({...y,html:i.renderMarkdown(y.body)}))}};return(0,s.renderMarkdownLayout)(a,i,r)}}]}),"createMarkdownLayoutExtension");0&&(module.exports={createMarkdownLayoutExtension});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var r=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var y=(t,o,a,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of i(o))!u.call(t,e)&&e!==a&&r(t,e,{get:()=>o[e],enumerable:!(n=d(o,e))||n.enumerable});return t};var k=t=>y(r({},"__esModule",{value:!0}),t);var p={};module.exports=k(p);
|
package/dist/cjs/docs/run.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var ge=Object.create;var C=Object.defineProperty;var ye=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var ve=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var m=(e,t)=>C(e,"name",{value:t,configurable:!0});var De=(e,t)=>{for(var r in t)C(e,r,{get:t[r],enumerable:!0})},Q=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of we(t))!Se.call(e,n)&&n!==r&&C(e,n,{get:()=>t[n],enumerable:!(a=ye(t,n))||a.enumerable});return e};var v=(e,t,r)=>(r=e!=null?ge(ve(e)):{},Q(t||!e||!e.__esModule?C(r,"default",{value:e,enumerable:!0}):r,e)),be=e=>Q(C({},"__esModule",{value:!0}),e);var Ue={};De(Ue,{buildDocs:()=>Ne});module.exports=be(Ue);const ze={};var re=require("marked"),c=require("fs/promises"),o=v(require("path"),1),oe=v(require("front-matter"),1),ae=v(require("isomorphic-dompurify"),1),ne=require("marked-highlight"),_=v(require("highlight.js"),1),ie=v(require("./templates/default.template.js"),1),le=v(require("./renderer/index.js"),1),ce=require("./markdown-layout/index.js"),me=v(require("clean-css"),1),ue=v(require("html-minifier"),1),X=v(require("@putout/minify"),1),P=require("url"),f=v(require("fs"),1);let V,A="";const Y=new me.default({inline:["none"]}),R=new Map;R.set("default",ie.default);let W;const Z=m((e,t)=>t===!1?!1:t===void 0?e:e===!1||e===void 0?t:{...e,...t},"mergeThemeMode"),$e=m((e,t)=>{if(!(!e&&!t))return{light:Z(e?.light,t?.light),dark:Z(e?.dark,t?.dark)}},"mergeTheme"),xe=m((e,t)=>({...e,...t,markdownLayouts:{...e.markdownLayouts,...t.markdownLayouts},headScripts:{...e.headScripts,...t.headScripts},scripts:{...e.scripts,...t.scripts},theme:$e(e.theme,t.theme),meta:{...e.meta,...t.meta},site:{...e.site,...t.site}}),"mergeTemplateConfig"),Pe=m((e,t)=>{if(typeof e=="function")return!0;const{match:r}=e;return r?typeof r=="string"?t.includes(r):Array.isArray(r)?r.some(a=>t.includes(a)):r instanceof RegExp?r.test(t):r(t):!0},"scriptMatches"),ee=m((e,t)=>e?Object.values(e).filter(r=>r!==!1).filter(r=>Pe(r,t)).map(r=>typeof r=="function"?r():r.render()):[],"renderPageScripts"),G=m((e,t)=>{const r=Object.entries(t).filter(([a])=>a.startsWith("--")).map(([a,n])=>` ${a}: ${n};`).join(`
|
|
2
2
|
`);return r?`${e} {
|
|
3
3
|
${r}
|
|
4
4
|
}`:""},"renderThemeBlock"),ke=m(e=>{if(!e)return"";const t=e.light===!1,r=e.dark===!1,a=e.light===!1?void 0:e.light,n=r?void 0:e.dark,u=a||n;return u?[G(":root",u),n&&!t?`@media (prefers-color-scheme: dark) {
|
|
@@ -7,10 +7,10 @@ ${G(" :root",n)}
|
|
|
7
7
|
.site-logo-dark { display: block; }`:"",r&&a?`.site-logo-light { display: block; }
|
|
8
8
|
.site-logo-dark { display: none; }`:""].filter(Boolean).join(`
|
|
9
9
|
|
|
10
|
-
`):""},"renderThemeStylesheet"),Te=m((e="")=>String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),"escapeXML"),Me=m((e="")=>e.replace(/```[\s\S]*?```/g," ").replace(/`([^`]+)`/g,"$1").replace(/!\[[^\]]*]\([^)]*\)/g," ").replace(/\[([^\]]+)]\([^)]*\)/g,"$1").replace(/^#{1,6}\s+/gm,"").replace(/^---+$/gm," ").replace(/[>*_~]/g,"").replace(/\s+/g," ").trim(),"stripMarkdown"),je=m(e=>e==="/index.html"?"/":e.replace(/\/index\.html$/,"/").replace(/\.html$/,"").replace(/\/+/g,"/"),"pagePathToUrlPath"),
|
|
10
|
+
`):""},"renderThemeStylesheet"),Te=m((e="")=>String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"),"escapeXML"),Me=m((e="")=>e.replace(/```[\s\S]*?```/g," ").replace(/`([^`]+)`/g,"$1").replace(/!\[[^\]]*]\([^)]*\)/g," ").replace(/\[([^\]]+)]\([^)]*\)/g,"$1").replace(/^#{1,6}\s+/gm,"").replace(/^---+$/gm," ").replace(/[>*_~]/g,"").replace(/\s+/g," ").trim(),"stripMarkdown"),je=m(e=>e==="/index.html"?"/":e.replace(/\/index\.html$/,"/").replace(/\.html$/,"").replace(/\/+/g,"/"),"pagePathToUrlPath"),te=m((e,t)=>e?`${e.replace(/\/$/,"")}${t==="/"?"/":t}`:t,"canonicalUrl"),Ce=m(async(e,t)=>f.default.existsSync(e)?(await(0,c.mkdir)(o.default.dirname(t),{recursive:!0}),await(0,c.cp)(e,t),!0):!1,"copyIfExists"),Fe=m(async e=>{const t=o.default.resolve(e,"logo.svg");f.default.existsSync(t)&&await Promise.all(["logo.light.svg","logo.dark.svg"].map(async r=>{const a=o.default.resolve(e,r);f.default.existsSync(a)||await(0,c.cp)(t,a)}))},"ensureLogoModeAssets"),Ge=m(e=>{const t={sitemap:!0,robots:!0,llms:!0,llmsFull:!0,netlify:!1};return e===!1?{sitemap:!1,robots:!1,llms:!1,llmsFull:!1,netlify:!1}:e===!0||e===void 0?t:{...t,...e}},"normalizeGeneratedFilesConfig"),Le=m((e,t)=>{if(!t)return"";const r=new Date().toISOString().slice(0,10);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
11
11
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
12
12
|
${e.map(n=>{const u=n.urlPath==="/"?"1.0":"0.8";return` <url>
|
|
13
|
-
<loc>${Te(
|
|
13
|
+
<loc>${Te(te(t,n.urlPath))}</loc>
|
|
14
14
|
<lastmod>${r}</lastmod>
|
|
15
15
|
<changefreq>weekly</changefreq>
|
|
16
16
|
<priority>${u}</priority>
|
|
@@ -35,7 +35,7 @@ This file is generated at build time from the Markdown documentation. Use it to
|
|
|
35
35
|
|
|
36
36
|
${e.map(r=>`## ${r.title}
|
|
37
37
|
|
|
38
|
-
URL: ${
|
|
38
|
+
URL: ${te(t,r.urlPath)}
|
|
39
39
|
Source: docs/${r.sourcePath}
|
|
40
40
|
Description: ${r.description}
|
|
41
41
|
|
|
@@ -75,4 +75,4 @@ for = "/robots.txt"
|
|
|
75
75
|
[headers.values]
|
|
76
76
|
Content-Type = "text/plain; charset=utf-8"
|
|
77
77
|
Cache-Control = "public, max-age=0, must-revalidate"
|
|
78
|
-
`,"generateNetlifyToml")
|
|
78
|
+
`,"generateNetlifyToml"),x=m(async(e,t,r,a)=>{if(await Ce(e,t))return;const n=r();if(!n){a&&console.warn(a);return}await(0,c.mkdir)(o.default.dirname(t),{recursive:!0}),await(0,c.writeFile)(t,n)},"writeGeneratedFile"),_e=m(async({docsDir:e,docsSiteDir:t,pages:r,siteUrl:a,publicDir:n,generatedFiles:u})=>{u.sitemap&&await x(o.default.resolve(e,"sitemap.xml"),o.default.resolve(t,"sitemap.xml"),()=>Le(r,a),"Skipping generated sitemap.xml because buildDocs({ siteUrl }) is not set."),u.robots&&await x(o.default.resolve(e,"robots.txt"),o.default.resolve(t,"robots.txt"),()=>Ee(a)),u.llms&&await x(o.default.resolve(e,"llms.txt"),o.default.resolve(t,"llms.txt"),()=>Oe(r)),u.llmsFull&&await x(o.default.resolve(e,"llms-full.txt"),o.default.resolve(t,"llms-full.txt"),()=>Ae(r,a)),u.netlify&&(await x(o.default.resolve(e,"_redirects"),o.default.resolve(t,"_redirects"),()=>Re(r,u)),await x(o.default.resolve(e,"netlify.toml"),o.default.resolve(t,"netlify.toml"),()=>We(n&&o.default.basename(n))))},"writeGeneratedDocsFiles"),se=m((e={},t,r)=>{const a=new re.Marked((0,ne.markedHighlight)({langPrefix:"hljs language-",highlight(n,u){const h=_.default.getLanguage(u)?u:"plaintext";return _.default.highlight(n,{language:h}).value}}));return a.use({renderer:le.default}),a.use((0,ce.createMarkdownLayoutExtension)({marked:a,handlers:e.markdownLayouts,renderMarkdown:r,templateConfig:e})),e.markedOptions&&a.use(e.markedOptions),t&&a.use(t),a},"createBaseMarked"),Be=m((e={},t,r)=>{const a=se(e,t),n=m(h=>a.parse(h),"renderMarkdown"),u=se(e,t,n);return u.use({hooks:{postprocess(h){const{layout:w="default",...k}=W.attributes,T=ee(e.headScripts,h),M=ee(e.scripts,h);h=ae.default.sanitize(h);const b=[...h.matchAll(/<h([0-6])\sid="[^"]+".*?>.*?<a\s+href="([^"]+)".*?>([\s\S]*?)<\/a><\/h\1>/gm)].map(p=>({path:p[2],label:p[3].replace(/<[^>]+>/g,"").replace(/\s+/g," ").trim(),level:p[1]}));return R.get(w)?.({...k,content:h,siteMap:W.siteMap,tableOfContent:b,projectMeta:V,renderMarkdown:n,headScripts:T,scripts:M,themeStylesheet:e.theme?`/stylesheets/theme.css?v=${A}`:void 0,cacheKey:A,siteUrl:r,templateConfig:e})||h}}}),u},"createMarked"),S=m(async e=>{const t=await(0,c.readdir)(e),r=[];for(const a of t){const n=o.default.extname(a);/^[._]/.test(a)||(n?r.push(o.default.join(e,a)):/(stylesheets|assets|scripts)/.test(a)||r.push(...await S(o.default.join(e,a))))}return r},"traverseDirectory"),Ne=m(async({srcDir:e,publicDir:t,markedOptions:r,template:a,siteUrl:n,generatedFiles:u}={})=>{A=Date.now().toString(36);try{const s=o.default.resolve(process.cwd(),"package.json");f.default.existsSync(s)&&(V=JSON.parse(await(0,c.readFile)(s,"utf-8")))}catch(s){console.warn("Failed to load project package.json metadata",s)}const h=m(()=>{try{return __dirname}catch{return o.default.dirname((0,P.fileURLToPath)(ze.url))}},"getDirname"),w=a?o.default.resolve(h(),"templates",a):null,k=w?o.default.resolve(w,"assets"):null,T=w?o.default.resolve(w,"stylesheets"):null,M=w?o.default.resolve(w,"layouts"):null;let b={};if(w)try{let s=o.default.resolve(w,"template.config.js");if(f.default.existsSync(s)||(s=s.replace(/\.js$/,".ts")),f.default.existsSync(s)){const i=await import((0,P.pathToFileURL)(s).href);b=i.default||i}}catch(s){console.error(`Failed to load template config for ${a}`,s)}const p=e??o.default.resolve(process.cwd(),"docs"),d=t??o.default.resolve(process.cwd(),"website"),pe=Ge(u),D=o.default.resolve(p,"_template"),B=o.default.resolve(D,"assets"),N=o.default.resolve(D,"stylesheets"),U=o.default.resolve(D,"scripts"),z=o.default.resolve(D,"layouts"),q=o.default.resolve(p,"_layouts"),F=o.default.resolve(p,"assets"),H=o.default.resolve(p,"stylesheets"),L=o.default.resolve(p,"scripts");try{let s=o.default.resolve(D,"template.config.js");if(f.default.existsSync(s)||(s=s.replace(/\.js$/,".ts")),f.default.existsSync(s)){const i=await import((0,P.pathToFileURL)(s).href),l=i.default||i;b=xe(b,l)}}catch(s){console.error("Failed to load docs _template config",s)}const fe=Be(b,r,n);if(await(0,c.mkdir)(d,{recursive:!0}),k&&f.default.existsSync(k))try{await(0,c.cp)(k,F.replace(p,d),{recursive:!0})}catch(s){console.warn(s)}if(f.default.existsSync(F))try{await(0,c.cp)(F,F.replace(p,d),{recursive:!0})}catch(s){console.warn(s)}if(f.default.existsSync(B))try{await(0,c.cp)(B,o.default.resolve(d,"assets"),{recursive:!0})}catch(s){console.warn(s)}await Fe(o.default.resolve(d,"assets"));try{const s=new Set;if(T&&f.default.existsSync(T)&&(await S(T)).forEach(l=>s.add(l)),f.default.existsSync(H)&&(await S(H)).forEach(l=>s.add(l)),f.default.existsSync(N)&&(await S(N)).forEach(l=>s.add(l)),s.size){await(0,c.mkdir)(o.default.join(d,"stylesheets"),{recursive:!0});for(const l of s){const g=await(0,c.readFile)(l,"utf-8"),y=Y.minify(g);y.errors.length&&y.errors.forEach(console.error);const j=l.startsWith(D)?l.replace(D,d):l.startsWith(p)?l.replace(p,d):o.default.join(d,"stylesheets",o.default.basename(l));await(0,c.writeFile)(j,y.styles??g)}}const i=ke(b.theme);if(i){const l=Y.minify(i);l.errors.length&&l.errors.forEach(console.error),await(0,c.mkdir)(o.default.join(d,"stylesheets"),{recursive:!0}),await(0,c.writeFile)(o.default.join(d,"stylesheets","theme.css"),l.styles??i)}}catch(s){console.error(s)}if(f.default.existsSync(L))try{const s=await S(L);s.length&&await(0,c.mkdir)(L.replace(p,d),{recursive:!0});for(const i of s)try{const l=await(0,c.readFile)(i,"utf-8");await(0,c.writeFile)(i.replace(p,d),X.minify(l))}catch(l){console.error(l)}}catch(s){console.warn(s)}if(f.default.existsSync(U))try{const s=await S(U);s.length&&await(0,c.mkdir)(o.default.join(d,"scripts"),{recursive:!0});for(const i of s)try{const l=await(0,c.readFile)(i,"utf-8");await(0,c.writeFile)(i.replace(D,d),X.minify(l))}catch(l){console.error(l)}}catch(s){console.warn(s)}try{const s=new Map;M&&f.default.existsSync(M)&&(await S(M)).forEach(i=>{/\.(j|t)s$/.test(i)&&s.set(o.default.basename(i).replace(/\.(j|t)s$/,""),i)}),f.default.existsSync(q)&&(await S(q)).forEach(i=>{/\.(j|t)s$/.test(i)&&s.set(o.default.basename(i).replace(/\.(j|t)s$/,""),i)}),f.default.existsSync(z)&&(await S(z)).forEach(i=>{/\.(j|t)s$/.test(i)&&s.set(o.default.basename(i).replace(/\.(j|t)s$/,""),i)});for(const[i,l]of s.entries()){const g=await import((0,P.pathToFileURL)(l).href);R.set(i,g.default)}}catch(s){console.error("Template import failed",s)}const de=await S(p),I=new Map,J=(await Promise.all(de.filter(s=>s.endsWith(".md")).map(async s=>{const i=await(0,c.readFile)(s,"utf-8");return{filePath:s,...(0,oe.default)(i)}}))).sort((s,i)=>(s.attributes.order??0)-(i.attributes.order??0)).map(({attributes:s,body:i,filePath:l})=>{const g=l.replace(p,"").replace(/\.md/,".html"),y=l.replace(p,d).replace(".md",".html"),j=y.replace(o.default.basename(y),""),E=o.default.basename(g)||"/",he=g.replace(E,"").replace(/\/$/,"");let $=I;he.split("/").filter(Boolean).forEach(O=>{$.has(O)||$.set(O,new Map),$=$.get(O)});const K={...s,path:g};return $.has(E)||$.set(E,K),{attributes:K,fileWebsitePath:y,fileDirWebsitePath:j,body:i,sourcePath:o.default.relative(p,l),siteMap:I}});for(const{attributes:s,body:i,fileDirWebsitePath:l,fileWebsitePath:g,siteMap:y}of J){W={attributes:s,siteMap:y};const j=await fe.parse(i);await(0,c.mkdir)(l,{recursive:!0}),await(0,c.writeFile)(g,ue.default.minify(j,{includeAutoGeneratedTags:!0,removeAttributeQuotes:!0,removeComments:!0,removeRedundantAttributes:!0,removeScriptTypeAttributes:!0,removeStyleLinkTypeAttributes:!0,sortClassName:!0,useShortDoctype:!0,collapseWhitespace:!0,minifyJS:!0,minifyCSS:!0}))}await _e({docsDir:p,docsSiteDir:d,pages:J.map(({attributes:s,body:i,sourcePath:l})=>{const g=je(String(s.path)),y=Me(i);return{sourcePath:l,urlPath:g,title:String(s.title||s.name||"").trim()||"Documentation",name:String(s.name||s.title||"").trim()||"Documentation",description:String(s.description||"").trim()||y.slice(0,156)||"Documentation page.",order:Number(s.order??999),summary:y.slice(0,320)}}),siteUrl:n,publicDir:d,generatedFiles:pe})},"buildDocs");0&&(module.exports={buildDocs});
|
|
@@ -121,7 +121,7 @@ docs/_template/assets/logo.svg
|
|
|
121
121
|
|
|
122
122
|
The footer also uses social icons from `/assets/*.svg`.
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
Header and footer links are driven by `site` config. Override `_header.js`, `_footer.js`, or the full page layouts only when the HTML structure itself needs to change.
|
|
125
125
|
|
|
126
126
|
## Metadata
|
|
127
127
|
|
|
@@ -167,6 +167,57 @@ export default {
|
|
|
167
167
|
|
|
168
168
|
Override `_head-meta.js` in `docs/_template/layouts` only when the generated metadata shape itself needs to change.
|
|
169
169
|
|
|
170
|
+
## Site Identity And Links
|
|
171
|
+
|
|
172
|
+
The template is generic. Product-specific labels, repository links, footer links, and edit links should live in `docs/_template/template.config.js` under `site`.
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
// docs/_template/template.config.js
|
|
176
|
+
export default {
|
|
177
|
+
site: {
|
|
178
|
+
name: 'Example',
|
|
179
|
+
packageName: '@example/project',
|
|
180
|
+
repositoryUrl: 'https://github.com/example/project',
|
|
181
|
+
repositoryLabel: 'Example GitHub repository',
|
|
182
|
+
docsEditUrl: 'https://github.com/example/project/tree/main/docs',
|
|
183
|
+
navLinks: [
|
|
184
|
+
{ label: 'Features', href: '/#features' },
|
|
185
|
+
{ label: 'Code', href: '/#code' },
|
|
186
|
+
{ label: 'Install', href: '/#install' },
|
|
187
|
+
],
|
|
188
|
+
actionLinks: [
|
|
189
|
+
{
|
|
190
|
+
label: 'Documentation',
|
|
191
|
+
href: '/documentation',
|
|
192
|
+
className: 'btn-primary',
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
footerDescription: 'Documentation for Example.',
|
|
196
|
+
footerGroups: [
|
|
197
|
+
{
|
|
198
|
+
title: 'Learning Resources',
|
|
199
|
+
links: [{ label: 'Documentation', href: '/documentation' }],
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
socialLinks: [
|
|
203
|
+
{
|
|
204
|
+
name: 'GitHub',
|
|
205
|
+
href: 'https://github.com/example',
|
|
206
|
+
icon: '/assets/github.svg',
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
copyright: `Copyright © ${new Date().getFullYear()} Example.`,
|
|
210
|
+
},
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Relevant fields:
|
|
215
|
+
|
|
216
|
+
- `repositoryUrl` powers the header GitHub links and the docs version badge.
|
|
217
|
+
- `docsEditUrl` powers the “edit this doc” link. If omitted, that link is hidden.
|
|
218
|
+
- `packageName` powers the default landing hero install command.
|
|
219
|
+
- `navLinks`, `actionLinks`, `footerGroups`, and `socialLinks` replace the template defaults.
|
|
220
|
+
|
|
170
221
|
## Markdown Layout Handlers
|
|
171
222
|
|
|
172
223
|
`template.config.js` registers these Markdown layout handlers:
|
|
@@ -227,7 +278,8 @@ Supported layout options:
|
|
|
227
278
|
- `title2`: second headline line.
|
|
228
279
|
- `primaryHref`: primary CTA URL. Defaults to `/documentation/get-started`.
|
|
229
280
|
- `primaryLabel`: primary CTA label. Defaults to `Get Started`.
|
|
230
|
-
- `secondaryLabel`: secondary CTA label. Defaults to `npm i
|
|
281
|
+
- `secondaryLabel`: secondary CTA label. Defaults to `site.landingHeroSecondaryLabel`, then `npm i ${site.packageName}`, then `Install`.
|
|
282
|
+
- `versionHref`: version badge URL. Defaults to `site.landingHeroVersionHref`, then `site.repositoryUrl`.
|
|
231
283
|
|
|
232
284
|
Supported parts:
|
|
233
285
|
|
|
@@ -238,7 +290,7 @@ Supported parts:
|
|
|
238
290
|
Notes:
|
|
239
291
|
|
|
240
292
|
- The secondary CTA currently points to `#install`.
|
|
241
|
-
- The version badge
|
|
293
|
+
- The version badge links to `versionHref`, `site.landingHeroVersionHref`, or `site.repositoryUrl`.
|
|
242
294
|
|
|
243
295
|
## `landing-ecosystem`
|
|
244
296
|
|
|
@@ -579,9 +631,7 @@ docs/_template/template.config.js
|
|
|
579
631
|
|
|
580
632
|
## Assets
|
|
581
633
|
|
|
582
|
-
The template includes
|
|
583
|
-
|
|
584
|
-
Generic or shared assets:
|
|
634
|
+
The template includes only generic/shared assets. Product-specific logos, banners, screenshots, and icons should live in the docs source under `docs/_template/assets`.
|
|
585
635
|
|
|
586
636
|
- `logo.svg`: compatibility fallback for the main site logo.
|
|
587
637
|
- `logo.light.svg`: preferred logo on light backgrounds.
|
|
@@ -589,19 +639,6 @@ Generic or shared assets:
|
|
|
589
639
|
- `favicon/*`: default favicons.
|
|
590
640
|
- social icons: `medium2.svg`, `facebook.svg`, `instagram.svg`, `reddit.svg`, `twitter.svg`, `youtube.svg`.
|
|
591
641
|
|
|
592
|
-
Markup-specific assets still present:
|
|
593
|
-
|
|
594
|
-
- `markup-banner.jpg`
|
|
595
|
-
- `markup-essentials-training.jpg`
|
|
596
|
-
- `markup-favicon.*`
|
|
597
|
-
- `markup-logo*`
|
|
598
|
-
- `client-server.svg`
|
|
599
|
-
- `fast.svg`
|
|
600
|
-
- `independent.svg`
|
|
601
|
-
- `reactive.svg`
|
|
602
|
-
- `simple.svg`
|
|
603
|
-
- `small.svg`
|
|
604
|
-
|
|
605
642
|
Override assets from a docs project by adding files at the same target path:
|
|
606
643
|
|
|
607
644
|
```txt
|
|
@@ -637,7 +674,7 @@ The landing and documentation stylesheets import or rely on the shared styles as
|
|
|
637
674
|
|
|
638
675
|
## Scripts
|
|
639
676
|
|
|
640
|
-
Template scripts are registered by marker
|
|
677
|
+
Template scripts are registered by marker. The template renders `headScripts` inside `<head>` and `scripts` before `</body>`.
|
|
641
678
|
|
|
642
679
|
```js
|
|
643
680
|
scripts: {
|
|
@@ -732,18 +769,6 @@ export default {
|
|
|
732
769
|
}
|
|
733
770
|
```
|
|
734
771
|
|
|
735
|
-
## Known Template-Specific Assumptions
|
|
736
|
-
|
|
737
|
-
Some template internals are still Markup or Before Semicolon oriented:
|
|
738
|
-
|
|
739
|
-
- `_header.js` has Markup-oriented GitHub and documentation links.
|
|
740
|
-
- `_footer.js` has Before Semicolon social links, footer copy, and learning links.
|
|
741
|
-
- `document.js` builds edit links against the Markup GitHub docs path.
|
|
742
|
-
- Some landing layout handlers contain default labels or links aimed at Markup docs.
|
|
743
|
-
- Several assets are Markup-specific.
|
|
744
|
-
|
|
745
|
-
These are template defaults, not builder requirements. Override them from `docs/_template` for another documentation site.
|
|
746
|
-
|
|
747
772
|
## Minimal Landing Page
|
|
748
773
|
|
|
749
774
|
````md
|
|
@@ -1,77 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
name: 'Facebook',
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
link: 'https://www.instagram.com/before_semicolon_/',
|
|
14
|
-
icon: 'assets/instagram.svg',
|
|
15
|
-
name: 'Instagram',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
link: 'https://www.reddit.com/r/beforesemicolon/',
|
|
19
|
-
icon: 'assets/reddit.svg',
|
|
20
|
-
name: 'Reddit',
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
link: 'https://twitter.com/BeforeSemicolon',
|
|
24
|
-
icon: 'assets/twitter.svg',
|
|
25
|
-
name: 'Twitter',
|
|
26
|
-
},
|
|
1
|
+
import {
|
|
2
|
+
escapeAttribute,
|
|
3
|
+
escapeHTML,
|
|
4
|
+
linkAttrs,
|
|
5
|
+
siteConfig,
|
|
6
|
+
siteName,
|
|
7
|
+
} from './_layout-utils.js'
|
|
8
|
+
|
|
9
|
+
const defaultFooterGroups = [
|
|
27
10
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
name: 'YouTube',
|
|
11
|
+
title: 'Documentation',
|
|
12
|
+
links: [{ label: 'Docs', href: '/documentation' }],
|
|
31
13
|
},
|
|
32
14
|
]
|
|
33
15
|
|
|
34
|
-
|
|
35
|
-
const siteName =
|
|
36
|
-
props.projectMeta?.name || props.name || props.title || 'Documentation'
|
|
37
|
-
const logo = `
|
|
16
|
+
const renderLogo = (name) => `
|
|
38
17
|
<span class="site-logo-pair">
|
|
39
|
-
<img class="site-logo site-logo-dark" src="/assets/logo.dark.svg" alt="${
|
|
18
|
+
<img class="site-logo site-logo-dark" src="/assets/logo.dark.svg" alt="${escapeAttribute(name)} logo" width="100" height="30" />
|
|
40
19
|
<img class="site-logo site-logo-light" src="/assets/logo.light.svg" alt="" width="100" height="30" aria-hidden="true" />
|
|
41
20
|
</span>`
|
|
42
21
|
|
|
43
|
-
|
|
44
|
-
<footer class="site-footer">
|
|
45
|
-
<div class="footer-inner wrapper">
|
|
46
|
-
<div class="footer-brand">
|
|
47
|
-
${logo}
|
|
48
|
-
<p>A reactive HTML templating system for building dynamic UIs with pure JavaScript. No build step. No virtual DOM.</p>
|
|
49
|
-
</div>
|
|
22
|
+
const renderFooterGroup = (group) => `
|
|
50
23
|
<ul class="footer-links">
|
|
51
|
-
<li><h4
|
|
52
|
-
|
|
53
|
-
<li><a target="_blank" rel="noopener" href="https://www.youtube.com/watch?v=mIr2XglV5nQ&list=PLpWvGP6yhJUgWNiz25vj__CArY9Z0O6ke&index=1">Essentials Training</a></li>
|
|
54
|
-
</ul>
|
|
55
|
-
<ul class="footer-links">
|
|
56
|
-
<li><h4>About <em>Before Semicolon</em></h4></li>
|
|
57
|
-
<li><a href="https://github.com/beforesemicolon" rel="noopener" target="_blank">Open Source</a></li>
|
|
58
|
-
<li><a href="https://beforesemicolon.com/" rel="noopener" target="_blank">Website</a></li>
|
|
59
|
-
<li><a href="https://medium.com/before-semicolon" rel="noopener" target="_blank">Blog</a></li>
|
|
60
|
-
<li><a href="https://www.youtube.com/channel/UCrU33aw1k9BqTIq2yKXrmBw" rel="noopener" target="_blank">YouTube Channel</a></li>
|
|
61
|
-
</ul>
|
|
62
|
-
<div class="footer-social" aria-label="social-media">
|
|
63
|
-
${social
|
|
24
|
+
<li><h4>${escapeHTML(group.title)}</h4></li>
|
|
25
|
+
${(group.links || [])
|
|
64
26
|
.map(
|
|
65
|
-
(
|
|
66
|
-
|
|
67
|
-
<span class="footer-social-icon" style="--icon: url('/${s.icon}')" aria-hidden="true"></span>
|
|
68
|
-
</a>
|
|
69
|
-
`
|
|
27
|
+
(link) =>
|
|
28
|
+
`<li><a href="${escapeAttribute(link.href)}"${linkAttrs(link)}>${escapeHTML(link.label)}</a></li>`
|
|
70
29
|
)
|
|
71
30
|
.join('')}
|
|
31
|
+
</ul>`
|
|
32
|
+
|
|
33
|
+
const renderSocialLink = (link) => `
|
|
34
|
+
<a href="${escapeAttribute(link.href)}"${linkAttrs(link)} aria-label="${escapeAttribute(link.name)}">
|
|
35
|
+
<span class="footer-social-icon" style="--icon: url('${escapeAttribute(link.icon)}')" aria-hidden="true"></span>
|
|
36
|
+
</a>`
|
|
37
|
+
|
|
38
|
+
export default (props = {}) => {
|
|
39
|
+
const site = siteConfig(props)
|
|
40
|
+
const name = siteName(props)
|
|
41
|
+
const description =
|
|
42
|
+
site.footerDescription ||
|
|
43
|
+
props.description ||
|
|
44
|
+
'Documentation, guides, and references for this project.'
|
|
45
|
+
const footerGroups = site.footerGroups || defaultFooterGroups
|
|
46
|
+
const socialLinks = site.socialLinks || []
|
|
47
|
+
const copyright =
|
|
48
|
+
site.copyright ||
|
|
49
|
+
`Copyright © ${new Date().getFullYear()} ${escapeHTML(name)}. All rights reserved.`
|
|
50
|
+
|
|
51
|
+
return `
|
|
52
|
+
<footer class="site-footer">
|
|
53
|
+
<div class="footer-inner wrapper">
|
|
54
|
+
<div class="footer-brand">
|
|
55
|
+
${renderLogo(name)}
|
|
56
|
+
<p>${escapeHTML(description)}</p>
|
|
72
57
|
</div>
|
|
58
|
+
${footerGroups.map(renderFooterGroup).join('')}
|
|
59
|
+
${
|
|
60
|
+
socialLinks.length
|
|
61
|
+
? `<div class="footer-social" aria-label="social-media">
|
|
62
|
+
${socialLinks.map(renderSocialLink).join('')}
|
|
63
|
+
</div>`
|
|
64
|
+
: ''
|
|
65
|
+
}
|
|
73
66
|
<div class="footer-credit">
|
|
74
|
-
<span
|
|
67
|
+
<span>${copyright}</span>
|
|
75
68
|
</div>
|
|
76
69
|
</div>
|
|
77
70
|
</footer>
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/* global process */
|
|
2
|
-
const isDev = process.env.NODE_ENV === 'development'
|
|
3
|
-
|
|
4
1
|
const fallbackSiteUrl = 'https://beforesemicolon.com'
|
|
5
2
|
const fallbackSiteName = 'Before Semicolon'
|
|
6
3
|
const fallbackTitle = 'Before Semicolon Documentation'
|
|
@@ -234,18 +231,5 @@ export default (props = {}) => {
|
|
|
234
231
|
<link rel="stylesheet" href="/stylesheets/github-dark.hightlighter.css${cacheKey}">
|
|
235
232
|
${jsonScript(pageJson({ ...props, siteUrl, siteName, defaultImage, title, description }))}
|
|
236
233
|
${jsonScript(breadcrumbJson({ siteUrl, title, path: props.path }))}
|
|
237
|
-
${
|
|
238
|
-
isDev
|
|
239
|
-
? ''
|
|
240
|
-
: `<!-- Google tag (gtag.js) -->
|
|
241
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-N3MXGDP5PS"></script>
|
|
242
|
-
<script>
|
|
243
|
-
window.dataLayer = window.dataLayer || [];
|
|
244
|
-
function gtag(){dataLayer.push(arguments);}
|
|
245
|
-
gtag('js', new Date());
|
|
246
|
-
|
|
247
|
-
gtag('config', 'G-N3MXGDP5PS');
|
|
248
|
-
</script>`
|
|
249
|
-
}
|
|
250
234
|
`
|
|
251
235
|
}
|
|
@@ -1,42 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import {
|
|
2
|
+
escapeAttribute,
|
|
3
|
+
escapeHTML,
|
|
4
|
+
linkAttrs,
|
|
5
|
+
siteConfig,
|
|
6
|
+
siteName,
|
|
7
|
+
} from './_layout-utils.js'
|
|
8
|
+
|
|
9
|
+
const githubIcon =
|
|
10
|
+
'<svg aria-hidden="true" viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>'
|
|
11
|
+
|
|
12
|
+
const renderLogo = (name, width = 90, height = 27) => `
|
|
6
13
|
<span class="site-logo-pair">
|
|
7
|
-
<img class="site-logo site-logo-dark" src="/assets/logo.dark.svg" alt="${
|
|
8
|
-
<img class="site-logo site-logo-light" src="/assets/logo.light.svg" alt="" width="
|
|
14
|
+
<img class="site-logo site-logo-dark" src="/assets/logo.dark.svg" alt="${escapeAttribute(name)} logo" width="${width}" height="${height}" />
|
|
15
|
+
<img class="site-logo site-logo-light" src="/assets/logo.light.svg" alt="" width="${width}" height="${height}" aria-hidden="true" />
|
|
9
16
|
</span>`
|
|
10
17
|
|
|
18
|
+
const defaultNavLinks = [
|
|
19
|
+
{ label: 'Features', href: '/#features' },
|
|
20
|
+
{ label: 'Code', href: '/#code' },
|
|
21
|
+
{ label: 'Install', href: '/#install' },
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
const defaultActionLinks = [
|
|
25
|
+
{
|
|
26
|
+
label: 'Documentation',
|
|
27
|
+
href: '/documentation',
|
|
28
|
+
className: 'btn-primary',
|
|
29
|
+
},
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
const renderTextLink = (link) => `
|
|
33
|
+
<a href="${escapeAttribute(link.href)}"${linkAttrs(link)}${link.className ? ` class="${escapeAttribute(link.className)}"` : ''}${link.ariaLabel ? ` aria-label="${escapeAttribute(link.ariaLabel)}"` : ''}>${escapeHTML(link.label)}</a>`
|
|
34
|
+
|
|
35
|
+
const renderRepositoryLink = (props, docs = false) => {
|
|
36
|
+
const site = siteConfig(props)
|
|
37
|
+
|
|
38
|
+
if (!site.repositoryUrl) return ''
|
|
39
|
+
|
|
40
|
+
const label = site.repositoryLabel || `${siteName(props)} repository`
|
|
41
|
+
|
|
42
|
+
if (docs) {
|
|
43
|
+
return `
|
|
44
|
+
<a href="${escapeAttribute(site.repositoryUrl)}" target="_blank" rel="noopener" aria-label="${escapeAttribute(label)}" class="github-link docs-github-link">
|
|
45
|
+
<span>v${escapeHTML(props.projectMeta?.version || '')}</span>
|
|
46
|
+
${githubIcon}
|
|
47
|
+
</a>`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return `
|
|
51
|
+
<a href="${escapeAttribute(site.repositoryUrl)}" target="_blank" rel="noopener" aria-label="${escapeAttribute(label)}" class="github-link">
|
|
52
|
+
${githubIcon}
|
|
53
|
+
</a>`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default (props = {}) => {
|
|
57
|
+
const isDocs = props.path?.startsWith('/documentation')
|
|
58
|
+
const name = siteName(props)
|
|
59
|
+
const site = siteConfig(props)
|
|
60
|
+
const navLinks = site.navLinks || defaultNavLinks
|
|
61
|
+
const actionLinks = site.actionLinks || defaultActionLinks
|
|
62
|
+
|
|
11
63
|
return `
|
|
12
64
|
<header class="site-header">
|
|
13
65
|
<div class="header-inner wrapper">
|
|
14
66
|
<h1>
|
|
15
|
-
<a href="/" aria-label="${
|
|
16
|
-
${
|
|
67
|
+
<a href="/" aria-label="${escapeAttribute(name)} home">
|
|
68
|
+
${renderLogo(name)}
|
|
17
69
|
</a>
|
|
18
70
|
</h1>
|
|
19
71
|
${
|
|
20
72
|
isDocs
|
|
21
73
|
? `
|
|
22
74
|
<nav class="nav-actions docs-actions">
|
|
23
|
-
|
|
24
|
-
<span>v${props.projectMeta?.version || ''}</span>
|
|
25
|
-
<svg aria-hidden="true" viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
|
26
|
-
</a>
|
|
75
|
+
${renderRepositoryLink(props, true)}
|
|
27
76
|
</nav>
|
|
28
77
|
`
|
|
29
78
|
: `
|
|
30
79
|
<nav class="nav-links">
|
|
31
|
-
|
|
32
|
-
<a href="/#code">Code</a>
|
|
33
|
-
<a href="/#install">Install</a>
|
|
80
|
+
${navLinks.map(renderTextLink).join('')}
|
|
34
81
|
</nav>
|
|
35
82
|
<nav class="nav-actions">
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</a>
|
|
39
|
-
<a href="/documentation" class="btn-primary">Documentation</a>
|
|
83
|
+
${renderRepositoryLink(props)}
|
|
84
|
+
${actionLinks.map(renderTextLink).join('')}
|
|
40
85
|
</nav>
|
|
41
86
|
`
|
|
42
87
|
}
|