-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLDR-17803 site: add navigation (#4020)
- Loading branch information
1 parent
ef78779
commit a992ebd
Showing
18 changed files
with
726 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/node_modules | ||
/assets/json | ||
/assets/vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,4 +18,3 @@ defaults: | |
path: '' | ||
values: | ||
layout: page | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/node_modules/*.js | ||
content-type: application-javascript; charset=utf-8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// extract site frontmatter, save to json | ||
|
||
import * as fs from "node:fs/promises"; | ||
import * as path from "node:path"; | ||
import { default as process } from "node:process"; | ||
import { default as matter } from "gray-matter"; | ||
|
||
const SKIP_THESE = /(node_modules|\.jekyll-cache)/; | ||
|
||
async function processFile(d, fullPath, out) { | ||
const f = await fs.readFile(fullPath, "utf-8"); | ||
const m = matter(f); | ||
if (m && m.data) { | ||
const { data } = m; | ||
out.all.push({ ...data, fullPath }); | ||
} else { | ||
out.app.push({ fullPath }); // synthesize data? | ||
} | ||
} | ||
|
||
/** process one dirent */ | ||
async function processEntry(d, out, e) { | ||
const fullpath = path.join(d, e.name); | ||
if (SKIP_THESE.test(e.name)) return; | ||
if (e.isDirectory()) { | ||
return await traverse(fullpath, out); | ||
} else if (!e.isFile() || !/\.md$/.test(e.name)) { | ||
return; | ||
} | ||
await processFile(d, fullpath, out); | ||
} | ||
|
||
/** | ||
* @param {string} d path to directory | ||
* @param {object} out output struct | ||
*/ | ||
async function traverse(d, out) { | ||
const dirents = await fs.readdir(d, { withFileTypes: true }); | ||
const promises = dirents.map((e) => processEntry(d, out, e)); | ||
return Promise.all(promises); | ||
} | ||
|
||
async function main() { | ||
const out = { | ||
all: [], | ||
dirs: {}, | ||
}; | ||
await fs.mkdir("assets/json/", { recursive: true }); | ||
await traverse(".", out); | ||
await fs.writeFile("assets/json/tree.json", JSON.stringify(out, null, " ")); | ||
} | ||
|
||
main().then( | ||
() => console.log("Done."), | ||
(e) => { | ||
console.error(e); | ||
process.exitCode = 1; | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
const { ref } = Vue; | ||
|
||
// site management | ||
|
||
let myPath = window.location.pathname.slice(1) || "index.html" | ||
if (!/\.html/.test(myPath)) { | ||
myPath = `${myPath}.html`; // cloudflare likes to drop the .html | ||
} | ||
|
||
/** replace a/b/c.md with a/b */ | ||
function path2dir(p) { | ||
const dir = p.split("/").slice(0, -1).join("/"); | ||
return dir; | ||
} | ||
|
||
/** replace a/b/c.md with a/b/c.html */ | ||
function md2html(p) { | ||
return p.replace(/\.md$/, ".html"); | ||
} | ||
|
||
/** replace a/b/c.html with a/b/c.md */ | ||
function html2md(p) { | ||
return p.replace(/\.html$/, ".md"); | ||
} | ||
|
||
/** load and cook the site data */ | ||
async function siteData() { | ||
// load the json | ||
const d = await fetch("/assets/json/tree.json"); | ||
const j = await d.json(); | ||
const { all } = j; | ||
|
||
// 'all' is an array of { title, fullPath } entries. | ||
// Flat list of paths | ||
const allPaths = all.map(({ fullPath }) => fullPath); | ||
// Find all 'directories' (ending with /) | ||
const allDirs = new Set(); | ||
allPaths.forEach((p) => { | ||
const segs = p.split("/").slice(0, -1); // ['', 'dir1'] | ||
for (let n = 0; n <= segs.length; n++) { | ||
// add all parent paths, so: '', dir1, dir1/dir2 etc. | ||
const subpath = segs.slice(0, n).join("/"); | ||
allDirs.add(subpath); | ||
} | ||
}); | ||
j.allDirs = {}; | ||
j.allIndexes = []; | ||
// allDirs: '', index, downloads, etc… | ||
allDirs.forEach((dir) => { | ||
// presumed index page: /downloads -> /downloads.md | ||
// also / -> /index.md | ||
const dirIndex = `${dir || "index"}.md`; | ||
// console.dir({dir, dirIndex}); | ||
if (allPaths.indexOf(dirIndex) !== -1) { | ||
j.allDirs[dir] = { index: dirIndex }; | ||
j.allIndexes.push(dirIndex); | ||
} else { | ||
console.error(`No index page: ${dirIndex}`); | ||
j.allDirs[dir] = {}; | ||
} | ||
j.allDirs[dir].pages = []; | ||
}); | ||
allPaths.forEach((p) => { | ||
const dir = path2dir(p); | ||
j.allDirs[dir].pages.push(p); | ||
}); | ||
// map md -> title | ||
j.title = {}; | ||
all.forEach(({ title, fullPath }) => (j.title[fullPath] = title)); | ||
return j; | ||
} | ||
|
||
const app = Vue.createApp( | ||
{ | ||
setup(props) { | ||
const tree = ref({}); | ||
const status = ref(null); | ||
|
||
return { | ||
tree, | ||
status, | ||
}; | ||
}, | ||
mounted() { | ||
const t = this; | ||
siteData().then( | ||
(d) => (t.tree.value = d), | ||
(e) => (t.status = e) | ||
); | ||
}, | ||
props: { | ||
path: String, | ||
}, | ||
computed: { | ||
mdPath() { | ||
if (this.path) { | ||
return html2md(this.path); | ||
} | ||
return null; | ||
}, | ||
ourDir() { | ||
if (this.path) { | ||
return path2dir(this.path); | ||
} | ||
return ""; | ||
}, | ||
ourIndex() { | ||
if (this.tree?.value) { | ||
// first ARE we an index page? | ||
if (this.tree.value.allIndexes.indexOf(this.mdPath) != -1) { | ||
return this.mdPath; // we are an index | ||
} | ||
return this.tree.value.allDirs[this.ourDir].index; | ||
} | ||
return null; | ||
}, | ||
ourIndexHtml() { | ||
if (this.ourIndex) { | ||
return md2html(this.ourIndex); | ||
} else { | ||
return null; | ||
} | ||
}, | ||
ourIndexTitle() { | ||
if (this.ourIndex && this.tree?.value) { | ||
return this.tree.value.title[this.ourIndex] || this.ourIndex; | ||
} else { | ||
return null; | ||
} | ||
}, | ||
ourTitle() { | ||
if (this.tree?.value) { | ||
if (this.path === "") return this.rootTitle; | ||
return this.tree.value.title[html2md(this.path)]; | ||
} | ||
}, | ||
// title of root | ||
rootTitle() { | ||
return this.tree?.value?.title["index.md"]; | ||
}, | ||
// list of pages for siblings of this dir | ||
siblingPages() { | ||
if (!this.tree?.value) return []; | ||
let dirForPage = this.ourDir; | ||
if (this.tree.value.allIndexes.indexOf(this.mdPath) != -1) { | ||
const dirPages = Object.entries(this.tree?.value?.allDirs) | ||
.filter(([k, {index}]) => index == this.mdPath)[0]; | ||
if (dirPages) { | ||
// our page is an index -so, show the subpages instead of the siblings. | ||
dirForPage = dirPages[0]; // the adjusted index | ||
} | ||
} | ||
let thePages = this.tree?.value?.allDirs[dirForPage].pages ?? []; | ||
if (dirForPage === "") { | ||
thePages = [...thePages, ...this.tree?.value?.allDirs["index"].pages]; | ||
} | ||
const c = new Intl.Collator([]); | ||
return thePages | ||
.map((path) => ({ | ||
path, | ||
html: md2html(path), | ||
title: this.tree.value.title[path] ?? path, | ||
})) | ||
.sort((a, b) => c.compare(a.title, b.title)); | ||
}, | ||
}, | ||
template: `<div> | ||
<div class='status' v-if="status">{{ status }}</div> | ||
<div class='status' v-if="!tree">Loading…</div> | ||
<span v-if="path !== 'index.html'"> | ||
<a class='uplink' href="/">{{ rootTitle }}</a> | | ||
</span> | ||
<span v-if="path !== '' && ourIndexHtml && (ourIndexHtml != path) && (ourIndexHtml != 'index.html')"> | ||
<a class='uplink' | ||
v-bind:href="'/'+ourIndexHtml" | ||
> | ||
{{ ourIndexTitle }} | ||
</a> | ||
| | ||
</span> | ||
<span class="title"> {{ ourTitle }} </span> | ||
<ul class="subpages"> | ||
<li v-for="subpage of siblingPages" :key="subpage.path"> | ||
<span v-if="path == subpage.html"> | ||
<b>{{ subpage.title }}</b> | ||
</span> | ||
<a v-else v-bind:href="'/'+subpage.html"> | ||
{{ subpage.title }} | ||
</a> | ||
</li> | ||
</ul> | ||
</div>`, | ||
}, | ||
{ | ||
// path of / goes to /index.html | ||
path: myPath, | ||
} | ||
); | ||
|
||
// app.component("CldrPage", { | ||
// setup() {}, | ||
// template: `<p>Hello</p> | ||
// `, | ||
// }); | ||
|
||
// app.component("CldrList", { | ||
// setup() {}, | ||
// template: ` | ||
// <p>Hullo</p> | ||
// `, | ||
// }); | ||
|
||
app.mount("#nav"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
title: "Coding CLDR Tools" | ||
--- | ||
|
||
Pages concerning coding CLDR Tools |
Oops, something went wrong.