fix: Optimize docs page API (7MB→19KB), fix categories, add MI translations
- Add summary projection to Document.list() excluding heavy content fields - Fix 23 documents with invalid categories (framework/governance/reference) - Archive 9 duplicate documents (kept canonical short-slug versions) - Add Te Reo Māori UI translations to docs-app.js and document-cards.js - Refactor language checks to be extensible (no more hardcoded EN/DE/FR) - Remove unused font preloads from docs.html (fixes browser warning) - Add resources to valid publish categories Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
28cb1139a9
commit
0ef20a6e8d
5 changed files with 84 additions and 35 deletions
|
|
@ -38,10 +38,6 @@
|
|||
<meta name="apple-mobile-web-app-title" content="Tractatus">
|
||||
<link rel="apple-touch-icon" href="/images/tractatus-icon-new.svg">
|
||||
|
||||
<!-- Preload critical fonts for faster initial render -->
|
||||
<link rel="preload" href="/fonts/inter-400.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/fonts/inter-700.woff2" as="font" type="font/woff2" crossorigin>
|
||||
|
||||
<link rel="stylesheet" href="/css/fonts.css?v=0.1.2.1770750464740">
|
||||
<link rel="stylesheet" href="/css/tailwind.css?v=0.1.2.1770750464740">
|
||||
<link rel="stylesheet" href="/css/tractatus-theme.min.css?v=0.1.2.1770750464740">
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ class DocumentCards {
|
|||
practical: 'Guides pratiques',
|
||||
technical: 'Détails techniques',
|
||||
reference: 'Documentation de référence'
|
||||
},
|
||||
mi: {
|
||||
title: 'Aratohu Tae',
|
||||
critical: 'Ngā wāhanga waipuke',
|
||||
conceptual: 'Ngā whakamāramatanga ariā',
|
||||
practical: 'Ngā aratohu whaihua',
|
||||
technical: 'Ngā taipitopito hangarau',
|
||||
reference: 'Ngā tuhinga tohutoro'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,32 @@ const UI_TRANSLATIONS = {
|
|||
'advanced-topics': 'Sujets avancés',
|
||||
'business-leadership': 'Business & Leadership'
|
||||
}
|
||||
},
|
||||
mi: {
|
||||
pageTitle: 'Ngā Tuhinga Anga',
|
||||
pageSubtitle: 'Ngā tautukunga hangarau, ngā aratohu, me ngā rauemi tohutoro',
|
||||
documentsHeading: 'Ngā Tuhinga',
|
||||
searchButton: 'Rapu',
|
||||
backToDocuments: 'Hoki ki ngā Tuhinga',
|
||||
selectDocument: 'Kōwhiria he Tuhinga',
|
||||
selectDocumentDesc: 'Kōwhiria he tuhinga mai i te taha ki te tīmata pānui',
|
||||
loadingDocument: 'Kei te uta te tuhinga...',
|
||||
errorLoadingDoc: 'He hapa i te utanga o te tuhinga',
|
||||
tableOfContents: 'Rārangi Kaupapa',
|
||||
downloadPdf: 'Tikiake PDF',
|
||||
github: 'GitHub',
|
||||
publicRepository: 'Pūtahi Tūmatanui',
|
||||
publicRepositoryDesc: 'Waehere pūtake, tauira me ngā koha',
|
||||
readmeQuickStart: 'README & Tīmata Tere',
|
||||
readmeQuickStartDesc: 'Aratohu whakauru me te tīmata',
|
||||
categories: {
|
||||
'getting-started': 'Tīmata',
|
||||
'resources': 'Ngā Rauemi',
|
||||
'research-theory': 'Rangahau & Ariā',
|
||||
'technical-reference': 'Tohutoro Hangarau',
|
||||
'advanced-topics': 'Kaupapa Matatau',
|
||||
'business-leadership': 'Pakihi & Hautūtanga'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -95,17 +121,15 @@ function updatePageUI(lang = currentLanguage) {
|
|||
const t = getUITranslations(lang);
|
||||
|
||||
// Update page header
|
||||
const allPageTitles = Object.values(UI_TRANSLATIONS).map(t => t.pageTitle);
|
||||
const pageTitle = document.querySelector('h1');
|
||||
if (pageTitle && pageTitle.textContent === UI_TRANSLATIONS.en.pageTitle ||
|
||||
pageTitle.textContent === UI_TRANSLATIONS.de.pageTitle ||
|
||||
pageTitle.textContent === UI_TRANSLATIONS.fr.pageTitle) {
|
||||
if (pageTitle && allPageTitles.includes(pageTitle.textContent)) {
|
||||
pageTitle.textContent = t.pageTitle;
|
||||
}
|
||||
|
||||
const allPageSubtitles = Object.values(UI_TRANSLATIONS).map(t => t.pageSubtitle);
|
||||
const pageSubtitle = document.querySelector('.text-gray-600.mt-2');
|
||||
if (pageSubtitle && (pageSubtitle.textContent === UI_TRANSLATIONS.en.pageSubtitle ||
|
||||
pageSubtitle.textContent === UI_TRANSLATIONS.de.pageSubtitle ||
|
||||
pageSubtitle.textContent === UI_TRANSLATIONS.fr.pageSubtitle)) {
|
||||
if (pageSubtitle && allPageSubtitles.includes(pageSubtitle.textContent)) {
|
||||
pageSubtitle.textContent = t.pageSubtitle;
|
||||
}
|
||||
|
||||
|
|
@ -116,20 +140,17 @@ function updatePageUI(lang = currentLanguage) {
|
|||
}
|
||||
|
||||
// Update sidebar Documents heading
|
||||
const allDocsHeadings = Object.values(UI_TRANSLATIONS).map(t => t.documentsHeading);
|
||||
const docsHeading = document.querySelector('aside h3');
|
||||
if (docsHeading && (docsHeading.textContent === UI_TRANSLATIONS.en.documentsHeading ||
|
||||
docsHeading.textContent === UI_TRANSLATIONS.de.documentsHeading ||
|
||||
docsHeading.textContent === UI_TRANSLATIONS.fr.documentsHeading)) {
|
||||
if (docsHeading && allDocsHeadings.includes(docsHeading.textContent)) {
|
||||
docsHeading.textContent = t.documentsHeading;
|
||||
}
|
||||
|
||||
// Update GitHub section heading
|
||||
const allGithubLabels = Object.values(UI_TRANSLATIONS).map(t => t.github);
|
||||
const githubHeadings = document.querySelectorAll('aside h3');
|
||||
githubHeadings.forEach(heading => {
|
||||
if (heading.textContent.trim() === UI_TRANSLATIONS.en.github ||
|
||||
heading.textContent.trim() === UI_TRANSLATIONS.de.github ||
|
||||
heading.textContent.trim() === UI_TRANSLATIONS.fr.github) {
|
||||
// Keep the SVG icon, just update text
|
||||
if (allGithubLabels.includes(heading.textContent.trim())) {
|
||||
const textNode = Array.from(heading.childNodes).find(node => node.nodeType === Node.TEXT_NODE);
|
||||
if (textNode) {
|
||||
textNode.textContent = t.github;
|
||||
|
|
@ -138,31 +159,28 @@ function updatePageUI(lang = currentLanguage) {
|
|||
});
|
||||
|
||||
// Update GitHub links
|
||||
const allRepoTitles = Object.values(UI_TRANSLATIONS).map(t => t.publicRepository);
|
||||
const allReadmeTitles = Object.values(UI_TRANSLATIONS).map(t => t.readmeQuickStart);
|
||||
const allRepoDescs = Object.values(UI_TRANSLATIONS).map(t => t.publicRepositoryDesc);
|
||||
const allReadmeDescs = Object.values(UI_TRANSLATIONS).map(t => t.readmeQuickStartDesc);
|
||||
|
||||
const githubLinks = document.querySelectorAll('aside a[href*="github.com"]');
|
||||
githubLinks.forEach(link => {
|
||||
const titleDiv = link.querySelector('.text-sm.font-medium');
|
||||
const descDiv = link.querySelector('.text-xs.text-gray-500');
|
||||
|
||||
if (titleDiv) {
|
||||
if (titleDiv.textContent === UI_TRANSLATIONS.en.publicRepository ||
|
||||
titleDiv.textContent === UI_TRANSLATIONS.de.publicRepository ||
|
||||
titleDiv.textContent === UI_TRANSLATIONS.fr.publicRepository) {
|
||||
if (allRepoTitles.includes(titleDiv.textContent)) {
|
||||
titleDiv.textContent = t.publicRepository;
|
||||
} else if (titleDiv.textContent === UI_TRANSLATIONS.en.readmeQuickStart ||
|
||||
titleDiv.textContent === UI_TRANSLATIONS.de.readmeQuickStart ||
|
||||
titleDiv.textContent === UI_TRANSLATIONS.fr.readmeQuickStart) {
|
||||
} else if (allReadmeTitles.includes(titleDiv.textContent)) {
|
||||
titleDiv.textContent = t.readmeQuickStart;
|
||||
}
|
||||
}
|
||||
|
||||
if (descDiv) {
|
||||
if (descDiv.textContent === UI_TRANSLATIONS.en.publicRepositoryDesc ||
|
||||
descDiv.textContent === UI_TRANSLATIONS.de.publicRepositoryDesc ||
|
||||
descDiv.textContent === UI_TRANSLATIONS.fr.publicRepositoryDesc) {
|
||||
if (allRepoDescs.includes(descDiv.textContent)) {
|
||||
descDiv.textContent = t.publicRepositoryDesc;
|
||||
} else if (descDiv.textContent === UI_TRANSLATIONS.en.readmeQuickStartDesc ||
|
||||
descDiv.textContent === UI_TRANSLATIONS.de.readmeQuickStartDesc ||
|
||||
descDiv.textContent === UI_TRANSLATIONS.fr.readmeQuickStartDesc) {
|
||||
} else if (allReadmeDescs.includes(descDiv.textContent)) {
|
||||
descDiv.textContent = t.readmeQuickStartDesc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ async function listDocuments(req, res) {
|
|||
filter.audience = audience;
|
||||
}
|
||||
|
||||
// Use summary projection for list endpoint (returns ~7KB instead of ~7MB)
|
||||
const summary = req.query.fields !== 'full';
|
||||
|
||||
if (quadrant && !audience) {
|
||||
documents = await Document.findByQuadrant(quadrant, {
|
||||
limit: parseInt(limit),
|
||||
|
|
@ -48,7 +51,8 @@ async function listDocuments(req, res) {
|
|||
documents = await Document.list({
|
||||
limit: parseInt(limit),
|
||||
skip: parseInt(skip),
|
||||
filter
|
||||
filter,
|
||||
summary
|
||||
});
|
||||
total = await Document.count(filter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -223,8 +223,8 @@ class Document {
|
|||
|
||||
// Validate category is in allowed list
|
||||
const validCategories = [
|
||||
'getting-started', 'technical-reference', 'research-theory',
|
||||
'advanced-topics', 'case-studies', 'business-leadership', 'archives'
|
||||
'getting-started', 'resources', 'research-theory', 'technical-reference',
|
||||
'advanced-topics', 'business-leadership', 'archives'
|
||||
];
|
||||
if (!validCategories.includes(category)) {
|
||||
return {
|
||||
|
|
@ -310,13 +310,36 @@ class Document {
|
|||
|
||||
/**
|
||||
* List all documents
|
||||
* @param {object} options
|
||||
* @param {boolean} options.summary - If true, return only summary fields (for sidebar/listing)
|
||||
*/
|
||||
static async list(options = {}) {
|
||||
const collection = await getCollection('documents');
|
||||
const { limit = 50, skip = 0, sort = { order: 1, 'metadata.date_created': -1 }, filter = {} } = options;
|
||||
const { limit = 50, skip = 0, sort = { order: 1, 'metadata.date_created': -1 }, filter = {}, summary = false } = options;
|
||||
|
||||
return await collection
|
||||
.find(filter)
|
||||
const query = collection.find(filter);
|
||||
|
||||
if (summary) {
|
||||
query.project({
|
||||
title: 1,
|
||||
slug: 1,
|
||||
category: 1,
|
||||
order: 1,
|
||||
visibility: 1,
|
||||
quadrant: 1,
|
||||
persistence: 1,
|
||||
audience: 1,
|
||||
download_formats: 1,
|
||||
'metadata.date_created': 1,
|
||||
'metadata.date_updated': 1,
|
||||
'metadata.version': 1,
|
||||
'translations.de.title': 1,
|
||||
'translations.fr.title': 1,
|
||||
'translations.mi.title': 1
|
||||
});
|
||||
}
|
||||
|
||||
return await query
|
||||
.sort(sort)
|
||||
.skip(skip)
|
||||
.limit(limit)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue