Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(v2): docs versioning ❄️πŸ”₯ #1983

Merged
merged 36 commits into from
Nov 22, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2daebde
wip: versioning
endiliey Nov 6, 2019
b5fa5c2
wip again
endiliey Nov 9, 2019
0d47a21
nits lint
endiliey Nov 11, 2019
d6b61ed
Merge branch 'master' into endi/versioning
endiliey Nov 11, 2019
f3f6d0c
refactor metadata code so that we can have inobject properties optimi…
endiliey Nov 11, 2019
6b72119
remove buggy permalink code
endiliey Nov 11, 2019
9584826
modify versioned docs fixture such that foo/baz only exists in v1.0.0
endiliey Nov 11, 2019
5d15c83
refactor metadata.ts so that there is less transformon object
endiliey Nov 12, 2019
e9f3d1b
more refactoring
endiliey Nov 12, 2019
be470d6
reduce test fixtures, refactoring
endiliey Nov 12, 2019
6842d96
refactoring readability
endiliey Nov 12, 2019
8cb5977
finish metadata part
endiliey Nov 12, 2019
01000f9
refactor with readdir
endiliey Nov 12, 2019
e48b7b8
first pass of implementation
endiliey Nov 12, 2019
3fd93f4
fix mdx laoder
endiliey Nov 12, 2019
1e37e65
Merge branch 'master' into endi/versioning
endiliey Nov 13, 2019
87c368f
Merge branch 'master' into endi/versioning
endiliey Nov 13, 2019
c54ef7f
split generated routes by version for performance & smaller bundle
endiliey Nov 16, 2019
5ac4aef
test data for demo
endiliey Nov 16, 2019
2568db0
refactor with set
endiliey Nov 16, 2019
122b9c7
more tests
endiliey Nov 17, 2019
c4df12c
Merge branch 'master' into endi/versioning
endiliey Nov 19, 2019
64302d0
typo
endiliey Nov 19, 2019
31255ff
fix typo
endiliey Nov 19, 2019
4bd3a1e
better temporary ui
endiliey Nov 19, 2019
0180499
Merge branch 'master' into endi/versioning
endiliey Nov 19, 2019
3fe3ea3
stronger typing & docsVersion command
endiliey Nov 20, 2019
116df01
add 100% test coverage for docsVersion command
endiliey Nov 20, 2019
ec5602a
more test and delete manual docs cut
endiliey Nov 20, 2019
92f115d
cut 2.0.0-alpha.35 docs
endiliey Nov 20, 2019
1875da1
Merge branch 'master' into endi/versioning
endiliey Nov 22, 2019
dae70cc
cut alpha.36 instead
endiliey Nov 22, 2019
1f3deab
copyright
endiliey Nov 22, 2019
d88bbd3
delete versioned docs
endiliey Nov 22, 2019
3740613
stronger test on metadata
endiliey Nov 22, 2019
5f88f8d
update typo
endiliey Nov 22, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -230,32 +230,6 @@ describe('createOrder', () => {
});
});

test('multiple sidebars with unknown sidebar item type', () => {
expect(() =>
createOrder({
docs: [
{
type: 'category',
label: 'Category1',
items: [
{type: 'endi', id: 'doc1'},
{type: 'doc', id: 'doc2'},
],
},
],
otherDocs: [
{
type: 'category',
label: 'Category1',
items: [{type: 'doc', id: 'doc5'}],
},
],
}),
).toThrowErrorMatchingInlineSnapshot(
`"Unknown item type: endi. Item: {\\"type\\":\\"endi\\",\\"id\\":\\"doc1\\"}"`,
);
});

test('edge cases', () => {
expect(createOrder({})).toEqual({});
expect(createOrder(undefined)).toEqual({});
Expand Down
18 changes: 15 additions & 3 deletions packages/docusaurus-plugin-content-docs/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ import {
VERSIONED_SIDEBARS_DIR,
} from './constants';

export function getVersionedDocsDir(siteDir: string) {
return path.join(siteDir, VERSIONED_DOCS_DIR);
}

export function getVersionedSidebarsDir(siteDir: string) {
return path.join(siteDir, VERSIONED_SIDEBARS_DIR);
}

export function getVersionsJSONFile(siteDir: string) {
return path.join(siteDir, VERSIONS_JSON_FILE);
}

export default function(siteDir: string): Env {
const versioning: VersioningEnv = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In future, i'll add translation to this env. So this PR is like a building block for translated docs already

enabled: false,
Expand All @@ -23,7 +35,7 @@ export default function(siteDir: string): Env {
sidebarsDir: '',
};

const versionsJSONFile = path.join(siteDir, VERSIONS_JSON_FILE);
const versionsJSONFile = getVersionsJSONFile(siteDir);
if (fs.existsSync(versionsJSONFile)) {
const parsedVersions = JSON.parse(
fs.readFileSync(versionsJSONFile, 'utf8'),
Expand All @@ -32,8 +44,8 @@ export default function(siteDir: string): Env {
versioning.latestVersion = parsedVersions[0];
versioning.enabled = true;
versioning.versions = parsedVersions;
(versioning.docsDir = path.join(siteDir, VERSIONED_DOCS_DIR)),
(versioning.sidebarsDir = path.join(siteDir, VERSIONED_SIDEBARS_DIR));
versioning.docsDir = getVersionedDocsDir(siteDir);
versioning.sidebarsDir = getVersionedSidebarsDir(siteDir);
}
}

Expand Down
11 changes: 11 additions & 0 deletions packages/docusaurus-plugin-content-docs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
VersionToSidebars,
} from './types';
import {Configuration} from 'webpack';
import {docsVersion} from './version';

const DEFAULT_OPTIONS: PluginOptions = {
path: 'docs', // Path to data on filesystem, relative to site dir.
Expand Down Expand Up @@ -78,6 +79,16 @@ export default function pluginContentDocs(
return {
name: 'docusaurus-plugin-content-docs',

extendCli(cli) {
cli
.command('docs:version')
.arguments('<version>')
.description('Tag a new version for docs')
.action(version => {
docsVersion(version, siteDir, options);
});
},

getPathsToWatch() {
const {include} = options;
let globPattern = include.map(pattern => `${docsDir}/${pattern}`);
Expand Down
16 changes: 3 additions & 13 deletions packages/docusaurus-plugin-content-docs/src/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import {
Sidebar,
SidebarItem,
SidebarItemDoc,
SidebarItemCategory,
Order,
} from './types';
import {Sidebar, SidebarItem, Order} from './types';

// Build the docs meta such as next, previous, category and sidebar.
export default function createOrder(allSidebars: Sidebar = {}): Order {
Expand All @@ -26,20 +20,16 @@ export default function createOrder(allSidebars: Sidebar = {}): Order {
switch (item.type) {
case 'category':
indexItems({
items: (item as SidebarItemCategory).items,
items: item.items,
});
break;
case 'ref':
case 'link':
// Refs and links should not be shown in navigation.
break;
case 'doc':
ids.push((item as SidebarItemDoc).id);
ids.push(item.id);
break;
default:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a never, All errors checking has been done in loadSidebars

throw new Error(
`Unknown item type: ${item.type}. Item: ${JSON.stringify(item)}`,
);
}
});
};
Expand Down
18 changes: 11 additions & 7 deletions packages/docusaurus-plugin-content-docs/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@ export interface PluginOptions extends MetadataOptions {
}

export type SidebarItemDoc = {
type: string;
type: 'doc' | 'ref';
id: string;
};

export interface SidebarItemLink {
type: string;
type: 'link';
href: string;
label: string;
}

export interface SidebarItemCategory {
type: string;
type: 'category';
label: string;
items: SidebarItem[];
}

export interface SidebarItemCategoryRaw {
type: string;
type: 'category';
label: string;
items: SidebarItemRaw[];
}
Expand All @@ -54,7 +54,11 @@ export type SidebarItemRaw =
| string
| SidebarItemDoc
| SidebarItemLink
| SidebarItemCategoryRaw;
| SidebarItemCategoryRaw
| {
type: string;
[key: string]: any;
};

// Sidebar given by user that is not normalized yet. e.g: sidebars.json
export interface SidebarRaw {
Expand All @@ -68,7 +72,7 @@ export interface Sidebar {
}

export interface DocsSidebarItemCategory {
type: string;
type: 'category';
label: string;
items: (SidebarItemLink | DocsSidebarItemCategory)[];
}
Expand Down Expand Up @@ -137,7 +141,7 @@ export interface VersionToSidebars {
export interface LoadedContent {
docsMetadata: DocsMetadata;
docsDir: string;
docsSidebars: Sidebar;
docsSidebars: DocsSidebar;
permalinkToSidebar: PermalinkToSidebar;
versionToSidebars: VersionToSidebars;
}
Expand Down
113 changes: 113 additions & 0 deletions packages/docusaurus-plugin-content-docs/src/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {
getVersionsJSONFile,
getVersionedDocsDir,
getVersionedSidebarsDir,
} from './env';
import fs from 'fs-extra';
import path from 'path';
import {PluginOptions, Sidebar, SidebarItemCategory} from './types';
import loadSidebars from './sidebars';

export function docsVersion(
version: string | null | undefined,
siteDir: string,
options: PluginOptions,
) {
if (!version) {
throw new Error(
'No version number specified!.\nPass the version you wish to create as an argument.\nEx: 1.0.0',
);
}
if (version.includes('/')) {
throw new Error(
'Invalid version number specified! Do not include slash (/). Try something like: 1.0.0',
);
}

// Load existing versions
let versions = [];
const versionsJSONFile = getVersionsJSONFile(siteDir);
if (fs.existsSync(versionsJSONFile)) {
versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8'));
}

// Check if version already exist
if (versions.includes(version)) {
throw new Error(
'This version already exists!.\nSpecify a new version to create that does not already exist.',
);
}

const {path: docsPath, sidebarPath} = options;

// Copy docs files
const docsDir = path.join(siteDir, docsPath);
if (fs.existsSync(docsDir)) {
const versionedDir = getVersionedDocsDir(siteDir);
const newVersionDir = path.join(versionedDir, `version-${version}`);

fs.copy(docsDir, newVersionDir);
}

// Load current sidebar and create a new versioned sidebars file
if (fs.existsSync(sidebarPath)) {
const loadedSidebars: Sidebar = loadSidebars([sidebarPath]);

// Transform id in original sidebar to versioned id
const normalizeCategory = (
category: SidebarItemCategory,
): SidebarItemCategory => {
const items = category.items.map(item => {
switch (item.type) {
case 'category':
return normalizeCategory(item);
case 'ref':
case 'doc':
return {
type: item.type,
id: `version-${version}/${item.id}`,
};
}
return item;
});
return {...category, items};
};

const versionedSidebar: Sidebar = Object.entries(loadedSidebars).reduce(
(acc: Sidebar, [sidebarId, sidebarItemCategories]) => {
const newVersionedSidebarId = `version-${version}/${sidebarId}`;
acc[
newVersionedSidebarId
] = sidebarItemCategories.map(sidebarItemCategory =>
normalizeCategory(sidebarItemCategory),
);
return acc;
},
{},
);

const versionedSidebarsDir = getVersionedSidebarsDir(siteDir);
const newSidebarFile = path.join(
versionedSidebarsDir,
`version-${version}-sidebars.json`,
);
fs.writeFileSync(
newSidebarFile,
`${JSON.stringify(versionedSidebar, null, 2)}\n`,
'utf8',
);
}

// update versions.json file
versions.unshift(version);
fs.writeFileSync(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);

console.log(`Version ${version} created!\n`);
}