diff --git a/src/config.js b/src/config.js index 4f44336..6f635ec 100644 --- a/src/config.js +++ b/src/config.js @@ -120,6 +120,12 @@ export async function getConfig(hugoConfig) { ...file, base_url: baseUrl === '/' ? '' : baseUrl, source: file.source || paths.source || '', + multilingual: { + languages: hugoConfig.languages || [], + defaultContentLanguage: hugoConfig.defaultContentLanguage || '', + defaultContentLanguageInSubdir: hugoConfig.defaultContentLanguageInSubdir || false, + disableLanguages: hugoConfig.disableLanguages || [], + }, paths: { ...paths, ...file.paths diff --git a/src/generators/collections.js b/src/generators/collections.js index a406953..bb2ed8d 100644 --- a/src/generators/collections.js +++ b/src/generators/collections.js @@ -113,23 +113,36 @@ function isIndex(path) { return !!path.match(/\/_?index\.(md|html?)$/); } -export function getPageUrlFromPath(path, contentDir) { +export function getPageUrlFromPath(path, contentDir, multilingualOptions = {}) { if (!isIndex(path)) { return; } - return path + const languageCodes = pathHelper.getSupportedLanguages(); + const defaultLanguage = multilingualOptions.defaultContentLanguage; + const prependLanguageCode = multilingualOptions.defaultContentLanguageInSubdir === true; + + let unprocessedUrl = path .replace(`${contentDir || ''}/`, '/') - .replace(/\/_?index\.(md|html?)/, '/') + .replace(/\/_?index\.(md|html?)/, '/'); + + if (!!defaultLanguage && prependLanguageCode) { + const rootFolder = unprocessedUrl.split('/')?.[1] || '/'; + if (rootFolder && !(languageCodes.includes(rootFolder))) { + unprocessedUrl = `/${defaultLanguage}${unprocessedUrl}`; + } + } + + return unprocessedUrl .replace(/\/+/g, '/'); } -async function processItem(path, collectionKey, hugoUrls) { +async function processItem({ path, collectionKey, hugoUrls, multilingual }) { const paths = pathHelper.getPaths(); const parsed = await parseFile(join(paths.source, path)); const item = { - url: hugoUrls[path] || getPageUrlFromPath(path, paths.content) || '', + url: hugoUrls[path] || getPageUrlFromPath(path, paths.content, multilingual) || '', path, collection: collectionKey, ...parsed @@ -190,7 +203,7 @@ export async function getCollectionsAndConfig(config, hugoUrls) { } log(`Parsing ${chalk.green(path)} into ${chalk.bold(collectionKey)} collection`, 'debug'); - const item = await processItem(path, collectionKey, hugoUrls); + const item = await processItem({ path, collectionKey, hugoUrls, multilingual: config.multilingual }); collections[collectionKey] = collections[collectionKey] || []; collections[collectionKey].push(item); diff --git a/src/generators/info.js b/src/generators/info.js index 22e4d72..546bbbb 100644 --- a/src/generators/info.js +++ b/src/generators/info.js @@ -38,6 +38,9 @@ export async function getInfo(hugoConfig, options) { const data = await getData(config); const generator = await getGenerator(hugoConfig); + // multlingual not needed in info.json + delete config.multilingual; + return { ...config, time: new Date().toISOString(), diff --git a/src/helpers/paths.js b/src/helpers/paths.js index f4fcbad..febd3f3 100644 --- a/src/helpers/paths.js +++ b/src/helpers/paths.js @@ -1,4 +1,4 @@ -import { dirname, join } from 'path'; +import { join } from 'path'; import { getGlob } from './globs.js'; let cachedPaths; @@ -46,6 +46,15 @@ export function getSupportedLanguages(hugoConfig = {}) { return cachedLanguages; } +export function clearAllCachedItems() { + clearCachedLanguages(); + clearCachedLayouts(); +} + +export function clearCachedLanguages() { + cachedLanguages = null; +} + export function clearCachedLayouts() { cachedLayouts = null; } @@ -117,6 +126,8 @@ export default { getPaths, getSupportedLanguages, clearCachedLayouts, + clearCachedLanguages, + clearAllCachedItems, generatePaths, getDataPaths, getLayoutTree, diff --git a/test/generators/collections.test.js b/test/generators/collections.test.js index 966fd49..694829a 100644 --- a/test/generators/collections.test.js +++ b/test/generators/collections.test.js @@ -98,7 +98,7 @@ describe('collections generator', function () { describe('getLayout', function () { before(function () { - pathHelper.clearCachedLayouts(); + pathHelper.clearAllCachedItems(); mock(testFileStructure); pathHelper.getSupportedLanguages({ languages: { en: {} } }); }); @@ -175,7 +175,7 @@ describe('collections generator', function () { after(function () { mock.restore(); - pathHelper.clearCachedLayouts(); + pathHelper.clearAllCachedItems(); }); }); @@ -185,7 +185,7 @@ describe('collections generator', function () { ...collectionFiles, 'data/staff_members': { 'anna.yml': '' } }; - + pathHelper.clearAllCachedItems(); mock(fileStructure); }); @@ -306,6 +306,7 @@ describe('collections generator', function () { after(function () { mock.restore(); + pathHelper.clearAllCachedItems(); }); }); }); diff --git a/test/helpers/paths.test.js b/test/helpers/paths.test.js index 92fa8c2..c402d0f 100644 --- a/test/helpers/paths.test.js +++ b/test/helpers/paths.test.js @@ -25,7 +25,7 @@ describe('pathHelper', function () { describe('getLayoutTree', function () { before(function () { - pathHelper.clearCachedLayouts(); + pathHelper.clearAllCachedItems(); }); it('should create a layout tree using layout file structure', async function () { diff --git a/test/integration/integration.test.js b/test/integration/integration.test.js index 402857f..d9edb23 100644 --- a/test/integration/integration.test.js +++ b/test/integration/integration.test.js @@ -70,6 +70,10 @@ describe('integration should generate info.json', function () { await run('collections-config-override'); }); + it('with multilingual pages', async function () { + await run('multilingual'); + }); + it('with legacy config', async function () { await run('legacy', ['--config', 'cloudcannon.toml,config.toml']); }); diff --git a/test/integration/multilingual.json b/test/integration/multilingual.json new file mode 100644 index 0000000..f31c73e --- /dev/null +++ b/test/integration/multilingual.json @@ -0,0 +1,49 @@ +{ + "base_url": "", + "source": "", + "paths": { + "source": "", + "archetypes": "archetypes", + "assets": "assets", + "content": "content", + "pages": "content", + "data": "data", + "layouts": "layouts", + "publish": "public", + "static": "static", + "uploads": "static/uploads", + "config": "" + }, + "time": "UNCHECKED", + "version": "0.0.3", + "cloudcannon": "UNCHECKED", + "generator": "UNCHECKED", + "collections_config": { + "pages": { + "output": true, + "filter": "strict", + "parse_branch_index": true, + "auto_discovered": true, + "path": "content" + } + }, + "collections": { + "pages": [ + { + "url": "/en/", + "path": "content/_index.md", + "collection": "pages", + "title": "index", + "content_path": "_index.md", + "layout": "index" + }, + { + "url": "/en/about/", + "path": "content/about.md", + "collection": "pages", + "title": "About", + "content_path": "about.md" + } + ] + } +} \ No newline at end of file diff --git a/test/integration/multilingual/archetypes/default.md b/test/integration/multilingual/archetypes/default.md new file mode 100644 index 0000000..00e77bd --- /dev/null +++ b/test/integration/multilingual/archetypes/default.md @@ -0,0 +1,6 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +draft: true +--- + diff --git a/test/integration/multilingual/config.toml b/test/integration/multilingual/config.toml new file mode 100644 index 0000000..4ffd47b --- /dev/null +++ b/test/integration/multilingual/config.toml @@ -0,0 +1,16 @@ +baseURL = 'http://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' +disableKinds = ['term', 'taxonomy', 'section'] + +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true + +[languages] +[languages.de] +title = 'Mein blog' +contentDir = 'content/de/nested' +weight = 2 +[languages.en] +title = 'My blog' +weight = 1 \ No newline at end of file diff --git a/test/integration/multilingual/content/_index.md b/test/integration/multilingual/content/_index.md new file mode 100644 index 0000000..069defd --- /dev/null +++ b/test/integration/multilingual/content/_index.md @@ -0,0 +1,5 @@ +--- +title: index +--- + +Home page content. \ No newline at end of file diff --git a/test/integration/multilingual/content/about.md b/test/integration/multilingual/content/about.md new file mode 100644 index 0000000..b6f3f85 --- /dev/null +++ b/test/integration/multilingual/content/about.md @@ -0,0 +1,5 @@ +--- +title: About +--- + +We are a company. \ No newline at end of file diff --git a/test/integration/multilingual/layouts/_default/_list.html b/test/integration/multilingual/layouts/_default/_list.html new file mode 100644 index 0000000..72e636a --- /dev/null +++ b/test/integration/multilingual/layouts/_default/_list.html @@ -0,0 +1,5 @@ +{{ define "main" }} +
+ {{ .Content }} +
+{{ end }} \ No newline at end of file diff --git a/test/integration/multilingual/layouts/_default/baseof.html b/test/integration/multilingual/layouts/_default/baseof.html new file mode 100644 index 0000000..80af9d5 --- /dev/null +++ b/test/integration/multilingual/layouts/_default/baseof.html @@ -0,0 +1,10 @@ + + + + + + + + {{ block "main" . }} {{ end }} + + \ No newline at end of file diff --git a/test/integration/multilingual/layouts/index.html b/test/integration/multilingual/layouts/index.html new file mode 100644 index 0000000..7e817aa --- /dev/null +++ b/test/integration/multilingual/layouts/index.html @@ -0,0 +1,3 @@ +
+ {{ .Content }} +
\ No newline at end of file