Skip to content

Commit

Permalink
CLDR-17803 site: add navigation (#4020)
Browse files Browse the repository at this point in the history
  • Loading branch information
srl295 authored and conradarcturus committed Sep 25, 2024
1 parent ef78779 commit a992ebd
Show file tree
Hide file tree
Showing 18 changed files with 726 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ jobs:
bundler-cache: true
- name: Setup Jekyll
run: 'gem install bundler jekyll kramdown-parser-gfm webrick'
- name: Setup assets
run: 'cd docs/site/assets && npm ci && npm run build'
- name: Build cldr.pages.dev
run: 'cd docs/site && jekyll build'
- name: Pre-install Wrangler
Expand Down
3 changes: 3 additions & 0 deletions docs/site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
/assets/json
/assets/vendor
1 change: 0 additions & 1 deletion docs/site/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ defaults:
path: ''
values:
layout: page

2 changes: 2 additions & 0 deletions docs/site/_headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/*.js
content-type: application-javascript; charset=utf-8
20 changes: 12 additions & 8 deletions docs/site/_layouts/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,27 @@
<div class="icon"><a href="http://www.unicode.org/"> <img border="0"
src="http://www.unicode.org/webscripts/logo60s2.gif" align="middle" alt="[Unicode]" width="34"
height="33"></a>&nbsp;&nbsp;
<a class="bar" href="/">
<font size="3">
CLDR Site / {{page.title}}
</font>
</a>

<div id="nav" class="nav">
<!-- Vue mount here -->
</div>
<i>This navigation UI is temporary, just to give access to the pages.</i>
</div>
<div class="bar"><a href="http://www.unicode.org" class="bar">Home</a>
| <a href="http://www.unicode.org/sitemap/" class="bar">Site
Map</a> | <a href="http://www.unicode.org/search/" class="bar">Search</a></div>
<!-- <div class="bar"><a href="http://www.unicode.org" class="bar">Home</a>
| <a href="http://www.unicode.org/search/" class="bar">Search</a></div> -->
</header>



<section class="body">
{{ content }}
</section>
<footer>
© 1991-2024 Unicode, Inc. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. See <a href="https://www.unicode.org/copyright.html">Terms of Use</a>.
</footer>
<!-- workaround for cloudflare content-type issue -->
<script src="/assets/vendor/vue.global.prod.js"></script>
<script src="/assets/js/cldrsite.js"></script>
</body>

</html>
17 changes: 17 additions & 0 deletions docs/site/assets/css/page.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ header > div.icon {
flex-grow: 1;
}

header .title {
color: white;
font-size: 1.5em;
}

header .nav, header .nav > div {
display: inline;
}

header .nav a, header .nav .title {
color: white;
}

header .nav ul b {
color: yellow;
}

footer {
width: 100%;
margin-left: auto;
Expand Down
59 changes: 59 additions & 0 deletions docs/site/assets/js/build.mjs
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;
}
);
214 changes: 214 additions & 0 deletions docs/site/assets/js/cldrsite.js
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");
2 changes: 1 addition & 1 deletion docs/site/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ title: Internal Development

# Internal Development

![Unicode copyright](https://www.unicode.org/img/hb_notice.gif)
![Unicode copyright](https://www.unicode.org/img/hb_notice.gif)
6 changes: 3 additions & 3 deletions docs/site/development/cldr-big-red-switch.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: CLDR: Big Red Switch
title: 'CLDR: Big Red Switch'
---

# CLDR: Big Red Switch
Expand All @@ -12,7 +12,7 @@ title: CLDR: Big Red Switch

### Trial New Version (Let us know if you need write access!)

(For editors: [List View of BRS](https://cldr.unicode.org/development/cldr-big-red-switch/list-view-of-brs), [Spreadsheet View](https://docs.google.com/spreadsheets/d/1dIOLxKX2gW7BRDVdMBH9qr1GdxpPj8Bc1Pe-02p_92k/edit#gid=0))
(For editors: [List View of BRS](https://cldr.unicode.org/development/cldr-big-red-switch/list-view-of-brs), [Spreadsheet View](https://docs.google.com/spreadsheets/d/1dIOLxKX2gW7BRDVdMBH9qr1GdxpPj8Bc1Pe-02p_92k/edit#gid=0))

## Contributor Message

Expand All @@ -28,4 +28,4 @@ However, names are not automatically entered there, since some people may not wi
2. e\-mail that list **on BCC:** the above message with a subject line of "\[CLDR X.Y Contributor Message]", and a request to please keep the subject line intact.
3. Then, the subject line can be used to filter/locate the contributor requests.

![Unicode copyright](https://www.unicode.org/img/hb_notice.gif)
![Unicode copyright](https://www.unicode.org/img/hb_notice.gif)
5 changes: 5 additions & 0 deletions docs/site/development/coding-cldr-tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: "Coding CLDR Tools"
---

Pages concerning coding CLDR Tools
Loading

0 comments on commit a992ebd

Please sign in to comment.