feat(docs,blog,pages): add support for "unlisted" front matter - hide md content in production (#8004)

Co-authored-by: sebastienlorber <lorber.sebastien@gmail.com>
This commit is contained in:
Jody Heavener 2022-11-03 06:31:41 -07:00 committed by GitHub
parent 7a023a2c41
commit 683ba3d2a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
131 changed files with 2449 additions and 303 deletions

View file

@ -5,7 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/
import {normalizeFrontMatterTags, groupTaggedItems, type Tag} from '../tags';
import {
normalizeFrontMatterTags,
groupTaggedItems,
type Tag,
getTagVisibility,
} from '../tags';
describe('normalizeFrontMatterTags', () => {
it('normalizes simple string tag', () => {
@ -183,3 +188,52 @@ describe('groupTaggedItems', () => {
expect(groupItems(input)).toEqual(expectedOutput);
});
});
describe('getTagVisibility', () => {
type Item = {id: string; unlisted: boolean};
function isUnlisted(item: Item): boolean {
return item.unlisted;
}
const item1: Item = {id: '1', unlisted: false};
const item2: Item = {id: '2', unlisted: true};
const item3: Item = {id: '3', unlisted: false};
const item4: Item = {id: '4', unlisted: true};
it('works for some unlisted', () => {
expect(
getTagVisibility({
items: [item1, item2, item3, item4],
isUnlisted,
}),
).toEqual({
listedItems: [item1, item3],
unlisted: false,
});
});
it('works for all unlisted', () => {
expect(
getTagVisibility({
items: [item2, item4],
isUnlisted,
}),
).toEqual({
listedItems: [item2, item4],
unlisted: true,
});
});
it('works for all listed', () => {
expect(
getTagVisibility({
items: [item1, item3],
isUnlisted,
}),
).toEqual({
listedItems: [item1, item3],
unlisted: false,
});
});
});

View file

@ -0,0 +1,54 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
type Env = 'production' | 'development';
/**
* To easily work on draft/unlisted in dev mode, use this env variable!
* SIMULATE_PRODUCTION_VISIBILITY=true yarn start:website
*/
const simulateProductionVisibility =
process.env.SIMULATE_PRODUCTION_VISIBILITY === 'true';
/**
* draft/unlisted is a production-only concept
* In dev it is ignored and all content files are included
*/
function isProduction(env: Env | undefined): boolean {
return (
simulateProductionVisibility ||
(env ?? process.env.NODE_ENV) === 'production'
);
}
/**
* A draft content will not be included in the production build
*/
export function isDraft({
frontMatter,
env,
}: {
frontMatter: {draft?: boolean};
env?: Env;
}): boolean {
return (isProduction(env) && frontMatter.draft) ?? false;
}
/**
* An unlisted content will be included in the production build, but hidden.
* It is excluded from sitemap, has noIndex, does not appear in lists etc...
* Only users having the link can find it.
*/
export function isUnlisted({
frontMatter,
env,
}: {
frontMatter: {unlisted?: boolean};
env?: Env;
}): boolean {
return (isProduction(env) && frontMatter.unlisted) ?? false;
}

View file

@ -62,6 +62,7 @@ export {
type FrontMatterTag,
normalizeFrontMatterTags,
groupTaggedItems,
getTagVisibility,
} from './tags';
export {
parseMarkdownHeadingId,
@ -103,3 +104,4 @@ export {
findFolderContainingFile,
getFolderContainingFile,
} from './dataFileUtils';
export {isDraft, isUnlisted} from './contentVisibilityUtils';

View file

@ -25,6 +25,8 @@ export type TagsListItem = Tag & {
export type TagModule = TagsListItem & {
/** The tags list page's permalink. */
allTagsPath: string;
/** Is this tag unlisted? (when it only contains unlisted items) */
unlisted: boolean;
};
export type FrontMatterTag = string | Tag;
@ -128,3 +130,32 @@ export function groupTaggedItems<Item>(
return result;
}
/**
* Permits to get the "tag visibility" (hard to find a better name)
* IE, is this tag listed or unlisted
* And which items should be listed when this tag is browsed
*/
export function getTagVisibility<Item>({
items,
isUnlisted,
}: {
items: Item[];
isUnlisted: (item: Item) => boolean;
}): {
unlisted: boolean;
listedItems: Item[];
} {
const allItemsUnlisted = items.every(isUnlisted);
// When a tag is full of unlisted items, we display all the items
// when tag is browsed, but we mark the tag as unlisted
if (allItemsUnlisted) {
return {unlisted: true, listedItems: items};
}
// When a tag has some listed items, the tag remains listed
// but we filter its unlisted items
return {
unlisted: false,
listedItems: items.filter((item) => !isUnlisted(item)),
};
}