Skip to content

Commit e1f34eb

Browse files
Add when a page was last updated into the Docs site (#4341)
* Update husky to 8.0.0 * Init husky * Update cspell to 5.20.0 * Add frontmatter and update cspell to not error when no files found * Read frontmatter from mdx files to get 'lastUpdated' property * Display last updated on page * Remove unused import * Add packages to help set up frontmatter in mdx files * Update custom remark plugin to remove frontmatter * Add a skip section into switch statement * Find first element after frontmatter quicker * Make LastUpdated Provider root element in page.tsx * Add blockquote check when parsing tree during frontmatter plugin * Add last updated dates to mdx files during amplify build * Move addLastUpdated script to preBuild section * Update yarn.lock * Update yarn.lock * Move last updated text into left Menu component * Add 'sh' to supported language for code blocks * Change text to page updated * Add useReducer and useContext to manage state of a page's last updated date * remove comments * Pass down the parent Page last updated date into the provider component * Account for fragments without filterkeys * remove console log * update fragments component for tests * Add comment and table cases for frontmatter plugin * use forwardRef and useImperativeHandle to allow use of ref on function component * Remove relative file path from frontmatter * Set package version for new packages * Update the types * remove outdated code * Add id to html element for page last updated text --------- Co-authored-by: Tim Nguyen <[email protected]>
1 parent c54286b commit e1f34eb

File tree

15 files changed

+1580
-689
lines changed

15 files changed

+1580
-689
lines changed

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env sh
22
. "$(dirname -- "$0")/_/husky.sh"
33

4-
yarn spellcheck-diff
4+
yarn spellcheck-diff

amplify.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ frontend:
44
preBuild:
55
commands:
66
- yarn install
7+
- node tasks/addLastUpdatedToMdxFiles.js
78
build:
89
commands:
910
- echo "API_ENV=$API_ENV" >> .env.custom

next.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ module.exports = async (phase, { defaultConfig }) => {
2323
const codeBlockPlugin = await require('./src/plugins/code-block.tsx');
2424
// eslint-disable-next-line @typescript-eslint/no-var-requires
2525
const importPlugin = await require('./src/plugins/import.tsx');
26+
// eslint-disable-next-line @typescript-eslint/no-var-requires
27+
const frontmatterPlugin = await require('./src/plugins/frontmatter.tsx');
2628

2729
const withMDX = require('@next/mdx')({
2830
extension: /\.mdx$/,
2931
options: {
3032
remarkPlugins: [
33+
frontmatterPlugin,
3134
importPlugin,
3235
headingLinkPlugin,
3336
pagePlugin,

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"dotenv": "^16.0.0",
3131
"emotion": "^10.0.23",
3232
"extract-mdx-metadata": "^2.0.0",
33+
"gray-matter": "4.0.3",
3334
"html-entities": "^1.2.1",
3435
"instantsearch.js": "^4.39.1",
3536
"next": "^12.1.4",
@@ -73,12 +74,14 @@
7374
"eslint-plugin-prettier": "^3.1.1",
7475
"eslint-plugin-react": "^7.16.0",
7576
"fs-extra": "^9.0.1",
77+
"git-jiggy": "1.1.1",
7678
"husky": "^8.0.1",
7779
"jest": "^26.6.3",
7880
"jest-cli": "^26.6.3",
7981
"prettier": "^1.19.1",
8082
"puppeteer": "1.20.0",
8183
"rollup-plugin-node-polyfills": "^0.2.1",
84+
"tiny-glob": "0.2.9",
8285
"sass": "^1.54.8",
8386
"ts-jest": "^26.0.3",
8487
"ts-node": "^8.5.0",
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
import {useRouter} from "next/router";
1+
import { useRouter } from 'next/router';
22

3-
export default function FilterChildren({children}) {
3+
export default function FilterChildren({ children }) {
44
const router = useRouter();
55

6-
let filterKey = "";
7-
if ("platform" in router.query) {
6+
let filterKey = '';
7+
if ('platform' in router.query) {
88
filterKey = router.query.platform as string;
9-
} else if ("integration" in router.query) {
9+
} else if ('integration' in router.query) {
1010
filterKey = router.query.integration as string;
11-
} else if ("framework" in router.query) {
11+
} else if ('framework' in router.query) {
1212
filterKey = router.query.framework as string;
1313
}
14+
1415
const filteredChildren = children.filter(
15-
(el) => el.key === filterKey || el.key === "all",
16+
(el) => el.key === filterKey || el.key === 'all'
1617
);
18+
1719
return filteredChildren;
1820
}

src/components/Fragments/index.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
1-
import FilterChildren from "../FilterChildren";
1+
import FilterChildren from '../FilterChildren';
2+
import { useLastUpdatedDatesContext } from '../LastUpdatedProvider';
3+
import { MdxFrontmatterType } from '../Page';
24

3-
export default function Fragments({fragments}) {
5+
export default function Fragments({ fragments }) {
46
const children = [];
7+
let frontmatter: MdxFrontmatterType;
8+
9+
const { state, dispatch } = useLastUpdatedDatesContext();
10+
511
for (const key in fragments) {
612
const fragment = fragments[key]([]);
13+
frontmatter = fragment.props.frontmatter;
14+
15+
if (frontmatter && frontmatter.lastUpdated) {
16+
if (
17+
state.files[key] === undefined ||
18+
(state.files[key] &&
19+
!state.files[key].includes(frontmatter.lastUpdated))
20+
) {
21+
dispatch({
22+
type: 'update',
23+
key: key,
24+
lastUpdated: frontmatter.lastUpdated
25+
});
26+
}
27+
}
28+
729
children.push(<div key={key}>{fragment}</div>);
830
}
931

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { createContext, useContext, useReducer } from 'react';
2+
3+
type PageLastUpdatedDatesType = {
4+
parentPageLastUpdatedDate: string;
5+
};
6+
7+
type PageLastUpdatedState = {
8+
files: PageLastUpdatedDatesType;
9+
};
10+
11+
const pageLastUpdatedReducer = (
12+
state: PageLastUpdatedState,
13+
action: { type: string; key: string; lastUpdated: string }
14+
) => {
15+
switch (action.type) {
16+
case 'update': {
17+
if (!Object.prototype.hasOwnProperty.call(state.files, action.key)) {
18+
state.files[action.key] = [];
19+
state.files[action.key].push(action.lastUpdated);
20+
} else if (!state.files[action.key].includes(action.lastUpdated)) {
21+
state.files[action.key].push(action.lastUpdated);
22+
}
23+
24+
return {
25+
...state
26+
};
27+
}
28+
default:
29+
return state;
30+
}
31+
};
32+
33+
type LastUpdatedDatesContextType = {
34+
state: PageLastUpdatedState;
35+
dispatch: any;
36+
};
37+
38+
const LastUpdatedDatesContext = createContext<LastUpdatedDatesContextType>({
39+
state: { files: { parentPageLastUpdatedDate: '' } },
40+
dispatch: (action: any) => {
41+
/** no-op */
42+
}
43+
});
44+
45+
export default function LastUpdatedDatesProvider({
46+
children,
47+
parentPageLastUpdatedDate
48+
}) {
49+
const [state, dispatch] = useReducer(pageLastUpdatedReducer, {
50+
files: { parentPageLastUpdatedDate: parentPageLastUpdatedDate }
51+
});
52+
53+
return (
54+
<LastUpdatedDatesContext.Provider value={{ state, dispatch }}>
55+
{children}
56+
</LastUpdatedDatesContext.Provider>
57+
);
58+
}
59+
60+
export function useLastUpdatedDatesContext() {
61+
const context = useContext(LastUpdatedDatesContext);
62+
if (!context) {
63+
throw new Error(
64+
'useLastUpdatedDatesContext must be used within a LastUpdatedDatesProvider'
65+
);
66+
}
67+
68+
return context;
69+
}

0 commit comments

Comments
 (0)