diff --git a/packages/akiradocs/package.json b/packages/akiradocs/package.json
index 13d3f4d..0c6f5fc 100644
--- a/packages/akiradocs/package.json
+++ b/packages/akiradocs/package.json
@@ -9,7 +9,8 @@
"dev": "npm run compile && set NEXT_PUBLIC_AKIRADOCS_EDIT_MODE=true && next dev",
"build": "npm run compile && npm run generate-sitemap && set NEXT_PUBLIC_AKIRADOCS_EDIT_MODE=false && next build",
"start": "set NEXT_PUBLIC_AKIRADOCS_EDIT_MODE=false && next start",
- "lint": "next lint"
+ "lint": "next lint",
+ "migrate-gitbook": "node scripts/migrations/gitbook.js"
},
"dependencies": {
"@ai-sdk/anthropic": "^1.0.1",
diff --git a/packages/akiradocs/scripts/compile.js b/packages/akiradocs/scripts/compile.js
index 0aaeed0..3ab70bf 100644
--- a/packages/akiradocs/scripts/compile.js
+++ b/packages/akiradocs/scripts/compile.js
@@ -95,11 +95,32 @@ async function convertMarkdownToBlocks(content) {
continue;
}
+ if (line.trim() === '***') {
+ if (currentBlock.length > 0) {
+ blocks.push({
+ id: String(blockId++),
+ type: 'paragraph',
+ content: currentBlock.join('\n').trim()
+ });
+ currentBlock = [];
+ }
+
+ blocks.push({
+ id: String(blockId++),
+ type: 'divider',
+ content: ''
+ });
+ continue;
+ }
+
if (line.startsWith('#')) {
if (!firstHeadingFound) {
const match = line.match(/^#+\s*(.*)/);
if (match) {
title = match[1].trim();
+ if (title.includes('**')) {
+ title = `${title.replace(/\*\*/g, '')}`;
+ }
firstHeadingFound = true;
skipNextLine = true;
continue;
@@ -119,10 +140,16 @@ async function convertMarkdownToBlocks(content) {
if (!match) continue;
const level = match[0].length;
+ let content = line.slice(level).trim();
+
+ if (content.includes('**')) {
+ content = `${content.replace(/\*\*/g, '')}`;
+ }
+
blocks.push({
id: String(blockId++),
type: 'heading',
- content: line.slice(level).trim(),
+ content: content,
metadata: { level }
});
diff --git a/packages/akiradocs/scripts/migrations/gitbook.js b/packages/akiradocs/scripts/migrations/gitbook.js
new file mode 100644
index 0000000..647b024
--- /dev/null
+++ b/packages/akiradocs/scripts/migrations/gitbook.js
@@ -0,0 +1,125 @@
+const { readFile, writeFile, mkdir } = require('fs/promises');
+const { glob } = require('glob');
+const matter = require('gray-matter');
+const path = require('path');
+const yargs = require('yargs/yargs');
+const { hideBin } = require('yargs/helpers');
+
+function processGitbookContent(content) {
+ // Remove Gitbook-specific content references
+ content = content.replace(/{% content-ref url="(.*?)" %}[\s\S]*?{% endcontent-ref %}/g, '');
+
+ // Convert Gitbook links to standard markdown links
+ content = content.replace(/\[(.*?)\]\((.*?)\.md\)/g, (match, text, url) => {
+ // Remove .md extension and convert to relative path
+ const cleanUrl = url.replace(/\.md$/, '');
+ return `[${text}](${cleanUrl})`;
+ });
+
+ return content;
+}
+
+async function migrateGitbookContent(options) {
+ const {
+ inputDir,
+ outputDir = '_contents',
+ language = 'en',
+ defaultAuthor = 'Anonymous'
+ } = options;
+
+ try {
+ const files = await glob(`${inputDir}/**/*.md`, { cwd: process.cwd() });
+
+ if (files.length === 0) {
+ console.warn(`No markdown files found in ${inputDir}`);
+ return;
+ }
+
+ console.log(`Found ${files.length} files to migrate...`);
+
+ for (const file of files) {
+ const content = await readFile(file, 'utf-8');
+ const { data: frontmatter, content: markdownContent } = matter(content);
+
+ const processedContent = processGitbookContent(markdownContent);
+
+ const newFrontmatter = {
+ title: frontmatter.title || '',
+ description: frontmatter.description || '',
+ author: frontmatter.author || defaultAuthor,
+ publishDate: frontmatter.publishDate || new Date().toISOString().split('T')[0],
+ modifiedDate: frontmatter.modifiedDate || new Date().toISOString().split('T')[0],
+ category: frontmatter.category || '',
+ keywords: frontmatter.keywords || []
+ };
+
+ const newContent = matter.stringify(processedContent, newFrontmatter);
+
+ const newPath = file
+ .replace(new RegExp(`^${inputDir}`), path.join(outputDir, language, 'docs'))
+ .replace(/SUMMARY\.md$/i, 'index.md');
+
+ await mkdir(path.dirname(newPath), { recursive: true });
+ await writeFile(newPath, newContent);
+
+ console.log(`Migrated ${file} -> ${newPath}`);
+ }
+ } catch (error) {
+ console.error('Error migrating Gitbook content:', error);
+ process.exit(1);
+ }
+}
+
+async function main() {
+ const argv = yargs(hideBin(process.argv))
+ .usage('Usage: $0 [options]')
+ .positional('input-dir', {
+ describe: 'Input directory containing Gitbook markdown files',
+ type: 'string'
+ })
+ .option('output-dir', {
+ alias: 'o',
+ type: 'string',
+ description: 'Output directory for processed files',
+ default: '_contents'
+ })
+ .option('language', {
+ alias: 'l',
+ type: 'string',
+ description: 'Language code for the content',
+ default: 'en'
+ })
+ .option('author', {
+ alias: 'a',
+ type: 'string',
+ description: 'Default author name for content without authors',
+ default: 'Anonymous'
+ })
+ .demandCommand(1, 'Please specify an input directory')
+ .help()
+ .argv;
+
+ // Clean up input directory path by removing trailing slashes
+ const inputDir = argv._[0].replace(/\/+$/, '');
+
+ if (!inputDir) {
+ console.error('Input directory is required');
+ process.exit(1);
+ }
+
+ await migrateGitbookContent({
+ inputDir,
+ outputDir: argv.outputDir,
+ language: argv.language,
+ defaultAuthor: argv.author
+ });
+}
+
+module.exports = {
+ main,
+ migrateGitbookContent
+};
+
+if (require.main === module) {
+ main();
+}
diff --git a/packages/akiradocs/src/app/[locale]/[type]/page.tsx b/packages/akiradocs/src/app/[locale]/[type]/page.tsx
index c56bd67..1b964cc 100644
--- a/packages/akiradocs/src/app/[locale]/[type]/page.tsx
+++ b/packages/akiradocs/src/app/[locale]/[type]/page.tsx
@@ -1,7 +1,9 @@
import { Metadata } from 'next'
import { redirect } from 'next/navigation'
-import { getAllPosts, getRecentContent } from '@/lib/content'
+import { getRecentContent } from '@/lib/content'
import { getHeaderConfig } from '@/lib/headerConfig'
+import { getAkiradocsConfig } from '@/lib/getAkiradocsConfig'
+import { Locale } from '@/types/AkiraConfigType'
type Props = {
params: Promise<{
@@ -13,7 +15,8 @@ type Props = {
export const dynamic = 'force-static';
export async function generateStaticParams() {
- const locales = ['en', 'es', 'fr'];
+ const akiraconfig = await getAkiradocsConfig();
+ const locales = akiraconfig.localization.locales.map((locale: Locale) => locale.code);
const types = ['docs', 'api', 'articles'];
const params: { locale: string, type: string }[] = [];
@@ -30,17 +33,18 @@ export async function generateMetadata({ params }: Props): Promise {
const resolvedParams = await Promise.resolve(params);
const { locale, type } = resolvedParams;
const headerConfig = getHeaderConfig();
-
+ const akiraconfig = await getAkiradocsConfig();
return {
title: `${type.charAt(0).toUpperCase() + type.slice(1)} - ${headerConfig.title}`,
description: `Browse our latest ${type}`,
alternates: {
canonical: `${process.env.NEXT_PUBLIC_SITE_URL}/${locale}/${type}`,
- languages: {
- 'en': `${process.env.NEXT_PUBLIC_SITE_URL}/en/${type}`,
- 'es': `${process.env.NEXT_PUBLIC_SITE_URL}/es/${type}`,
- 'fr': `${process.env.NEXT_PUBLIC_SITE_URL}/fr/${type}`,
- }
+ languages: Object.fromEntries(
+ akiraconfig.localization.locales.map((locale: Locale) => [
+ locale.code,
+ `${process.env.NEXT_PUBLIC_SITE_URL}/${locale.code}/${type}`
+ ])
+ )
}
}
}
diff --git a/packages/akiradocs/src/lib/renderers/BlockRenderer.tsx b/packages/akiradocs/src/lib/renderers/BlockRenderer.tsx
index ba5d2a9..b640646 100644
--- a/packages/akiradocs/src/lib/renderers/BlockRenderer.tsx
+++ b/packages/akiradocs/src/lib/renderers/BlockRenderer.tsx
@@ -64,16 +64,20 @@ export function BlockRenderer({ block, isEditing, onUpdate }: BlockRendererProps
);
case 'heading':
+ const hasStrong = block.content.includes('');
return (
onUpdate?.(block.id, content)}
>
- {block.content}
+ {hasStrong ? block.content.replace(/<\/?strong>/g, '') : block.content}
);
case 'list':
diff --git a/packages/akiradocs/src/types/AkiraConfigType.tsx b/packages/akiradocs/src/types/AkiraConfigType.tsx
index fcb3771..7dce737 100644
--- a/packages/akiradocs/src/types/AkiraConfigType.tsx
+++ b/packages/akiradocs/src/types/AkiraConfigType.tsx
@@ -28,7 +28,7 @@ type Logo = {
icon: string;
};
- type Locale = {
+ export type Locale = {
code: string;
name: string;
flag: string;