Add SEO and agent-readable documentation
This commit is contained in:
@@ -9,3 +9,4 @@ site/decodal-site/dist
|
|||||||
|
|
||||||
# Astro
|
# Astro
|
||||||
site/decodal-site/.astro
|
site/decodal-site/.astro
|
||||||
|
site/decodal-site/.wrangler
|
||||||
|
|||||||
@@ -40,6 +40,18 @@ npm --prefix site/decodal-site run build
|
|||||||
|
|
||||||
Use `npm --prefix site/decodal-site run build:wasm` when Rust bindings or formatter behavior changed.
|
Use `npm --prefix site/decodal-site run build:wasm` when Rust bindings or formatter behavior changed.
|
||||||
|
|
||||||
|
## Documentation site delivery
|
||||||
|
|
||||||
|
The canonical site origin is `https://decodal.hareworks.net`, configured through Astro's `site` option. A normal site build generates the sitemap, robots policy, social metadata, structured data, 404 page, and source-backed Markdown endpoints. `/llms.txt` indexes the individual English and Japanese Markdown pages; `/llms-full.txt` and `/ja/llms-full.txt` provide complete manuals. These resources are built directly from `doc/manual/source` and do not use Cloudflare's HTML-to-Markdown conversion.
|
||||||
|
|
||||||
|
Deploy the already prepared site with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm --prefix site/decodal-site run deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
Cloudflare Pages `_redirects` handles legacy paths within the site, but not hostname redirects. In the Cloudflare account, configure a Bulk Redirect from `https://decodal-site.pages.dev/` to `https://decodal.hareworks.net/` with status `301`, subpath matching, path-suffix preservation, and query-string preservation enabled. This prevents the Pages project hostname from becoming a second public origin.
|
||||||
|
|
||||||
## Syntax changes
|
## Syntax changes
|
||||||
|
|
||||||
When syntax changes:
|
When syntax changes:
|
||||||
|
|||||||
@@ -1,7 +1,47 @@
|
|||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
import sitemap from '@astrojs/sitemap';
|
||||||
|
|
||||||
|
const site = 'https://decodal.hareworks.net';
|
||||||
|
|
||||||
|
function alternateLinks(url) {
|
||||||
|
const pathname = new URL(url).pathname;
|
||||||
|
if (pathname === '/' || pathname === '/ja/') {
|
||||||
|
return [
|
||||||
|
{ url: `${site}/`, lang: 'en' },
|
||||||
|
{ url: `${site}/ja/`, lang: 'ja' },
|
||||||
|
{ url: `${site}/`, lang: 'x-default' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = pathname.match(/^\/docs\/(en|ja)\/(.*)$/);
|
||||||
|
if (!match) return undefined;
|
||||||
|
const localizedPath = match[2];
|
||||||
|
return [
|
||||||
|
{ url: `${site}/docs/en/${localizedPath}`, lang: 'en' },
|
||||||
|
{ url: `${site}/docs/ja/${localizedPath}`, lang: 'ja' },
|
||||||
|
{ url: `${site}/docs/en/${localizedPath}`, lang: 'x-default' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
site,
|
||||||
output: 'static',
|
output: 'static',
|
||||||
|
integrations: [
|
||||||
|
sitemap({
|
||||||
|
filter: (page) => {
|
||||||
|
const pathname = new URL(page).pathname;
|
||||||
|
return pathname !== '/docs/'
|
||||||
|
&& pathname !== '/404.html'
|
||||||
|
&& pathname !== '/404/'
|
||||||
|
&& !pathname.endsWith('.md')
|
||||||
|
&& !pathname.endsWith('.txt');
|
||||||
|
},
|
||||||
|
serialize(item) {
|
||||||
|
const links = alternateLinks(item.url);
|
||||||
|
return links ? { ...item, links } : item;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
build: {
|
build: {
|
||||||
assets: 'assets',
|
assets: 'assets',
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+82
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/check": "^0.9.4",
|
||||||
|
"@astrojs/sitemap": "3.2.1",
|
||||||
"@codemirror/language": "^6.12.4",
|
"@codemirror/language": "^6.12.4",
|
||||||
"@codemirror/view": "^6.43.6",
|
"@codemirror/view": "^6.43.6",
|
||||||
"@fontsource/ibm-plex-mono": "^5.3.0",
|
"@fontsource/ibm-plex-mono": "^5.3.0",
|
||||||
@@ -156,6 +157,17 @@
|
|||||||
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
|
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@astrojs/sitemap": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-uxMfO8f7pALq0ADL6Lk68UV6dNYjJ2xGUzyjjVj60JLBs5a6smtlkBYv3tQ0DzoqwS7c9n4FUx5lgv0yPo/fgA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sitemap": "^8.0.0",
|
||||||
|
"stream-replace-string": "^2.0.0",
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@astrojs/telemetry": {
|
"node_modules/@astrojs/telemetry": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.1.0.tgz",
|
||||||
@@ -2452,6 +2464,24 @@
|
|||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "24.13.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
|
||||||
|
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/sax": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/unist": {
|
"node_modules/@types/unist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
||||||
@@ -2670,6 +2700,12 @@
|
|||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/arg": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
@@ -6422,6 +6458,15 @@
|
|||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sax": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz",
|
||||||
|
"integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/section-matter": {
|
"node_modules/section-matter": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||||
@@ -6531,6 +6576,31 @@
|
|||||||
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/sitemap": {
|
||||||
|
"version": "8.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.3.tgz",
|
||||||
|
"integrity": "sha512-9Ew1tR2WYw8RGE2XLy7GjkusvYXy8Rg6y8TYuBuQMfIEdGcWoJpY2Wr5DzsEiL/TKCw56+YKTCCUHglorEYK+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^17.0.5",
|
||||||
|
"@types/sax": "^1.2.1",
|
||||||
|
"arg": "^5.0.0",
|
||||||
|
"sax": "^1.4.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"sitemap": "dist/cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0",
|
||||||
|
"npm": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/sitemap/node_modules/@types/node": {
|
||||||
|
"version": "17.0.45",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
|
||||||
|
"integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||||
@@ -6568,6 +6638,12 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stream-replace-string": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||||
@@ -6784,6 +6860,12 @@
|
|||||||
"node": ">=20.18.1"
|
"node": ">=20.18.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "7.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/unenv": {
|
"node_modules/unenv": {
|
||||||
"version": "2.0.0-rc.24",
|
"version": "2.0.0-rc.24",
|
||||||
"resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
|
"resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/check": "^0.9.4",
|
||||||
|
"@astrojs/sitemap": "3.2.1",
|
||||||
"@codemirror/language": "^6.12.4",
|
"@codemirror/language": "^6.12.4",
|
||||||
"@codemirror/view": "^6.43.6",
|
"@codemirror/view": "^6.43.6",
|
||||||
"@fontsource/ibm-plex-mono": "^5.3.0",
|
"@fontsource/ibm-plex-mono": "^5.3.0",
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
Content-Signal: search=yes, ai-input=yes, ai-train=no
|
||||||
|
X-Content-Type-Options: nosniff
|
||||||
|
|
||||||
|
/*.md
|
||||||
|
Content-Type: text/markdown; charset=utf-8
|
||||||
|
X-Robots-Tag: noindex
|
||||||
|
|
||||||
|
/llms.txt
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
X-Robots-Tag: noindex
|
||||||
|
|
||||||
|
/llms-full.txt
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
X-Robots-Tag: noindex
|
||||||
|
|
||||||
|
/ja/llms-full.txt
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
X-Robots-Tag: noindex
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/docs /docs/en/ 301
|
||||||
|
/docs/ /docs/en/ 301
|
||||||
|
/docs/components/ /docs/en/components/ 301
|
||||||
|
/docs/embedding/ /docs/en/embedding/ 301
|
||||||
|
/docs/introduction/ /docs/en/introduction/ 301
|
||||||
|
/docs/language/ /docs/en/language/ 301
|
||||||
|
/docs/language/constraints-and-defaults/ /docs/en/language/constraints-and-defaults/ 301
|
||||||
|
/docs/language/evaluation/ /docs/en/language/evaluation/ 301
|
||||||
|
/docs/language/examples/ /docs/en/language/examples/ 301
|
||||||
|
/docs/language/expression/ /docs/en/language/expression/ 301
|
||||||
|
/docs/language/expression/arithmetic/ /docs/en/language/expression/arithmetic/ 301
|
||||||
|
/docs/language/expression/array/ /docs/en/language/expression/array/ 301
|
||||||
|
/docs/language/expression/ascription/ /docs/en/language/expression/ascription/ 301
|
||||||
|
/docs/language/expression/composition/ /docs/en/language/expression/composition/ 301
|
||||||
|
/docs/language/expression/default/ /docs/en/language/expression/default/ 301
|
||||||
|
/docs/language/expression/function/ /docs/en/language/expression/function/ 301
|
||||||
|
/docs/language/expression/function-call/ /docs/en/language/expression/function-call/ 301
|
||||||
|
/docs/language/expression/identifier/ /docs/en/language/expression/identifier/ 301
|
||||||
|
/docs/language/expression/import/ /docs/en/language/expression/import/ 301
|
||||||
|
/docs/language/expression/let/ /docs/en/language/expression/let/ 301
|
||||||
|
/docs/language/expression/literal/ /docs/en/language/expression/literal/ 301
|
||||||
|
/docs/language/expression/logical-and-comparison/ /docs/en/language/expression/logical-and-comparison/ 301
|
||||||
|
/docs/language/expression/match/ /docs/en/language/expression/match/ 301
|
||||||
|
/docs/language/expression/object/ /docs/en/language/expression/object/ 301
|
||||||
|
/docs/language/expression/path-reference/ /docs/en/language/expression/path-reference/ 301
|
||||||
|
/docs/language/functions/ /docs/en/language/functions/ 301
|
||||||
|
/docs/language/grammar/ /docs/en/language/grammar/ 301
|
||||||
|
/docs/language/materialization-and-errors/ /docs/en/language/materialization-and-errors/ 301
|
||||||
|
/docs/language/modules-and-imports/ /docs/en/language/modules-and-imports/ 301
|
||||||
|
/docs/language/naming/ /docs/en/language/naming/ 301
|
||||||
|
/docs/language/operators/ /docs/en/language/operators/ 301
|
||||||
|
/docs/language/syntax/ /docs/en/language/syntax/ 301
|
||||||
|
/docs/language/value/ /docs/en/language/value/ 301
|
||||||
|
/docs/language/value/bool/ /docs/en/language/value/bool/ 301
|
||||||
|
/docs/language/value/float/ /docs/en/language/value/float/ 301
|
||||||
|
/docs/language/value/int/ /docs/en/language/value/int/ 301
|
||||||
|
/docs/language/value/string/ /docs/en/language/value/string/ 301
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||||
|
<rect width="64" height="64" fill="#1a73e8"/>
|
||||||
|
<path d="M17 13h14c12 0 20 7 20 19s-8 19-20 19H17V13Zm10 9v20h4c6 0 10-3 10-10s-4-10-10-10h-4Z" fill="#fff"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 228 B |
@@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630">
|
||||||
|
<rect width="1200" height="630" fill="#f6f7f8"/>
|
||||||
|
<rect x="72" y="72" width="1056" height="486" fill="#fff" stroke="#dadce0" stroke-width="2"/>
|
||||||
|
<rect x="120" y="118" width="72" height="72" fill="#1a73e8"/>
|
||||||
|
<path d="M139 135h16c14 0 23 8 23 19s-9 21-23 21h-16v-40Zm11 10v20h5c7 0 11-3 11-10s-4-10-11-10h-5Z" fill="#fff"/>
|
||||||
|
<text x="216" y="170" fill="#171717" font-family="IBM Plex Sans, Arial, sans-serif" font-size="54" font-weight="600">Decodal</text>
|
||||||
|
<text x="120" y="300" fill="#171717" font-family="IBM Plex Sans, Arial, sans-serif" font-size="68" font-weight="600">Deferred Constraint</text>
|
||||||
|
<text x="120" y="380" fill="#171717" font-family="IBM Plex Sans, Arial, sans-serif" font-size="68" font-weight="600">Data Language</text>
|
||||||
|
<text x="120" y="465" fill="#5f6368" font-family="IBM Plex Mono, monospace" font-size="30">configuration · constraints · defaults</text>
|
||||||
|
<rect x="120" y="505" width="160" height="6" fill="#1a73e8"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -11,9 +11,12 @@ const {
|
|||||||
playground = false,
|
playground = false,
|
||||||
frontpage = false,
|
frontpage = false,
|
||||||
locale,
|
locale,
|
||||||
|
noindex = false,
|
||||||
|
standalone = false,
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
const pathname = Astro.url.pathname;
|
const pathname = Astro.url.pathname;
|
||||||
|
const site = Astro.site ?? new URL('https://decodal.hareworks.net');
|
||||||
const language = locale ?? 'en';
|
const language = locale ?? 'en';
|
||||||
const pageDescription = description ?? (language === 'ja'
|
const pageDescription = description ?? (language === 'ja'
|
||||||
? 'Decodalは、設定、制約、デフォルトのための決定的なデータ言語です。'
|
? 'Decodalは、設定、制約、デフォルトのための決定的なデータ言語です。'
|
||||||
@@ -22,6 +25,20 @@ const docsLocale = language === 'ja' ? 'ja' : 'en';
|
|||||||
const otherDocsLocale = docsLocale === 'ja' ? 'en' : 'ja';
|
const otherDocsLocale = docsLocale === 'ja' ? 'en' : 'ja';
|
||||||
const isDocsPage = pathname.startsWith('/docs/');
|
const isDocsPage = pathname.startsWith('/docs/');
|
||||||
const localizedDocPath = active && active !== 'index' ? `${active}/` : '';
|
const localizedDocPath = active && active !== 'index' ? `${active}/` : '';
|
||||||
|
const canonicalUrl = new URL(pathname, site).href;
|
||||||
|
const englishUrl = new URL(frontpage ? '/' : `/docs/en/${localizedDocPath}`, site).href;
|
||||||
|
const japaneseUrl = new URL(frontpage ? '/ja/' : `/docs/ja/${localizedDocPath}`, site).href;
|
||||||
|
const markdownPath = frontpage
|
||||||
|
? language === 'ja' ? '/ja.md' : '/index.md'
|
||||||
|
: isDocsPage
|
||||||
|
? active === 'index'
|
||||||
|
? `/docs/${docsLocale}.md`
|
||||||
|
: `/docs/${docsLocale}/${active}.md`
|
||||||
|
: undefined;
|
||||||
|
const markdownUrl = markdownPath ? new URL(markdownPath, site).href : undefined;
|
||||||
|
const sitemapUrl = new URL('/sitemap-index.xml', site).href;
|
||||||
|
const llmsUrl = new URL('/llms.txt', site).href;
|
||||||
|
const socialImageUrl = new URL('/og.png', site).href;
|
||||||
const homeHref = language === 'ja' ? '/ja/' : '/';
|
const homeHref = language === 'ja' ? '/ja/' : '/';
|
||||||
const alternateHref = frontpage
|
const alternateHref = frontpage
|
||||||
? language === 'ja' ? '/' : '/ja/'
|
? language === 'ja' ? '/' : '/ja/'
|
||||||
@@ -32,6 +49,53 @@ const manualLabel = language === 'ja' ? 'マニュアル' : 'Manual';
|
|||||||
const manualHref = `/docs/${docsLocale}/introduction/`;
|
const manualHref = `/docs/${docsLocale}/introduction/`;
|
||||||
const manualIndexHref = `/docs/${docsLocale}/`;
|
const manualIndexHref = `/docs/${docsLocale}/`;
|
||||||
const nav = getNav(docsLocale);
|
const nav = getNav(docsLocale);
|
||||||
|
const localizedPage = !noindex && (frontpage || isDocsPage);
|
||||||
|
const structuredData = isDocsPage
|
||||||
|
? {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TechArticle',
|
||||||
|
headline: title,
|
||||||
|
description: pageDescription,
|
||||||
|
inLanguage: language,
|
||||||
|
url: canonicalUrl,
|
||||||
|
isPartOf: {
|
||||||
|
'@type': 'WebSite',
|
||||||
|
name: 'Decodal',
|
||||||
|
url: new URL('/', site).href,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: playground
|
||||||
|
? {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'WebApplication',
|
||||||
|
name: 'Decodal Playground',
|
||||||
|
description: pageDescription,
|
||||||
|
applicationCategory: 'DeveloperApplication',
|
||||||
|
operatingSystem: 'Web',
|
||||||
|
url: canonicalUrl,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@graph': [
|
||||||
|
{
|
||||||
|
'@type': 'WebSite',
|
||||||
|
name: 'Decodal',
|
||||||
|
description: pageDescription,
|
||||||
|
inLanguage: language,
|
||||||
|
url: canonicalUrl,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'SoftwareSourceCode',
|
||||||
|
name: 'Decodal',
|
||||||
|
description: pageDescription,
|
||||||
|
codeRepository: 'https://gitea.hareworks.net/Hare/Decodal',
|
||||||
|
license: [
|
||||||
|
'https://opensource.org/license/mit',
|
||||||
|
'https://www.apache.org/licenses/LICENSE-2.0',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
function isCurrent(path) {
|
function isCurrent(path) {
|
||||||
return pathname === path || (path !== '/' && pathname.startsWith(path));
|
return pathname === path || (path !== '/' && pathname.startsWith(path));
|
||||||
@@ -55,9 +119,33 @@ function renderNav(items, prefix = []) {
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="description" content={pageDescription} />
|
<meta name="description" content={pageDescription} />
|
||||||
{(frontpage || isDocsPage) && <link rel="alternate" hreflang="en" href={frontpage ? '/' : `/docs/en/${localizedDocPath}`} />}
|
{noindex && <meta name="robots" content="noindex" />}
|
||||||
{(frontpage || isDocsPage) && <link rel="alternate" hreflang="ja" href={frontpage ? '/ja/' : `/docs/ja/${localizedDocPath}`} />}
|
{!noindex && <link rel="canonical" href={canonicalUrl} />}
|
||||||
{(frontpage || isDocsPage) && <link rel="alternate" hreflang="x-default" href={frontpage ? '/' : `/docs/en/${localizedDocPath}`} />}
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||||
|
<link rel="sitemap" href={sitemapUrl} />
|
||||||
|
<link rel="describedby" href={llmsUrl} type="text/markdown" />
|
||||||
|
{markdownUrl && <link rel="alternate" type="text/markdown" href={markdownUrl} />}
|
||||||
|
{localizedPage && <link rel="alternate" hreflang="en" href={englishUrl} />}
|
||||||
|
{localizedPage && <link rel="alternate" hreflang="ja" href={japaneseUrl} />}
|
||||||
|
{localizedPage && <link rel="alternate" hreflang="x-default" href={englishUrl} />}
|
||||||
|
<meta property="og:type" content={isDocsPage ? 'article' : 'website'} />
|
||||||
|
<meta property="og:site_name" content="Decodal" />
|
||||||
|
<meta property="og:title" content={title} />
|
||||||
|
<meta property="og:description" content={pageDescription} />
|
||||||
|
<meta property="og:url" content={canonicalUrl} />
|
||||||
|
<meta property="og:locale" content={language === 'ja' ? 'ja_JP' : 'en_US'} />
|
||||||
|
{localizedPage && <meta property="og:locale:alternate" content={language === 'ja' ? 'en_US' : 'ja_JP'} />}
|
||||||
|
<meta property="og:image" content={socialImageUrl} />
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta property="og:image:alt" content="Decodal — Deferred Constraint Data Language" />
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content={title} />
|
||||||
|
<meta name="twitter:description" content={pageDescription} />
|
||||||
|
<meta name="twitter:image" content={socialImageUrl} />
|
||||||
|
<meta name="twitter:image:alt" content="Decodal — Deferred Constraint Data Language" />
|
||||||
|
{!noindex && <script type="application/ld+json" is:inline set:html={JSON.stringify(structuredData)} />}
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -73,8 +161,8 @@ function renderNav(items, prefix = []) {
|
|||||||
{(frontpage || isDocsPage) && <a class="language-switch" href={alternateHref} hreflang={otherDocsLocale} aria-label={alternateAriaLabel}>{alternateLabel}</a>}
|
{(frontpage || isDocsPage) && <a class="language-switch" href={alternateHref} hreflang={otherDocsLocale} aria-label={alternateAriaLabel}>{alternateLabel}</a>}
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<div class:list={{ layout: true, 'wide-layout': playground || frontpage, 'playground-layout': playground }}>
|
<div class:list={{ layout: true, 'wide-layout': playground || frontpage || standalone, 'playground-layout': playground }}>
|
||||||
{!playground && !frontpage && (
|
{!playground && !frontpage && !standalone && (
|
||||||
<aside class="sidebar">
|
<aside class="sidebar">
|
||||||
<div class="sidebar-content">
|
<div class="sidebar-content">
|
||||||
<a class="sidebar-title" href={manualIndexHref}>{manualLabel}</a>
|
<a class="sidebar-title" href={manualIndexHref}>{manualLabel}</a>
|
||||||
@@ -82,7 +170,7 @@ function renderNav(items, prefix = []) {
|
|||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
)}
|
)}
|
||||||
<main class={playground ? 'playground' : frontpage ? 'frontpage' : ''}>
|
<main class={playground ? 'playground' : frontpage ? 'frontpage' : standalone ? 'standalone' : ''}>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import { docTitle, orderedDocSlugs, sourceMarkdown } from './docs.js';
|
||||||
|
|
||||||
|
export const SITE_URL = 'https://decodal.hareworks.net';
|
||||||
|
|
||||||
|
const homePages = {
|
||||||
|
en: `# Decodal
|
||||||
|
|
||||||
|
Decodal is the Deferred Constraint Data Language: a small deterministic language for describing, composing, validating, and materializing structured data.
|
||||||
|
|
||||||
|
Configuration values, constraints, defaults, and derived values share one expression system. The host owns filesystems and external I/O; Decodal owns deterministic evaluation.
|
||||||
|
|
||||||
|
\`\`\`dcdl
|
||||||
|
let
|
||||||
|
Port = Int & >= 1 & <= 65535;
|
||||||
|
Service = {
|
||||||
|
host = String;
|
||||||
|
port = Port default 8080;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
host = "127.0.0.1";
|
||||||
|
} as Service;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [English manual](/docs/en.md)
|
||||||
|
- [Embedding guide](/docs/en/embedding.md)
|
||||||
|
- [Packages and integrations](/docs/en/components.md)
|
||||||
|
- [Japanese site](/ja.md)
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Browser playground](/playground/)
|
||||||
|
- [Source repository](https://gitea.hareworks.net/Hare/Decodal)
|
||||||
|
`,
|
||||||
|
ja: `# Decodal
|
||||||
|
|
||||||
|
Decodalは、構造化データの記述、合成、検証、具体化のための小さく決定的な言語、Deferred Constraint Data Languageである。
|
||||||
|
|
||||||
|
設定値、制約、デフォルト、派生値をひとつの式体系で扱う。filesystemや外部I/Oはホストが担い、Decodalは決定的な評価を担う。
|
||||||
|
|
||||||
|
\`\`\`dcdl
|
||||||
|
let
|
||||||
|
Port = Int & >= 1 & <= 65535;
|
||||||
|
Service = {
|
||||||
|
host = String;
|
||||||
|
port = Port default 8080;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
host = "127.0.0.1";
|
||||||
|
} as Service;
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## ドキュメント
|
||||||
|
|
||||||
|
- [日本語マニュアル](/docs/ja.md)
|
||||||
|
- [組み込みガイド](/docs/ja/embedding.md)
|
||||||
|
- [パッケージと統合](/docs/ja/components.md)
|
||||||
|
- [English site](/index.md)
|
||||||
|
|
||||||
|
## リソース
|
||||||
|
|
||||||
|
- [ブラウザPlayground](/playground/)
|
||||||
|
- [ソースリポジトリ](https://gitea.hareworks.net/Hare/Decodal)
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function homeMarkdown(locale = 'en') {
|
||||||
|
return homePages[locale] ?? homePages.en;
|
||||||
|
}
|
||||||
|
|
||||||
|
function markdownUrl(slug, locale) {
|
||||||
|
return slug === 'index'
|
||||||
|
? `${SITE_URL}/docs/${locale}.md`
|
||||||
|
: `${SITE_URL}/docs/${locale}/${slug}.md`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function manualLinks(locale) {
|
||||||
|
return orderedDocSlugs(locale, { includeIndex: true })
|
||||||
|
.map((slug) => `- [${docTitle(slug, locale)}](${markdownUrl(slug, locale)})`)
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function llmsText() {
|
||||||
|
return `# Decodal
|
||||||
|
|
||||||
|
> Decodal is a deterministic data language for configuration, constraints, defaults, validation, and materialization.
|
||||||
|
|
||||||
|
Use the English manual as the default reference. Japanese translations cover the same document structure. Markdown endpoints are generated directly from the manual sources rather than converted from HTML.
|
||||||
|
|
||||||
|
## English documentation
|
||||||
|
|
||||||
|
${manualLinks('en')}
|
||||||
|
|
||||||
|
## 日本語ドキュメント
|
||||||
|
|
||||||
|
${manualLinks('ja')}
|
||||||
|
|
||||||
|
## Complete manuals
|
||||||
|
|
||||||
|
- [Complete English manual](${SITE_URL}/llms-full.txt): All English manual pages in one text resource.
|
||||||
|
- [日本語マニュアル全文](${SITE_URL}/ja/llms-full.txt): 日本語マニュアルの全ページをまとめたテキスト。
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Project overview](${SITE_URL}/index.md): Concise English overview.
|
||||||
|
- [プロジェクト概要](${SITE_URL}/ja.md): 日本語の概要。
|
||||||
|
- [Browser playground](${SITE_URL}/playground/): Interactive Decodal runtime and editor.
|
||||||
|
- [Source repository](https://gitea.hareworks.net/Hare/Decodal): Rust, JavaScript, language service, and website source.
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fullManual(locale = 'en') {
|
||||||
|
const heading = locale === 'ja' ? 'Decodalマニュアル全文' : 'Complete Decodal Manual';
|
||||||
|
const note = locale === 'ja'
|
||||||
|
? 'このファイルは日本語マニュアルの原本から生成されている。各章の個別Markdownは /llms.txt を参照。'
|
||||||
|
: 'This file is generated from the English manual sources. See /llms.txt for links to individual Markdown pages.';
|
||||||
|
const pages = orderedDocSlugs(locale, { includeIndex: true })
|
||||||
|
.map((slug) => sourceMarkdown(slug, locale).trim())
|
||||||
|
.join('\n\n---\n\n');
|
||||||
|
return `# ${heading}\n\n${note}\n\n${pages}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function textResponse(content, language = 'en', contentType = 'text/markdown') {
|
||||||
|
return new Response(content, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': `${contentType}; charset=utf-8`,
|
||||||
|
'Content-Language': language,
|
||||||
|
'Content-Signal': 'search=yes, ai-input=yes, ai-train=no',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -173,6 +173,16 @@ export function allDocSlugs(locale = 'en') {
|
|||||||
return Object.keys(docsByLocale[locale] ?? {}).filter((slug) => slug !== 'index');
|
return Object.keys(docsByLocale[locale] ?? {}).filter((slug) => slug !== 'index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function flattenNav(items) {
|
||||||
|
return items.flatMap((item) => [item.slug, ...(item.children ? flattenNav(item.children) : [])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function orderedDocSlugs(locale = 'en', { includeIndex = false } = {}) {
|
||||||
|
const localizedDocs = docsByLocale[locale] ?? docsByLocale.en;
|
||||||
|
const slugs = flattenNav(getNav(locale)).filter((slug) => localizedDocs[slug]);
|
||||||
|
return includeIndex ? ['index', ...slugs] : slugs;
|
||||||
|
}
|
||||||
|
|
||||||
function findDocTitle(slug, items) {
|
function findDocTitle(slug, items) {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
if (item.slug === slug) return item.title;
|
if (item.slug === slug) return item.title;
|
||||||
@@ -185,13 +195,51 @@ function findDocTitle(slug, items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function docTitle(slug, locale = 'en') {
|
export function docTitle(slug, locale = 'en') {
|
||||||
|
if (slug === 'index') return locale === 'ja' ? 'Decodalマニュアル' : 'Decodal Manual';
|
||||||
return findDocTitle(slug, getNav(locale)) ?? slug;
|
return findDocTitle(slug, getNav(locale)) ?? slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMarkdown(slug, locale = 'en') {
|
function getSource(slug, locale) {
|
||||||
const localizedDocs = docsByLocale[locale] ?? docsByLocale.en;
|
const localizedDocs = docsByLocale[locale] ?? docsByLocale.en;
|
||||||
const source = localizedDocs[slug] ?? localizedDocs.index;
|
return localizedDocs[slug] ?? localizedDocs.index ?? '# Not found\n';
|
||||||
const html = marked.parse(source ?? '# Not found\n');
|
}
|
||||||
|
|
||||||
|
function stripInlineMarkdown(value) {
|
||||||
|
return value
|
||||||
|
.replace(/!\[([^\]]*)\]\([^)]*\)/g, '$1')
|
||||||
|
.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1')
|
||||||
|
.replace(/[`*_~]/g, '')
|
||||||
|
.replace(/<[^>]+>/g, '')
|
||||||
|
.replace(/\s+/g, ' ')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function docDescription(slug, locale = 'en') {
|
||||||
|
const blocks = getSource(slug, locale)
|
||||||
|
.replace(/```[\s\S]*?```/g, '')
|
||||||
|
.split(/\n\s*\n/)
|
||||||
|
.map((block) => block.trim())
|
||||||
|
.filter((block) => block && !block.startsWith('#') && !/^[-*]\s/.test(block));
|
||||||
|
const description = stripInlineMarkdown(blocks[0] ?? '');
|
||||||
|
if (description.length <= 180) return description;
|
||||||
|
const shortened = description.slice(0, 177).replace(/\s+\S*$/, '').trimEnd();
|
||||||
|
return `${shortened || description.slice(0, 177)}…`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sourceMarkdown(slug, locale = 'en') {
|
||||||
|
return getSource(slug, locale).replace(/\]\(([^)\s]+)\)/g, (all, destination) => {
|
||||||
|
const [href, hash = ''] = destination.split('#', 2);
|
||||||
|
if (!href.endsWith('.md')) return all;
|
||||||
|
const target = normalizeDocLink(locale, slug, href.slice(0, -3));
|
||||||
|
const pathname = target === 'index'
|
||||||
|
? `/docs/${locale}.md`
|
||||||
|
: `/docs/${locale}/${target}.md`;
|
||||||
|
return `](${pathname}${hash ? `#${hash}` : ''})`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderMarkdown(slug, locale = 'en') {
|
||||||
|
const html = marked.parse(getSource(slug, locale));
|
||||||
return html.replace(/href="([^"#][^"]*)\.md(#[^"]*)?"/g, (_all, href, hash = '') => {
|
return html.replace(/href="([^"#][^"]*)\.md(#[^"]*)?"/g, (_all, href, hash = '') => {
|
||||||
const target = normalizeDocLink(locale, slug, href);
|
const target = normalizeDocLink(locale, slug, href);
|
||||||
const pathname = target === 'index' ? `/docs/${locale}/` : `/docs/${locale}/${target}/`;
|
const pathname = target === 'index' ? `/docs/${locale}/` : `/docs/${locale}/${target}/`;
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
import ManualLayout from '../layouts/ManualLayout.astro';
|
||||||
|
---
|
||||||
|
<ManualLayout
|
||||||
|
title="Page not found — Decodal"
|
||||||
|
description="The requested Decodal page could not be found."
|
||||||
|
noindex
|
||||||
|
standalone
|
||||||
|
>
|
||||||
|
<article class="markdown not-found">
|
||||||
|
<h1>Page not found</h1>
|
||||||
|
<p>The requested page does not exist or has moved.</p>
|
||||||
|
<p><a href="/">Return home</a> or <a href="/docs/en/">open the manual</a>.</p>
|
||||||
|
</article>
|
||||||
|
</ManualLayout>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
import ManualLayout from '../../../layouts/ManualLayout.astro';
|
import ManualLayout from '../../../layouts/ManualLayout.astro';
|
||||||
import { allDocSlugs, docTitle, renderMarkdown } from '../../../lib/docs.js';
|
import { allDocSlugs, docDescription, docTitle, renderMarkdown } from '../../../lib/docs.js';
|
||||||
import '@fontsource/ibm-plex-sans-jp/latin-400.css';
|
import '@fontsource/ibm-plex-sans-jp/latin-400.css';
|
||||||
import '@fontsource/ibm-plex-sans-jp/latin-600.css';
|
import '@fontsource/ibm-plex-sans-jp/latin-600.css';
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ export function getStaticPaths() {
|
|||||||
const { slug } = Astro.props;
|
const { slug } = Astro.props;
|
||||||
const html = renderMarkdown(slug, 'en');
|
const html = renderMarkdown(slug, 'en');
|
||||||
const title = docTitle(slug, 'en');
|
const title = docTitle(slug, 'en');
|
||||||
|
const description = docDescription(slug, 'en');
|
||||||
---
|
---
|
||||||
<ManualLayout title={`${title} — Decodal Manual`} active={slug} locale="en">
|
<ManualLayout title={`${title} — Decodal Manual`} description={description} active={slug} locale="en">
|
||||||
<article class="markdown" set:html={html} />
|
<article class="markdown" set:html={html} />
|
||||||
</ManualLayout>
|
</ManualLayout>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { textResponse } from '../../../../lib/agent-content.js';
|
||||||
|
import { allDocSlugs, sourceMarkdown } from '../../../../lib/docs.js';
|
||||||
|
|
||||||
|
export function getStaticPaths() {
|
||||||
|
return allDocSlugs('en').map((slug) => ({ params: { slug }, props: { slug } }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GET({ props }) {
|
||||||
|
return textResponse(sourceMarkdown(props.slug, 'en'), 'en');
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { textResponse } from '../../../lib/agent-content.js';
|
||||||
|
import { sourceMarkdown } from '../../../lib/docs.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(sourceMarkdown('index', 'en'), 'en');
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
import ManualLayout from '../../../layouts/ManualLayout.astro';
|
import ManualLayout from '../../../layouts/ManualLayout.astro';
|
||||||
import { allDocSlugs, docTitle, renderMarkdown } from '../../../lib/docs.js';
|
import { allDocSlugs, docDescription, docTitle, renderMarkdown } from '../../../lib/docs.js';
|
||||||
import '@fontsource/ibm-plex-sans-jp/400.css';
|
import '@fontsource/ibm-plex-sans-jp/400.css';
|
||||||
import '@fontsource/ibm-plex-sans-jp/600.css';
|
import '@fontsource/ibm-plex-sans-jp/600.css';
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ export function getStaticPaths() {
|
|||||||
const { slug } = Astro.props;
|
const { slug } = Astro.props;
|
||||||
const html = renderMarkdown(slug, 'ja');
|
const html = renderMarkdown(slug, 'ja');
|
||||||
const title = docTitle(slug, 'ja');
|
const title = docTitle(slug, 'ja');
|
||||||
|
const description = docDescription(slug, 'ja');
|
||||||
---
|
---
|
||||||
<ManualLayout title={`${title} — Decodalマニュアル`} active={slug} locale="ja">
|
<ManualLayout title={`${title} — Decodalマニュアル`} description={description} active={slug} locale="ja">
|
||||||
<article class="markdown" set:html={html} />
|
<article class="markdown" set:html={html} />
|
||||||
</ManualLayout>
|
</ManualLayout>
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { textResponse } from '../../../../lib/agent-content.js';
|
||||||
|
import { allDocSlugs, sourceMarkdown } from '../../../../lib/docs.js';
|
||||||
|
|
||||||
|
export function getStaticPaths() {
|
||||||
|
return allDocSlugs('ja').map((slug) => ({ params: { slug }, props: { slug } }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GET({ props }) {
|
||||||
|
return textResponse(sourceMarkdown(props.slug, 'ja'), 'ja');
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { textResponse } from '../../../lib/agent-content.js';
|
||||||
|
import { sourceMarkdown } from '../../../lib/docs.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(sourceMarkdown('index', 'ja'), 'ja');
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { homeMarkdown, textResponse } from '../lib/agent-content.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(homeMarkdown('en'), 'en');
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { homeMarkdown, textResponse } from '../../lib/agent-content.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(homeMarkdown('ja'), 'ja');
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { fullManual, textResponse } from '../../lib/agent-content.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(fullManual('ja'), 'ja', 'text/plain');
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { fullManual, textResponse } from '../lib/agent-content.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(fullManual('en'), 'en', 'text/plain');
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { llmsText, textResponse } from '../lib/agent-content.js';
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(llmsText(), 'en', 'text/plain');
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { SITE_URL, textResponse } from '../lib/agent-content.js';
|
||||||
|
|
||||||
|
const robots = `User-agent: *
|
||||||
|
Content-Signal: search=yes, ai-input=yes, ai-train=no
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: ${SITE_URL}/sitemap-index.xml
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function GET() {
|
||||||
|
return textResponse(robots, 'en', 'text/plain');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user