@bbc/morty-docs 3.0.3 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/build/index.js +567 -6
- package/package.json +18 -24
- package/build/generate-indexes.js +0 -46
- package/build/generate-transform-input.js +0 -54
- package/build/helpers/filter-dirs-in-dir.js +0 -21
- package/build/helpers/filter-files-in-dir.js +0 -10
- package/build/helpers/get-directory-paths.js +0 -24
- package/build/helpers/get-header-paths.js +0 -14
- package/build/helpers/sort-array-by-date.js +0 -11
- package/build/markdown-to-html-parser.js +0 -64
- package/build/page-renderers/Components/Footer.js +0 -29
- package/build/page-renderers/Components/Header.js +0 -59
- package/build/page-renderers/Components/IndexListItem.js +0 -58
- package/build/page-renderers/Components/PrettyDate.js +0 -23
- package/build/page-renderers/Components/Reset.js +0 -61
- package/build/page-renderers/Components/Title.js +0 -23
- package/build/page-renderers/Components/icons/IconFileLines.js +0 -12
- package/build/page-renderers/Components/icons/IconFolderOpen.js +0 -12
- package/build/page-renderers/IndexPage.js +0 -84
- package/build/page-renderers/MortyPage.js +0 -211
- package/build/transform-content.js +0 -26
- package/build/transform.js +0 -24
package/package.json
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bbc/morty-docs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "To generate a static website from markdown documentation, to allow users to consume content in an easily accessible format",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"start": "rm -rf www && npm run build -- --
|
|
13
|
-
"build": "rm -rf build &&
|
|
14
|
-
"build-watch": "npm run build -- --source-maps --watch",
|
|
10
|
+
"prepare": "npm run build",
|
|
11
|
+
"prebuild": "[ -d node_modules ] || npm ci",
|
|
12
|
+
"start": "rm -rf www && npm run build -- --sourcemap && node run.js && npx http-server www",
|
|
13
|
+
"build": "rm -rf build && esbuild src/index.js --bundle --minify --platform=node --target=node22 --outfile=build/index.js",
|
|
15
14
|
"test": "jest --runInBand --outputFile test-results.json --json",
|
|
16
15
|
"coverage": "jest --coverage --runInBand && open coverage/lcov-report/index.html",
|
|
17
16
|
"lint": "standard",
|
|
18
17
|
"posttest": "npm run lint",
|
|
19
|
-
"
|
|
18
|
+
"preversion": "npm run test",
|
|
20
19
|
"postversion": "git push origin main && git push --tags origin main"
|
|
21
20
|
},
|
|
22
21
|
"files": [
|
|
@@ -41,29 +40,24 @@
|
|
|
41
40
|
},
|
|
42
41
|
"homepage": "https://github.com/bbc/morty-docs#readme",
|
|
43
42
|
"dependencies": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"react": "^
|
|
47
|
-
"react-dom": "^
|
|
48
|
-
"react-test-renderer": "^16.13.1",
|
|
49
|
-
"recursive-readdir": "^2.2.2",
|
|
50
|
-
"showdown": "^1.9.0"
|
|
43
|
+
"marked": "^15.0.12",
|
|
44
|
+
"node-emoji": "^2.2.0",
|
|
45
|
+
"react": "^19.2.1",
|
|
46
|
+
"react-dom": "^19.2.1"
|
|
51
47
|
},
|
|
52
48
|
"devDependencies": {
|
|
53
|
-
"@babel/
|
|
54
|
-
"@babel/
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"
|
|
49
|
+
"@babel/core": "^7.28.5",
|
|
50
|
+
"@babel/preset-react": "^7.28.5",
|
|
51
|
+
"@happy-dom/jest-environment": "^20.0.11",
|
|
52
|
+
"@testing-library/react": "^16.3.0",
|
|
53
|
+
"esbuild": "^0.27.1",
|
|
58
54
|
"http-server": "^14.1.1",
|
|
59
|
-
"jest": "^
|
|
60
|
-
"
|
|
61
|
-
"standard": "^12.0.1"
|
|
55
|
+
"jest": "^30.2.0",
|
|
56
|
+
"standard": "^17.1.2"
|
|
62
57
|
},
|
|
63
58
|
"standard": {
|
|
64
59
|
"env": [
|
|
65
60
|
"jest"
|
|
66
|
-
]
|
|
67
|
-
"parser": "babel-eslint"
|
|
61
|
+
]
|
|
68
62
|
}
|
|
69
63
|
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const renderIndexPage = require('./page-renderers/IndexPage');
|
|
3
|
-
const getDirectories = require('./helpers/get-directory-paths');
|
|
4
|
-
const filterFilesInDirectory = require('./helpers/filter-files-in-dir');
|
|
5
|
-
const filterDirectoriesInDirectory = require('./helpers/filter-dirs-in-dir');
|
|
6
|
-
const generateIndex = (directory, filePaths, subDirPaths, options) => {
|
|
7
|
-
const subDirLinks = subDirPaths.filter(dirPath => !dirPath.includes('/')).map(dirPath => ({
|
|
8
|
-
link: `${dirPath}/index.html`,
|
|
9
|
-
text: dirPath,
|
|
10
|
-
iconName: 'folder'
|
|
11
|
-
}));
|
|
12
|
-
const fileLinks = filePaths.map(filePath => {
|
|
13
|
-
const text = path.basename(filePath);
|
|
14
|
-
return {
|
|
15
|
-
link: encodeURIComponent(text),
|
|
16
|
-
text,
|
|
17
|
-
iconName: 'file'
|
|
18
|
-
};
|
|
19
|
-
});
|
|
20
|
-
return renderIndexPage([...subDirLinks, ...fileLinks], options, directory);
|
|
21
|
-
};
|
|
22
|
-
const generateIndexes = (files, options = {
|
|
23
|
-
contentTitle: ''
|
|
24
|
-
}) => {
|
|
25
|
-
const supportedFilePaths = files.map(file => file.relativePath).filter(relativePath => path.extname(relativePath) === '.html' || path.extname(relativePath) === '.pdf');
|
|
26
|
-
const directories = getDirectories(supportedFilePaths);
|
|
27
|
-
// If we have not got a 'root' folder, then add one.
|
|
28
|
-
// TODO: Refactor this so it is not needed (maybe?)
|
|
29
|
-
if (!directories.includes('')) {
|
|
30
|
-
directories.push('');
|
|
31
|
-
}
|
|
32
|
-
const indexes = directories.flatMap(directory => {
|
|
33
|
-
const filesInDir = filterFilesInDirectory(supportedFilePaths, directory);
|
|
34
|
-
const subDirsInDir = filterDirectoriesInDirectory(directories, directory);
|
|
35
|
-
const indexPath = path.join(directory, 'index.html');
|
|
36
|
-
if (filesInDir.includes(indexPath)) {
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
relativePath: indexPath,
|
|
41
|
-
raw: Buffer.from(generateIndex(directory, filesInDir, subDirsInDir, options))
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
return indexes;
|
|
45
|
-
};
|
|
46
|
-
module.exports = generateIndexes;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const generateTransformInput = dir => {
|
|
4
|
-
dir = path.format(path.parse(dir));
|
|
5
|
-
let list = [];
|
|
6
|
-
const files = fs.readdirSync(dir, {
|
|
7
|
-
recursive: true,
|
|
8
|
-
withFileTypes: true
|
|
9
|
-
});
|
|
10
|
-
// recursive option available from node 18+
|
|
11
|
-
// when options.withFileTypes set to true, the returned array will contain <fs.Dirent> objects.
|
|
12
|
-
for (const dirent of files) {
|
|
13
|
-
// Node API for Dirent is unstable
|
|
14
|
-
const dirPath = dirent.path || dirent.parentPath; // path is DEPRECATED! But parentPath does not work in 18.17
|
|
15
|
-
|
|
16
|
-
const fullPath = path.join(dirPath, dirent.name);
|
|
17
|
-
// console.log('fullPath = ', fullPath)
|
|
18
|
-
|
|
19
|
-
if (dirent.isDirectory()) {
|
|
20
|
-
console.log('directory... continue');
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
if (dirent.isFile()) {
|
|
24
|
-
list.push(makeInputObject(fullPath, dir));
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
if (dirent.isSymbolicLink) {
|
|
28
|
-
if (fs.existsSync(fullPath)) {
|
|
29
|
-
// fs.exists() is deprecated, but fs.existsSync() is not.
|
|
30
|
-
const stats = fs.statSync(fullPath);
|
|
31
|
-
console.log('Good symlink');
|
|
32
|
-
if (stats.isFile()) {
|
|
33
|
-
// get file details
|
|
34
|
-
list.push(makeInputObject(fullPath, dir)); // symlinks become copies
|
|
35
|
-
} else {
|
|
36
|
-
// recursive call to get all files in the symlinked directory
|
|
37
|
-
const newlist = generateTransformInput(fullPath);
|
|
38
|
-
list = list.concat(newlist);
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
console.log(`Broken symlink at: ${fullPath}`);
|
|
42
|
-
}
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return list;
|
|
47
|
-
};
|
|
48
|
-
const makeInputObject = (fullPath, rootPath) => {
|
|
49
|
-
return {
|
|
50
|
-
relativePath: fullPath.replace(`${rootPath}/`, ''),
|
|
51
|
-
raw: fs.readFileSync(fullPath)
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
module.exports = generateTransformInput;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
sortArrayByDate
|
|
3
|
-
} = require('./sort-array-by-date');
|
|
4
|
-
const filterDirs = (directoryPaths, directory) => {
|
|
5
|
-
const directoryArray = [];
|
|
6
|
-
const nestedDirFolders = directoryPaths.filter(directoryPath => directoryPath.includes(directory) && !directoryPath.startsWith(directory) && directoryPath !== directory);
|
|
7
|
-
if (nestedDirFolders.length) directoryArray.push(nestedDirFolders);
|
|
8
|
-
// if directory path includes the config folder then return the full directory path
|
|
9
|
-
|
|
10
|
-
const rootDirFolders = directoryPaths.filter(directoryPath => directoryPath.startsWith(directory) && directoryPath !== directory);
|
|
11
|
-
const rootDir = rootDirFolders.map(directoryPath => directoryPath.startsWith(`${directory}/`) && directory !== '' ? directoryPath.replace(`${directory}/`, '') : directoryPath);
|
|
12
|
-
if (rootDir.length) directoryArray.push(rootDir);
|
|
13
|
-
// if directory path starts with the config folder then remove the directory from the path
|
|
14
|
-
// sort array here
|
|
15
|
-
let sortedDirectoryArray = directoryArray;
|
|
16
|
-
if (sortedDirectoryArray.length) {
|
|
17
|
-
sortedDirectoryArray.map(arr => sortArrayByDate(arr));
|
|
18
|
-
}
|
|
19
|
-
return sortedDirectoryArray.flat();
|
|
20
|
-
};
|
|
21
|
-
module.exports = filterDirs;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
const {
|
|
2
|
-
sortArrayByDate
|
|
3
|
-
} = require('./sort-array-by-date');
|
|
4
|
-
const directoryDepth = path => path.split('/').length;
|
|
5
|
-
const isInRootDirectory = filePath => directoryDepth(filePath) === 1;
|
|
6
|
-
const isIn = directory => filePath => filePath.startsWith(directory) && directoryDepth(filePath) - 1 === directoryDepth(directory);
|
|
7
|
-
module.exports = (filePaths, directory) => {
|
|
8
|
-
const isInSpecifiedDirectory = directory ? isIn(directory) : isInRootDirectory;
|
|
9
|
-
return sortArrayByDate(filePaths.filter(isInSpecifiedDirectory));
|
|
10
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const getDirectoryPaths = filePaths => {
|
|
2
|
-
const dirPaths = filePaths.map(path => {
|
|
3
|
-
// file = SomeOtherDir/AnotherDir/AnotherNestedDir/file.html
|
|
4
|
-
if (!path.includes('/')) return ''; // if file is not in the directory, return '', as this is the root
|
|
5
|
-
|
|
6
|
-
const splitPaths = path.split('/'); // => [ 'SomeOtherDir', 'AnotherDir', 'AnotherNestedDir', 'File1.html' ]
|
|
7
|
-
splitPaths.pop(); // remove file.html
|
|
8
|
-
|
|
9
|
-
const allDirs = splitPaths.map((splitPath, index) => {
|
|
10
|
-
const newPath = joinPathParts(splitPaths, index);
|
|
11
|
-
return newPath;
|
|
12
|
-
});
|
|
13
|
-
return allDirs;
|
|
14
|
-
});
|
|
15
|
-
return [...new Set(dirPaths.flat())];
|
|
16
|
-
};
|
|
17
|
-
const joinPathParts = (pathsArray, end) => {
|
|
18
|
-
if (end === 0) {
|
|
19
|
-
return pathsArray[0];
|
|
20
|
-
}
|
|
21
|
-
end++;
|
|
22
|
-
return pathsArray.slice(0, end).join('/');
|
|
23
|
-
};
|
|
24
|
-
module.exports = getDirectoryPaths;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const getHeaderLinks = (basePath, relPath = '') => {
|
|
2
|
-
const combinedParts = [...basePath.split('/'), ...relPath.split('/')];
|
|
3
|
-
const paths = combinedParts.filter(part => part && !part.endsWith('.html') && !part.endsWith('.md'));
|
|
4
|
-
return paths.reduce((acc, item, index) => {
|
|
5
|
-
const prevPart = acc[index - 1];
|
|
6
|
-
const path = prevPart ? `${prevPart.path}/${item}` : `/${item}`;
|
|
7
|
-
acc.push({
|
|
8
|
-
text: item,
|
|
9
|
-
path
|
|
10
|
-
});
|
|
11
|
-
return acc;
|
|
12
|
-
}, []);
|
|
13
|
-
};
|
|
14
|
-
module.exports = getHeaderLinks;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const dateRegex = /\d{4}-\d{2}-\d{2}/; // i.e. 2019-10-29
|
|
2
|
-
|
|
3
|
-
function sortByDate(a, b) {
|
|
4
|
-
return a.match(dateRegex) && b.match(dateRegex) ? b.localeCompare(a) : a.localeCompare(b);
|
|
5
|
-
}
|
|
6
|
-
const sortArrayByDate = arr => {
|
|
7
|
-
return arr.sort(sortByDate);
|
|
8
|
-
};
|
|
9
|
-
module.exports = {
|
|
10
|
-
sortArrayByDate
|
|
11
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
const showdown = require('showdown');
|
|
2
|
-
|
|
3
|
-
// there may be an option to enable this, but since we haven't found it here is a reg-ex
|
|
4
|
-
// to convert links within a file from *.md to *.html
|
|
5
|
-
const convertMdLinksToHtmlLinks = {
|
|
6
|
-
type: 'output',
|
|
7
|
-
regex: /<a href="([^:\n]*?).md">/g,
|
|
8
|
-
// exclude colon, so external links aren't converted
|
|
9
|
-
replace: '<a href="$1.html">'
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
// Replace hash links with .html e.g. page.md#Title becomes page.html#Title.
|
|
13
|
-
const convertMdHashLinksToHtmlLinks = {
|
|
14
|
-
type: 'output',
|
|
15
|
-
regex: /<a href="([^:\n]*?).md#(.*?)">/g,
|
|
16
|
-
// exclude colon, so external links aren't converted
|
|
17
|
-
replace: '<a href="$1.html#$2">'
|
|
18
|
-
};
|
|
19
|
-
const headingExtension = {
|
|
20
|
-
type: 'output',
|
|
21
|
-
regex: /<(h[123456]) id="([^"]+)">(.*)<\/\1>/g,
|
|
22
|
-
replace: '<$1 id="$2"><a href="#$2">$3</a></$1>'
|
|
23
|
-
};
|
|
24
|
-
const classMap = {
|
|
25
|
-
img: 'img-responsive',
|
|
26
|
-
table: 'table'
|
|
27
|
-
};
|
|
28
|
-
const bindings = Object.keys(classMap).map(key => ({
|
|
29
|
-
type: 'output',
|
|
30
|
-
regex: new RegExp(`<${key}(.*)>`, 'g'),
|
|
31
|
-
replace: `<${key} class="${classMap[key]}" $1>`
|
|
32
|
-
}));
|
|
33
|
-
const normaliseBasePath = basePath => {
|
|
34
|
-
const pathElements = (basePath || '').split('/').filter(entry => Boolean(entry));
|
|
35
|
-
if (pathElements.length === 0) {
|
|
36
|
-
return '';
|
|
37
|
-
}
|
|
38
|
-
return '/' + pathElements.join('/');
|
|
39
|
-
};
|
|
40
|
-
const createParser = options => {
|
|
41
|
-
const basePath = normaliseBasePath(options.basePath);
|
|
42
|
-
const addBasePathToRootLinks = {
|
|
43
|
-
type: 'output',
|
|
44
|
-
regex: /<a href="\/([^:\n]*)">/g,
|
|
45
|
-
// exclude colon, so external links aren't converted
|
|
46
|
-
replace: `<a href="${basePath}/$1">`
|
|
47
|
-
};
|
|
48
|
-
const addBasePathToLinkHrefs = {
|
|
49
|
-
type: 'output',
|
|
50
|
-
regex: /<link(.+)href="\/([^:\n]*)"(.*)\/>/g,
|
|
51
|
-
// exclude colon, so external links aren't converted
|
|
52
|
-
replace: `<link$1href="${basePath}/$2"$3/>`
|
|
53
|
-
};
|
|
54
|
-
const parser = new showdown.Converter({
|
|
55
|
-
extensions: [convertMdLinksToHtmlLinks, convertMdHashLinksToHtmlLinks, addBasePathToRootLinks, addBasePathToLinkHrefs, headingExtension, ...bindings]
|
|
56
|
-
});
|
|
57
|
-
parser.setFlavor('github');
|
|
58
|
-
return parser;
|
|
59
|
-
};
|
|
60
|
-
const parseToHTML = (markdown, options = {}) => {
|
|
61
|
-
const parser = createParser(options);
|
|
62
|
-
return parser.makeHtml(markdown);
|
|
63
|
-
};
|
|
64
|
-
module.exports = parseToHTML;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const {
|
|
3
|
-
prettyDate
|
|
4
|
-
} = require('./PrettyDate');
|
|
5
|
-
const Styles = {
|
|
6
|
-
footer: {
|
|
7
|
-
bottom: '0',
|
|
8
|
-
width: '100%',
|
|
9
|
-
backgroundColor: '#f5f5f5',
|
|
10
|
-
boxSizing: 'border-box',
|
|
11
|
-
minHeight: '25vh',
|
|
12
|
-
position: 'relative',
|
|
13
|
-
textAlign: 'center',
|
|
14
|
-
padding: '1em 0 2em 0',
|
|
15
|
-
lineHeight: '1.5rem'
|
|
16
|
-
},
|
|
17
|
-
footerLink: {
|
|
18
|
-
color: '#337ab7'
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
const Footer = () => {
|
|
22
|
-
return React.createElement("footer", {
|
|
23
|
-
style: Styles.footer
|
|
24
|
-
}, React.createElement("a", {
|
|
25
|
-
href: "https://github.com/bbc/morty-docs",
|
|
26
|
-
style: Styles.footerLink
|
|
27
|
-
}, "Morty-Docs on github"), React.createElement("br", null), "Page generated on ", prettyDate(new Date()));
|
|
28
|
-
};
|
|
29
|
-
module.exports = Footer;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const getHeaderPaths = require('../../helpers/get-header-paths');
|
|
3
|
-
const Styles = {
|
|
4
|
-
navbar: {
|
|
5
|
-
border: 'none',
|
|
6
|
-
borderRadius: '0',
|
|
7
|
-
backgroundColor: '#000',
|
|
8
|
-
marginBottom: '0',
|
|
9
|
-
width: '100%'
|
|
10
|
-
},
|
|
11
|
-
headerNav: {},
|
|
12
|
-
headerLinks: {
|
|
13
|
-
padding: '1rem',
|
|
14
|
-
listStyle: 'none',
|
|
15
|
-
display: 'flex',
|
|
16
|
-
alignItems: 'center'
|
|
17
|
-
},
|
|
18
|
-
headerLink: {
|
|
19
|
-
textAlign: 'left',
|
|
20
|
-
color: 'lightblue',
|
|
21
|
-
fontSize: '1.5rem',
|
|
22
|
-
textDecoration: 'none'
|
|
23
|
-
},
|
|
24
|
-
separator: {
|
|
25
|
-
margin: '0 0.28rem',
|
|
26
|
-
color: '#ebebeb'
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
const HeaderLinks = ({
|
|
30
|
-
paths
|
|
31
|
-
}) => paths.map(({
|
|
32
|
-
text,
|
|
33
|
-
path
|
|
34
|
-
}, index) => {
|
|
35
|
-
return React.createElement("li", {
|
|
36
|
-
key: index
|
|
37
|
-
}, index !== paths.length ? React.createElement("span", {
|
|
38
|
-
"aria-hidden": true,
|
|
39
|
-
style: Styles.separator
|
|
40
|
-
}, "/") : undefined, React.createElement("a", {
|
|
41
|
-
style: Styles.headerLink,
|
|
42
|
-
href: path
|
|
43
|
-
}, text));
|
|
44
|
-
});
|
|
45
|
-
const Header = ({
|
|
46
|
-
relPath,
|
|
47
|
-
basePath
|
|
48
|
-
}) => {
|
|
49
|
-
return React.createElement("div", {
|
|
50
|
-
style: Styles.navbar
|
|
51
|
-
}, React.createElement("nav", {
|
|
52
|
-
style: Styles.headerNav
|
|
53
|
-
}, React.createElement("ol", {
|
|
54
|
-
style: Styles.headerLinks
|
|
55
|
-
}, React.createElement(HeaderLinks, {
|
|
56
|
-
paths: getHeaderPaths(basePath, relPath)
|
|
57
|
-
}))));
|
|
58
|
-
};
|
|
59
|
-
module.exports = Header;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const IconFileLines = require('./icons/IconFileLines');
|
|
3
|
-
const IconFolderOpen = require('./icons/IconFolderOpen');
|
|
4
|
-
const Styles = {
|
|
5
|
-
indexListItem: {
|
|
6
|
-
fontSize: '1.5rem',
|
|
7
|
-
borderBottom: 'solid black 1px',
|
|
8
|
-
marginBottom: '1rem',
|
|
9
|
-
paddingBottom: '0.5rem'
|
|
10
|
-
},
|
|
11
|
-
linkText: {
|
|
12
|
-
marginLeft: '1rem'
|
|
13
|
-
},
|
|
14
|
-
linkAnchor: {
|
|
15
|
-
textDecoration: 'none',
|
|
16
|
-
color: '#337ab7'
|
|
17
|
-
},
|
|
18
|
-
icon: {
|
|
19
|
-
fill: '#337ab7',
|
|
20
|
-
height: '1em',
|
|
21
|
-
verticalAlign: 'middle'
|
|
22
|
-
},
|
|
23
|
-
iconWrap: {
|
|
24
|
-
display: 'inline-block',
|
|
25
|
-
width: '1em'
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const Icon = ({
|
|
29
|
-
iconName
|
|
30
|
-
}) => {
|
|
31
|
-
if (iconName === 'folder') {
|
|
32
|
-
return React.createElement(IconFolderOpen, {
|
|
33
|
-
style: Styles.icon
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
return React.createElement(IconFileLines, {
|
|
37
|
-
style: Styles.icon
|
|
38
|
-
});
|
|
39
|
-
};
|
|
40
|
-
const IndexListItem = ({
|
|
41
|
-
link,
|
|
42
|
-
text,
|
|
43
|
-
iconName
|
|
44
|
-
}) => {
|
|
45
|
-
return React.createElement("li", {
|
|
46
|
-
style: Styles.indexListItem
|
|
47
|
-
}, React.createElement("a", {
|
|
48
|
-
href: link,
|
|
49
|
-
style: Styles.linkAnchor
|
|
50
|
-
}, React.createElement("span", {
|
|
51
|
-
style: Styles.iconWrap
|
|
52
|
-
}, React.createElement(Icon, {
|
|
53
|
-
iconName: iconName
|
|
54
|
-
})), React.createElement("span", {
|
|
55
|
-
style: Styles.linkText
|
|
56
|
-
}, text)));
|
|
57
|
-
};
|
|
58
|
-
module.exports = IndexListItem;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const nth = function (d) {
|
|
3
|
-
if (d > 3 && d < 21) return 'th';
|
|
4
|
-
switch (d % 10) {
|
|
5
|
-
case 1:
|
|
6
|
-
return 'st';
|
|
7
|
-
case 2:
|
|
8
|
-
return 'nd';
|
|
9
|
-
case 3:
|
|
10
|
-
return 'rd';
|
|
11
|
-
default:
|
|
12
|
-
return 'th';
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
const month = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
16
|
-
const prettyDate = dateObj => {
|
|
17
|
-
const day = dateObj.getDate();
|
|
18
|
-
const year = dateObj.getFullYear();
|
|
19
|
-
return React.createElement(React.Fragment, null, day, React.createElement("sup", null, nth(day)), " ", month[dateObj.getMonth()], " ", year);
|
|
20
|
-
};
|
|
21
|
-
module.exports = {
|
|
22
|
-
prettyDate
|
|
23
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const resetStyles = `/* http://meyerweb.com/eric/tools/css/reset/
|
|
3
|
-
v2.0 | 20110126
|
|
4
|
-
License: none (public domain)
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
html, body, div, span, applet, object, iframe,
|
|
8
|
-
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
|
9
|
-
a, abbr, acronym, address, big, cite, code,
|
|
10
|
-
del, dfn, em, img, ins, kbd, q, s, samp,
|
|
11
|
-
small, strike, strong, sub, sup, tt, var,
|
|
12
|
-
b, u, i, center,
|
|
13
|
-
dl, dt, dd, ol, ul, li,
|
|
14
|
-
fieldset, form, label, legend,
|
|
15
|
-
table, caption, tbody, tfoot, thead, tr, th, td,
|
|
16
|
-
article, aside, canvas, details, embed,
|
|
17
|
-
figure, figcaption, footer, header, hgroup,
|
|
18
|
-
menu, nav, output, ruby, section, summary,
|
|
19
|
-
time, mark, audio, video {
|
|
20
|
-
margin: 0;
|
|
21
|
-
padding: 0;
|
|
22
|
-
border: 0;
|
|
23
|
-
font-size: 100%;
|
|
24
|
-
font: inherit;
|
|
25
|
-
vertical-align: baseline;
|
|
26
|
-
}
|
|
27
|
-
/* HTML5 display-role reset for older browsers */
|
|
28
|
-
article, aside, details, figcaption, figure,
|
|
29
|
-
footer, header, hgroup, menu, nav, section {
|
|
30
|
-
display: block;
|
|
31
|
-
}
|
|
32
|
-
body {
|
|
33
|
-
line-height: 1;
|
|
34
|
-
}
|
|
35
|
-
ol, ul {
|
|
36
|
-
list-style: none;
|
|
37
|
-
}
|
|
38
|
-
blockquote, q {
|
|
39
|
-
quotes: none;
|
|
40
|
-
}
|
|
41
|
-
blockquote:before, blockquote:after,
|
|
42
|
-
q:before, q:after {
|
|
43
|
-
content: '';
|
|
44
|
-
content: none;
|
|
45
|
-
}
|
|
46
|
-
table {
|
|
47
|
-
border-collapse: collapse;
|
|
48
|
-
border-spacing: 0;
|
|
49
|
-
}
|
|
50
|
-
sup {
|
|
51
|
-
vertical-align: super;
|
|
52
|
-
font-size: smaller;
|
|
53
|
-
padding-right: 0.2rem;
|
|
54
|
-
}
|
|
55
|
-
`;
|
|
56
|
-
const Reset = () => React.createElement("style", {
|
|
57
|
-
dangerouslySetInnerHTML: {
|
|
58
|
-
__html: resetStyles
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
module.exports = Reset;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const Styles = {
|
|
3
|
-
heading: {
|
|
4
|
-
fontSize: '2rem',
|
|
5
|
-
fontWeight: '500'
|
|
6
|
-
}
|
|
7
|
-
};
|
|
8
|
-
const Title = ({
|
|
9
|
-
contentTitle
|
|
10
|
-
}) => {
|
|
11
|
-
if (contentTitle) {
|
|
12
|
-
return React.createElement("div", {
|
|
13
|
-
style: {
|
|
14
|
-
textAlign: 'center',
|
|
15
|
-
marginBottom: '20px',
|
|
16
|
-
marginTop: '32px'
|
|
17
|
-
}
|
|
18
|
-
}, React.createElement("h1", {
|
|
19
|
-
style: Styles.heading
|
|
20
|
-
}, contentTitle));
|
|
21
|
-
} else return null;
|
|
22
|
-
};
|
|
23
|
-
module.exports = Title;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const IconFileLines = ({
|
|
3
|
-
style
|
|
4
|
-
}) => React.createElement("svg", {
|
|
5
|
-
"aria-hidden": "true",
|
|
6
|
-
style: style,
|
|
7
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
-
viewBox: "0 0 384 512"
|
|
9
|
-
}, '<!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. -->', React.createElement("path", {
|
|
10
|
-
d: "M256 0v128h128L256 0zM224 128L224 0H48C21.49 0 0 21.49 0 48v416C0 490.5 21.49 512 48 512h288c26.51 0 48-21.49 48-48V160h-127.1C238.3 160 224 145.7 224 128zM272 416h-160C103.2 416 96 408.8 96 400C96 391.2 103.2 384 112 384h160c8.836 0 16 7.162 16 16C288 408.8 280.8 416 272 416zM272 352h-160C103.2 352 96 344.8 96 336C96 327.2 103.2 320 112 320h160c8.836 0 16 7.162 16 16C288 344.8 280.8 352 272 352zM288 272C288 280.8 280.8 288 272 288h-160C103.2 288 96 280.8 96 272C96 263.2 103.2 256 112 256h160C280.8 256 288 263.2 288 272z"
|
|
11
|
-
}));
|
|
12
|
-
module.exports = IconFileLines;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const React = require('react');
|
|
2
|
-
const IconFolderOpen = ({
|
|
3
|
-
style
|
|
4
|
-
}) => React.createElement("svg", {
|
|
5
|
-
"aria-hidden": "true",
|
|
6
|
-
style: style,
|
|
7
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
-
viewBox: "0 0 576 512"
|
|
9
|
-
}, '<!--! Font Awesome Free 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. -->', React.createElement("path", {
|
|
10
|
-
d: "M147.8 192H480V144C480 117.5 458.5 96 432 96h-160l-64-64h-160C21.49 32 0 53.49 0 80v328.4l90.54-181.1C101.4 205.6 123.4 192 147.8 192zM543.1 224H147.8C135.7 224 124.6 230.8 119.2 241.7L0 480h447.1c12.12 0 23.2-6.852 28.62-17.69l96-192C583.2 249 567.7 224 543.1 224z"
|
|
11
|
-
}));
|
|
12
|
-
module.exports = IconFolderOpen;
|