From d3a406a72eec01071620d2f0635b02c897be7e54 Mon Sep 17 00:00:00 2001 From: Saurav Panda Date: Mon, 9 Dec 2024 22:06:16 -0800 Subject: [PATCH] fix: updated compile code to maintain the formatting --- docs/public/context/en_docs.txt | 276 +++++++++++++------------- docs/scripts/compile.js | 90 +++++---- packages/akiradocs/scripts/compile.js | 90 +++++---- packages/create-app/package.json | 2 +- 4 files changed, 237 insertions(+), 221 deletions(-) diff --git a/docs/public/context/en_docs.txt b/docs/public/context/en_docs.txt index bd23552..fb064c6 100644 --- a/docs/public/context/en_docs.txt +++ b/docs/public/context/en_docs.txt @@ -474,55 +474,6 @@ Code example: }, } ------------- -[Document: docs/guides/analytics.json] -Title: Analytics Integration -Learn how to add analytics tracking to your documentation -AkiraDocs supports Google Analytics 4 (GA4) out of the box. This guide will help you set up analytics tracking for your documentation. -Setting up Google Analytics -1. Create a Google Analytics 4 property in your [Google Analytics account](https://analytics.google.com/) -2. Get your Measurement ID (starts with "G-") -3. Add the ID to your `akiradocs.config.json`: -Code example: -{ -"analytics": { -"google": { -"measurementId": "G-XXXXXXXXXX", -"enabled": true -}, -"debug": false -} -} -What's Tracked Automatically -Page views -Navigation between pages -Time on page -User language preferences -Device and browser information -Custom Event Tracking -You can track custom events using the `useAnalytics` hook: -Code example: -import { useAnalytics } from '@/hooks/useAnalytics' -function MyComponent() { - const { track } = useAnalytics() - const handleClick = () => { - track('doc_rating', { - rating: 5, - page: 'getting-started', - helpful: true - }) - } - return -} -Debug Mode -Enable debug mode to see analytics events in the console during development: -Code example: -{ -"analytics": { -"debug": true -} -} -This provides a complete analytics integration that's easy for users to set up and extend as needed. -------------- [Document: docs/getting-started/requirements.json] Title: System Requirements Before installing AkiraDocs, ensure your environment meets the following requirements. @@ -631,98 +582,54 @@ Code example: ✓ Docusaurus ✓ ReadTheDocs ------------- -[Document: docs/editor/overview.json] -Title: Editor Overview -AkiraDocs features a modern, Notion-like editor that combines the simplicity of block-based editing with the power of Markdown. -Editor Interface -Main Components -Toolbar: Quick access to formatting options and block types -Content Area: Block-based editing space -Sidebar: Navigation and document structure -Command Palette: Quick commands (Ctrl/Cmd + P) -Block Structure -Each content element is a block that can be: -Dragged and dropped to reorganize -Converted between different types -Duplicated or deleted -Nested within other blocks -Getting Started -Creating Content -1. Click the '+' button or press '/' to add a new block -2. Choose block type from the popup menu -3. Start typing or add content -Basic Operations +[Document: docs/guides/analytics.json] +Title: Analytics Integration +Learn how to add analytics tracking to your documentation +AkiraDocs supports Google Analytics 4 (GA4) out of the box. This guide will help you set up analytics tracking for your documentation. +Setting up Google Analytics +1. Create a Google Analytics 4 property in your [Google Analytics account](https://analytics.google.com/) +2. Get your Measurement ID (starts with "G-") +3. Add the ID to your `akiradocs.config.json`: Code example: -/ → Open block menu -⌘/Ctrl + P → Command palette -⌘/Ctrl + / → Show keyboard shortcuts -↑↓ → Navigate between blocks -Block Types -Text Blocks -Paragraphs -Headings (H1-H6) -Lists (Bulleted, Numbered) -Quotes -Callouts -Rich Media -Images -Videos -Embeds -Files -Code blocks -Special Blocks -Tables (Coming Soon) -Dividers -Custom components (Coming Soon) -------------- -[Document: docs/editor/features.json] -Title: Editor Features -Detailed overview of AkiraDocs editor capabilities and features. -Block System -Text Formatting -Basic Formatting -Bold, italic, underline -Strikethrough -Highlight -Code inline -Advanced Formatting -Custom colors -Multiple fonts -Text alignment -Indentation -Content Blocks -Rich Text +{ +"analytics": { +"google": { +"measurementId": "G-XXXXXXXXXX", +"enabled": true +}, +"debug": false +} +} +What's Tracked Automatically +Page views +Navigation between pages +Time on page +User language preferences +Device and browser information +Custom Event Tracking +You can track custom events using the `useAnalytics` hook: Code example: -# Heading 1 -## Heading 2 -> Blockquote -- Bullet list -1. Numbered list -Code Blocks +import { useAnalytics } from '@/hooks/useAnalytics' +function MyComponent() { + const { track } = useAnalytics() + const handleClick = () => { + track('doc_rating', { + rating: 5, + page: 'getting-started', + helpful: true + }) + } + return +} +Debug Mode +Enable debug mode to see analytics events in the console during development: Code example: -// Syntax highlighting -console.log('Hello World'); -Media Blocks -Image upload and embedding -Video embedding -File attachments -Interactive embeds -AI Features -Content Enhancement -Grammar and style suggestions -Content optimization -SEO recommendations -Translation assistance -Smart Formatting -Auto-formatting -Smart lists -Table formatting -Code block language detection -Collaboration Features -Version Control -Git integration -Change history -Rollback capabilities +{ +"analytics": { +"debug": true +} +} +This provides a complete analytics integration that's easy for users to set up and extend as needed. ------------- [Document: docs/contributing/how-to-contribute.json] Title: Contributing to AkiraDocs @@ -817,6 +724,99 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be repor Attribution This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. ------------- +[Document: docs/editor/overview.json] +Title: Editor Overview +AkiraDocs features a modern, Notion-like editor that combines the simplicity of block-based editing with the power of Markdown. +Editor Interface +Main Components +Toolbar: Quick access to formatting options and block types +Content Area: Block-based editing space +Sidebar: Navigation and document structure +Command Palette: Quick commands (Ctrl/Cmd + P) +Block Structure +Each content element is a block that can be: +Dragged and dropped to reorganize +Converted between different types +Duplicated or deleted +Nested within other blocks +Getting Started +Creating Content +1. Click the '+' button or press '/' to add a new block +2. Choose block type from the popup menu +3. Start typing or add content +Basic Operations +Code example: +/ → Open block menu +⌘/Ctrl + P → Command palette +⌘/Ctrl + / → Show keyboard shortcuts +↑↓ → Navigate between blocks +Block Types +Text Blocks +Paragraphs +Headings (H1-H6) +Lists (Bulleted, Numbered) +Quotes +Callouts +Rich Media +Images +Videos +Embeds +Files +Code blocks +Special Blocks +Tables (Coming Soon) +Dividers +Custom components (Coming Soon) +------------- +[Document: docs/editor/features.json] +Title: Editor Features +Detailed overview of AkiraDocs editor capabilities and features. +Block System +Text Formatting +Basic Formatting +Bold, italic, underline +Strikethrough +Highlight +Code inline +Advanced Formatting +Custom colors +Multiple fonts +Text alignment +Indentation +Content Blocks +Rich Text +Code example: +# Heading 1 +## Heading 2 +> Blockquote +- Bullet list +1. Numbered list +Code Blocks +Code example: +// Syntax highlighting +console.log('Hello World'); +Media Blocks +Image upload and embedding +Video embedding +File attachments +Interactive embeds +AI Features +Content Enhancement +Grammar and style suggestions +Content optimization +SEO recommendations +Translation assistance +Smart Formatting +Auto-formatting +Smart lists +Table formatting +Code block language detection +Collaboration Features +Version Control +Git integration +Change history +Rollback capabilities +------------- [Document: docs/content-management/creating-pages.json] Title: Creating and Organizing Pages Learn how to create, structure, and organize your documentation pages in AkiraDocs. You can create markdown pages or just use the editor UI. Note in _contents folder, you will only see markdown content created by you. If you use Editor UI, the content will be saved in the compiled folder and will be automatically translated to other languages. diff --git a/docs/scripts/compile.js b/docs/scripts/compile.js index 7d79527..f103660 100644 --- a/docs/scripts/compile.js +++ b/docs/scripts/compile.js @@ -307,69 +307,59 @@ async function createMetaFilesForAllFolders() { const sectionPath = path.join(langPath, section); if (!existsSync(sectionPath)) continue; + // Read existing meta file and preserve its structure let existingMeta = {}; const metaPath = path.join(sectionPath, '_meta.json'); - let existingDefaultRoute; - + if (existsSync(metaPath)) { - existingMeta = JSON.parse(await readFile(metaPath, 'utf-8')); - existingDefaultRoute = existingMeta.defaultRoute; + const metaContent = await readFile(metaPath, 'utf-8'); + try { + existingMeta = JSON.parse(metaContent); + } catch (e) { + console.warn(`Warning: Invalid JSON in ${metaPath}`); + } } + // Initialize meta with existing structure + const meta = { + defaultRoute: existingMeta.defaultRoute || (section === 'docs' ? '/docs/introduction' : '/articles/welcome'), + ...existingMeta + }; + + // Get all JSON files except _meta.json const jsonFiles = await glob('**/*.json', { cwd: sectionPath, ignore: ['**/_meta.json'] }); - const meta = { - defaultRoute: existingDefaultRoute || (section === 'docs' ? '/docs/introduction' : '/articles/welcome') - }; - + // Process each file and update the structure for (const jsonFile of jsonFiles) { const fileName = path.basename(jsonFile, '.json'); const filePath = path.join(sectionPath, jsonFile); const content = JSON.parse(await readFile(filePath, 'utf-8')); const dirs = path.dirname(jsonFile).split(path.sep).filter(d => d !== '.'); - const fileKey = fileName.replace(/-/g, ' ') - .split(' ') - .map((word, index) => { - const capitalized = word.charAt(0).toUpperCase() + word.slice(1); - return index === 0 ? capitalized.toLowerCase() : capitalized; - }) - .join(''); - + // Create nested structure while preserving existing data let current = meta; - - if (dirs.length > 0) { - for (const dir of dirs) { - const dirKey = dir.replace(/-/g, ' ') - .split(' ') - .map((word, index) => { - const capitalized = word.charAt(0).toUpperCase() + word.slice(1); - return index === 0 ? capitalized.toLowerCase() : capitalized; - }) - .join(''); - - if (!current[dirKey]) { - current[dirKey] = { - title: dir.split('_') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '), - items: {} - }; - } - current = current[dirKey].items; + for (const dir of dirs) { + const dirKey = formatKey(dir); + if (!current[dirKey]) { + current[dirKey] = { + title: formatTitle(dir), + items: {} + }; + } else if (!current[dirKey].items) { + current[dirKey].items = {}; } + current = current[dirKey].items; } + const fileKey = formatKey(fileName); const existingEntry = findExistingEntry(existingMeta, dirs, fileKey); - const title = existingEntry?.title || content.title || fileName.split('_') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); - + current[fileKey] = { - title, + ...existingEntry, // Preserve existing metadata + title: existingEntry?.title || content.title || formatTitle(fileName), path: `/${section}/${jsonFile.replace('.json', '')}` }; } @@ -384,6 +374,24 @@ async function createMetaFilesForAllFolders() { } } +// Helper function to format keys consistently +function formatKey(str) { + return str.replace(/-/g, ' ') + .split(' ') + .map((word, index) => { + const capitalized = word.charAt(0).toUpperCase() + word.slice(1); + return index === 0 ? capitalized.toLowerCase() : capitalized; + }) + .join(''); +} + +// Helper function to format titles consistently +function formatTitle(str) { + return str.split(/[_-]/) + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); +} + function findExistingEntry(meta, dirs, fileKey) { let current = meta; diff --git a/packages/akiradocs/scripts/compile.js b/packages/akiradocs/scripts/compile.js index 7d79527..f103660 100644 --- a/packages/akiradocs/scripts/compile.js +++ b/packages/akiradocs/scripts/compile.js @@ -307,69 +307,59 @@ async function createMetaFilesForAllFolders() { const sectionPath = path.join(langPath, section); if (!existsSync(sectionPath)) continue; + // Read existing meta file and preserve its structure let existingMeta = {}; const metaPath = path.join(sectionPath, '_meta.json'); - let existingDefaultRoute; - + if (existsSync(metaPath)) { - existingMeta = JSON.parse(await readFile(metaPath, 'utf-8')); - existingDefaultRoute = existingMeta.defaultRoute; + const metaContent = await readFile(metaPath, 'utf-8'); + try { + existingMeta = JSON.parse(metaContent); + } catch (e) { + console.warn(`Warning: Invalid JSON in ${metaPath}`); + } } + // Initialize meta with existing structure + const meta = { + defaultRoute: existingMeta.defaultRoute || (section === 'docs' ? '/docs/introduction' : '/articles/welcome'), + ...existingMeta + }; + + // Get all JSON files except _meta.json const jsonFiles = await glob('**/*.json', { cwd: sectionPath, ignore: ['**/_meta.json'] }); - const meta = { - defaultRoute: existingDefaultRoute || (section === 'docs' ? '/docs/introduction' : '/articles/welcome') - }; - + // Process each file and update the structure for (const jsonFile of jsonFiles) { const fileName = path.basename(jsonFile, '.json'); const filePath = path.join(sectionPath, jsonFile); const content = JSON.parse(await readFile(filePath, 'utf-8')); const dirs = path.dirname(jsonFile).split(path.sep).filter(d => d !== '.'); - const fileKey = fileName.replace(/-/g, ' ') - .split(' ') - .map((word, index) => { - const capitalized = word.charAt(0).toUpperCase() + word.slice(1); - return index === 0 ? capitalized.toLowerCase() : capitalized; - }) - .join(''); - + // Create nested structure while preserving existing data let current = meta; - - if (dirs.length > 0) { - for (const dir of dirs) { - const dirKey = dir.replace(/-/g, ' ') - .split(' ') - .map((word, index) => { - const capitalized = word.charAt(0).toUpperCase() + word.slice(1); - return index === 0 ? capitalized.toLowerCase() : capitalized; - }) - .join(''); - - if (!current[dirKey]) { - current[dirKey] = { - title: dir.split('_') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '), - items: {} - }; - } - current = current[dirKey].items; + for (const dir of dirs) { + const dirKey = formatKey(dir); + if (!current[dirKey]) { + current[dirKey] = { + title: formatTitle(dir), + items: {} + }; + } else if (!current[dirKey].items) { + current[dirKey].items = {}; } + current = current[dirKey].items; } + const fileKey = formatKey(fileName); const existingEntry = findExistingEntry(existingMeta, dirs, fileKey); - const title = existingEntry?.title || content.title || fileName.split('_') - .map(word => word.charAt(0).toUpperCase() + word.slice(1)) - .join(' '); - + current[fileKey] = { - title, + ...existingEntry, // Preserve existing metadata + title: existingEntry?.title || content.title || formatTitle(fileName), path: `/${section}/${jsonFile.replace('.json', '')}` }; } @@ -384,6 +374,24 @@ async function createMetaFilesForAllFolders() { } } +// Helper function to format keys consistently +function formatKey(str) { + return str.replace(/-/g, ' ') + .split(' ') + .map((word, index) => { + const capitalized = word.charAt(0).toUpperCase() + word.slice(1); + return index === 0 ? capitalized.toLowerCase() : capitalized; + }) + .join(''); +} + +// Helper function to format titles consistently +function formatTitle(str) { + return str.split(/[_-]/) + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); +} + function findExistingEntry(meta, dirs, fileKey) { let current = meta; diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 9558a40..60e9605 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "create-akiradocs", - "version": "1.0.44", + "version": "1.0.45", "description": "Create Akira Docs documentation sites with one command", "main": "./dist/index.js", "type": "module",