@jpmorganchase/mosaic-plugins 0.0.0-snapshot-20240604074928

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.
Files changed (64) hide show
  1. package/dist/$AliasPlugin.d.ts +10 -0
  2. package/dist/$AliasPlugin.js +66 -0
  3. package/dist/$AliasPlugin.js.map +1 -0
  4. package/dist/$CodeModPlugin.d.ts +7 -0
  5. package/dist/$CodeModPlugin.js +30 -0
  6. package/dist/$CodeModPlugin.js.map +1 -0
  7. package/dist/$RefPlugin.d.ts +31 -0
  8. package/dist/$RefPlugin.js +150 -0
  9. package/dist/$RefPlugin.js.map +1 -0
  10. package/dist/$TagPlugin.d.ts +28 -0
  11. package/dist/$TagPlugin.js +71 -0
  12. package/dist/$TagPlugin.js.map +1 -0
  13. package/dist/BreadcrumbsPlugin.d.ts +19 -0
  14. package/dist/BreadcrumbsPlugin.js +100 -0
  15. package/dist/BreadcrumbsPlugin.js.map +1 -0
  16. package/dist/BrokenLinksPlugin.d.ts +10 -0
  17. package/dist/BrokenLinksPlugin.js +80 -0
  18. package/dist/BrokenLinksPlugin.js.map +1 -0
  19. package/dist/FragmentPlugin.d.ts +7 -0
  20. package/dist/FragmentPlugin.js +92 -0
  21. package/dist/FragmentPlugin.js.map +1 -0
  22. package/dist/LazyPagePlugin.d.ts +14 -0
  23. package/dist/LazyPagePlugin.js +65 -0
  24. package/dist/LazyPagePlugin.js.map +1 -0
  25. package/dist/PagesWithoutFileExtPlugin.d.ts +9 -0
  26. package/dist/PagesWithoutFileExtPlugin.js +35 -0
  27. package/dist/PagesWithoutFileExtPlugin.js.map +1 -0
  28. package/dist/PropsTablePlugin.d.ts +6 -0
  29. package/dist/PropsTablePlugin.js +88 -0
  30. package/dist/PropsTablePlugin.js.map +1 -0
  31. package/dist/PublicAssetsPlugin.d.ts +18 -0
  32. package/dist/PublicAssetsPlugin.js +28 -0
  33. package/dist/PublicAssetsPlugin.js.map +1 -0
  34. package/dist/ReadingTimePlugin.d.ts +10 -0
  35. package/dist/ReadingTimePlugin.js +36 -0
  36. package/dist/ReadingTimePlugin.js.map +1 -0
  37. package/dist/SearchIndexPlugin.d.ts +56 -0
  38. package/dist/SearchIndexPlugin.js +154 -0
  39. package/dist/SearchIndexPlugin.js.map +1 -0
  40. package/dist/SharedConfigPlugin.d.ts +14 -0
  41. package/dist/SharedConfigPlugin.js +146 -0
  42. package/dist/SharedConfigPlugin.js.map +1 -0
  43. package/dist/SidebarPlugin.d.ts +44 -0
  44. package/dist/SidebarPlugin.js +260 -0
  45. package/dist/SidebarPlugin.js.map +1 -0
  46. package/dist/SiteMapPlugin.d.ts +9 -0
  47. package/dist/SiteMapPlugin.js +28 -0
  48. package/dist/SiteMapPlugin.js.map +1 -0
  49. package/dist/TableOfContentsPlugin.d.ts +20 -0
  50. package/dist/TableOfContentsPlugin.js +43 -0
  51. package/dist/TableOfContentsPlugin.js.map +1 -0
  52. package/dist/utils/PluginError.d.ts +7 -0
  53. package/dist/utils/PluginError.js +13 -0
  54. package/dist/utils/PluginError.js.map +1 -0
  55. package/dist/utils/mergePageConent.d.ts +16 -0
  56. package/dist/utils/mergePageConent.js +23 -0
  57. package/dist/utils/mergePageConent.js.map +1 -0
  58. package/dist/utils/normaliseRefs.d.ts +1 -0
  59. package/dist/utils/normaliseRefs.js +66 -0
  60. package/dist/utils/normaliseRefs.js.map +1 -0
  61. package/dist/utils/sortSidebarData.d.ts +19 -0
  62. package/dist/utils/sortSidebarData.js +35 -0
  63. package/dist/utils/sortSidebarData.js.map +1 -0
  64. package/package.json +71 -0
@@ -0,0 +1,10 @@
1
+ import type { Page, Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ interface AliasPluginPage extends Page {
3
+ aliases?: string[];
4
+ }
5
+ /**
6
+ * Plugin that scrapes `aliases` from page metadata and also applies all aliases stored in `config.data.aliases`
7
+ * Other plugins can use `setAliases` to apply new aliases, as long as they call it before this plugin has reaches `$beforeSend`
8
+ */
9
+ declare const $AliasPlugin: PluginType<AliasPluginPage>;
10
+ export default $AliasPlugin;
@@ -0,0 +1,66 @@
1
+ import path from 'path';
2
+ import { escapeRegExp } from 'lodash-es';
3
+ import PluginError from './utils/PluginError.js';
4
+ function createPageTest(ignorePages, pageExtensions) {
5
+ const extTest = new RegExp(`${pageExtensions.map(escapeRegExp).join('|')}$`);
6
+ const ignoreTest = new RegExp(`${ignorePages.map(escapeRegExp).join('|')}$`);
7
+ return file => !ignoreTest.test(file) && extTest.test(file) && !path.basename(file).startsWith('.');
8
+ }
9
+ /**
10
+ * Plugin that scrapes `aliases` from page metadata and also applies all aliases stored in `config.data.aliases`
11
+ * Other plugins can use `setAliases` to apply new aliases, as long as they call it before this plugin has reaches `$beforeSend`
12
+ */
13
+ const $AliasPlugin = {
14
+ async $afterSource(pages, { config, ignorePages, pageExtensions }) {
15
+ const isNonHiddenPage = createPageTest(ignorePages, pageExtensions);
16
+ // Group together all aliases defined in the frontmatter and store them in the alias config object
17
+ for (const page of pages) {
18
+ try {
19
+ if (!isNonHiddenPage(page.fullPath)) {
20
+ continue;
21
+ }
22
+ if (page.aliases) {
23
+ config.setAliases(page.fullPath, page.aliases);
24
+ }
25
+ delete page.aliases;
26
+ }
27
+ catch (e) {
28
+ throw new PluginError(e.message, page.fullPath);
29
+ }
30
+ }
31
+ return pages;
32
+ },
33
+ async $beforeSend(mutableFilesystem, { config }) {
34
+ // Prevent any more aliases being set after this lifecycle has been called - as they won't take effect
35
+ config.setAliases = () => {
36
+ throw new Error('Cannot set aliases after `$AliasPlugin` has reached `$beforeSend` lifecycle phase.');
37
+ };
38
+ if (!config.data.aliases) {
39
+ return;
40
+ }
41
+ for (const fullPath in config.data.aliases) {
42
+ try {
43
+ for (const alias of config.data.aliases[fullPath]) {
44
+ const aliasPath = path.posix.resolve(path.dirname(fullPath), alias).toLowerCase();
45
+ const aliasDir = path.dirname(aliasPath);
46
+ if (!(await mutableFilesystem.promises.exists(aliasDir))) {
47
+ await mutableFilesystem.promises.mkdir(aliasDir, {
48
+ recursive: true
49
+ });
50
+ }
51
+ if (!(await mutableFilesystem.promises.exists(aliasPath))) {
52
+ await mutableFilesystem.promises.symlink(fullPath, aliasPath);
53
+ }
54
+ else {
55
+ console.warn(`Alias '${aliasPath}' already exists. Is there a duplicate alias, or a page with the same name but different file extensions?`);
56
+ }
57
+ }
58
+ }
59
+ catch (e) {
60
+ throw new PluginError(e.message, fullPath);
61
+ }
62
+ }
63
+ }
64
+ };
65
+ export default $AliasPlugin;
66
+ //# sourceMappingURL=$AliasPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"$AliasPlugin.js","sourceRoot":"","sources":["../src/$AliasPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Page, Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ interface CodeModPluginPage extends Page {
3
+ frameOverrides?: Record<string, unknown>;
4
+ sharedConfig?: Record<string, unknown>;
5
+ }
6
+ declare const $CodeModPlugin: PluginType<CodeModPluginPage>;
7
+ export default $CodeModPlugin;
@@ -0,0 +1,30 @@
1
+ import { escapeRegExp } from 'lodash-es';
2
+ import path from 'path';
3
+ import PluginError from './utils/PluginError.js';
4
+ function createPageTest(ignorePages, pageExtensions) {
5
+ const extTest = new RegExp(`${pageExtensions.map(escapeRegExp).join('|')}$`);
6
+ const ignoreTest = new RegExp(`${ignorePages.map(escapeRegExp).join('|')}$`);
7
+ return file => !ignoreTest.test(file) && extTest.test(file) && !path.basename(file).startsWith('.');
8
+ }
9
+ const $CodeModPlugin = {
10
+ async $afterSource(pages, { ignorePages, pageExtensions }) {
11
+ const isNonHiddenPage = createPageTest(ignorePages, pageExtensions);
12
+ for (const page of pages) {
13
+ try {
14
+ if (!isNonHiddenPage(page.fullPath)) {
15
+ continue;
16
+ }
17
+ if (page.frameOverrides) {
18
+ page.sharedConfig = page.frameOverrides;
19
+ page.frameOverrides = { $ref: '#/sharedConfig' };
20
+ }
21
+ }
22
+ catch (e) {
23
+ throw new PluginError(e.message, page.fullPath);
24
+ }
25
+ }
26
+ return pages;
27
+ }
28
+ };
29
+ export default $CodeModPlugin;
30
+ //# sourceMappingURL=$CodeModPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"$CodeModPlugin.js","sourceRoot":"","sources":["../src/$CodeModPlugin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,WAAW,MAAM,wBAAwB,CAAC;AAEjD,SAAS,cAAc,CAAC,WAAW,EAAE,cAAc;IACjD,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,EAAE,CACZ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACzF,CAAC;AAOD,MAAM,cAAc,GAAkC;IACpD,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE;QACvD,MAAM,eAAe,GAAG,cAAc,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;QAEpE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;YACxB,IAAI;gBACF,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;oBACnC,SAAS;iBACV;gBACD,IAAI,IAAI,CAAC,cAAc,EAAE;oBACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC;oBACxC,IAAI,CAAC,cAAc,GAAG,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;iBAClD;aACF;YAAC,OAAO,CAAC,EAAE;gBACV,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;aACjD;SACF;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ interface RefsPluginConfigData {
3
+ refs: {
4
+ [key: string]: {
5
+ $$path: string[];
6
+ $$value: string;
7
+ }[];
8
+ };
9
+ globalRefs: {
10
+ [key: string]: {
11
+ $$path: string[];
12
+ $$value: string;
13
+ }[];
14
+ };
15
+ subscribedTags: string[];
16
+ }
17
+ interface RefsPluginPage {
18
+ fullPath: string;
19
+ refs: {
20
+ [key: string]: {
21
+ $$path: string[];
22
+ $$value: string;
23
+ }[];
24
+ };
25
+ }
26
+ /**
27
+ * Plugin that scrapes `$ref` properties from page metadata and also applies all refs stored in `config.data.refs`.
28
+ * Other plugins can use `setRef` to apply new refs, as long as they call it before this plugin has reaches `$beforeSend`
29
+ */
30
+ declare const $RefPlugin: PluginType<RefsPluginPage, unknown, RefsPluginConfigData>;
31
+ export default $RefPlugin;
@@ -0,0 +1,150 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import { reduce, omit, escapeRegExp } from 'lodash-es';
4
+ import { $RefParser } from '@apidevtools/json-schema-ref-parser';
5
+ import deepmerge from 'deepmerge';
6
+ import normaliseRefs from './utils/normaliseRefs.js';
7
+ import PluginError from './utils/PluginError.js';
8
+ import { mergePageContent } from './utils/mergePageConent.js';
9
+ const isWindows = /^win/.test(os.platform());
10
+ const windowsDrivePattern = /^([a-z]):/i;
11
+ /**
12
+ * The JSON Schema Ref parser turns refs into URLs.
13
+ * When running on Windows it adds in the drive letter to the beginning of the resolved ref filepath
14
+ *
15
+ * WE DON"T WANT THIS
16
+ *
17
+ * Regardless of platform, Mosaic uses an in-memory fs so we don't need drive letters.
18
+ * We need the path as it is in the mosaic fs.
19
+ */
20
+ function normaliseWindowsPath(url) {
21
+ const drivePart = windowsDrivePattern.exec(url)?.[0];
22
+ return drivePart ? url.slice(drivePart.length) : url;
23
+ }
24
+ function createRefResolver(normalisedRefs, serialiser, mutableFilesystem) {
25
+ return {
26
+ file: {
27
+ canRead: true,
28
+ order: 1,
29
+ async read(file, callback) {
30
+ try {
31
+ const filePath = isWindows ? normaliseWindowsPath(file.url) : file.url;
32
+ const refedPage = normalisedRefs[filePath] ||
33
+ (await serialiser.deserialise(filePath, await mutableFilesystem.promises.readFile(filePath)));
34
+ return callback(null, omit(refedPage, 'content'));
35
+ }
36
+ catch (e) {
37
+ return callback(e, null);
38
+ }
39
+ }
40
+ }
41
+ };
42
+ }
43
+ const findKeys = (obj, targetProp, pathParts = []) => reduce(obj, (found, value, key) => {
44
+ if (key === targetProp) {
45
+ return found.concat([[pathParts.concat(String(key)), value]]);
46
+ }
47
+ if (typeof value === 'object') {
48
+ const foundParents = findKeys(value, targetProp, pathParts.concat(String(key)));
49
+ return found.concat(foundParents);
50
+ }
51
+ return found;
52
+ }, []);
53
+ function createPageTest(ignorePages, pageExtensions) {
54
+ const extTest = new RegExp(`${pageExtensions.map(escapeRegExp).join('|')}$`);
55
+ const ignoreTest = new RegExp(`${ignorePages.map(escapeRegExp).join('|')}$`);
56
+ return file => !ignoreTest.test(file) && extTest.test(file) && !path.basename(file).startsWith('.');
57
+ }
58
+ /**
59
+ * Plugin that scrapes `$ref` properties from page metadata and also applies all refs stored in `config.data.refs`.
60
+ * Other plugins can use `setRef` to apply new refs, as long as they call it before this plugin has reaches `$beforeSend`
61
+ */
62
+ const $RefPlugin = {
63
+ async afterUpdate(mutableFilesystem, { ignorePages, globalFilesystem, serialiser, pageExtensions, globalConfig }) {
64
+ mutableFilesystem.__internal_do_not_use_addReadFileHook(async (pagePath, fileData) => {
65
+ if (globalConfig.data.globalRefs[pagePath]) {
66
+ const expandedRefs = await normaliseRefs(String(pagePath), globalConfig.data.globalRefs[pagePath], globalFilesystem, pageExtensions, ignorePages);
67
+ const page = await serialiser.deserialise(pagePath, fileData);
68
+ const normalisedRef = mergePageContent(page, expandedRefs);
69
+ const resolve = createRefResolver({
70
+ [pagePath]: normalisedRef
71
+ }, serialiser, globalFilesystem);
72
+ const refParser = new $RefParser();
73
+ try {
74
+ const resolved = await refParser.dereference(String(pagePath), normalisedRef, {
75
+ resolve,
76
+ dereference: { circular: false }
77
+ });
78
+ const serialisedPage = await serialiser.serialise(pagePath, {
79
+ ...normalisedRef,
80
+ ...resolved
81
+ });
82
+ return serialisedPage;
83
+ }
84
+ catch (e) {
85
+ console.warn(`Error resolving ref(s) for page '${pagePath}'. ${e.message.replace(/\.$/, '')} in '${e.source}'`);
86
+ throw new PluginError(e.message, page.fullPath);
87
+ }
88
+ }
89
+ return fileData;
90
+ });
91
+ },
92
+ async $beforeSend(mutableFilesystem, { config, serialiser, pageExtensions, ignorePages }) {
93
+ // Prevent any more refs being set after this lifecycle has been called - as they won't take effect
94
+ config.setRef = () => {
95
+ throw new Error('Cannot set refs after `RefPlugin` has reached `$beforeSend` lifecycle phase.');
96
+ };
97
+ const normalisedRefs = {};
98
+ if (config.data.refs) {
99
+ // First pass of refs, normalises any $ref entries to expand wildcards
100
+ for (const fullPath in config.data.refs) {
101
+ const page = await serialiser.deserialise(fullPath, await mutableFilesystem.promises.readFile(fullPath));
102
+ try {
103
+ const expandedRefs = await normaliseRefs(String(fullPath), config.data.refs[fullPath], mutableFilesystem, pageExtensions, ignorePages);
104
+ normalisedRefs[fullPath] = deepmerge(page, expandedRefs);
105
+ }
106
+ catch (e) {
107
+ throw new PluginError(e.message, page.fullPath);
108
+ }
109
+ }
110
+ const resolve = createRefResolver(normalisedRefs, serialiser, mutableFilesystem);
111
+ const refParser = new $RefParser();
112
+ // Second pass of refs, resolves the refs
113
+ for (const fullPath in normalisedRefs) {
114
+ const page = normalisedRefs[fullPath];
115
+ try {
116
+ const resolved = await refParser.dereference(String(fullPath), page, {
117
+ resolve,
118
+ dereference: { circular: false }
119
+ });
120
+ normalisedRefs[fullPath] = { ...page, ...resolved };
121
+ }
122
+ catch (e) {
123
+ console.warn(`Error resolving ref(s) for page '${fullPath}'. ${e.message.replace(/\.$/, '')} in '${e.source}'`);
124
+ throw new PluginError(e.message, page.fullPath);
125
+ }
126
+ }
127
+ // Third pass, write out the files
128
+ for (const fullPath in normalisedRefs) {
129
+ await mutableFilesystem.promises.writeFile(fullPath, await serialiser.serialise(fullPath, normalisedRefs[fullPath]));
130
+ }
131
+ }
132
+ },
133
+ async $afterSource(pages, { config, ignorePages, pageExtensions }) {
134
+ const isNonHiddenPage = createPageTest(ignorePages, pageExtensions);
135
+ for (const page of pages) {
136
+ if (!isNonHiddenPage(page.fullPath)) {
137
+ continue;
138
+ }
139
+ const refs = findKeys(page, '$ref');
140
+ if (refs.length) {
141
+ for (const ref of refs) {
142
+ config.setRef(page.fullPath, ...ref);
143
+ }
144
+ }
145
+ }
146
+ return pages;
147
+ }
148
+ };
149
+ export default $RefPlugin;
150
+ //# sourceMappingURL=$RefPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"$RefPlugin.js","sourceRoot":"","sources":["../src/$RefPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Page, Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ interface TagPluginPage extends Page {
3
+ tags?: string[];
4
+ }
5
+ interface TagPluginConfigData {
6
+ tagRefs: {
7
+ [key: string]: {
8
+ $$path: string[];
9
+ $$value: string[];
10
+ }[];
11
+ };
12
+ globalRefs: {
13
+ [key: string]: {
14
+ $$path: string[];
15
+ $$value: string[];
16
+ }[];
17
+ };
18
+ subscribedTags: string[];
19
+ }
20
+ /**
21
+ * Plugin that scrapes `$tag` from page metadata and also applies all aliases stored in `config.data.tags`.
22
+ * Tags ultimately resolve down into refs, but are different from normal refs, in that they are applied to the
23
+ * union filesystem (all merged filesystems), not to the individual source filesystem that they were defined on.
24
+ * Other plugins can use `setData()` and modify the `tags` property, to apply new global refs, as long as
25
+ * they do so before this plugin has reaches `$beforeSend`
26
+ */
27
+ declare const $TagPlugin: PluginType<TagPluginPage, unknown, TagPluginConfigData>;
28
+ export default $TagPlugin;
@@ -0,0 +1,71 @@
1
+ import path from 'path';
2
+ import { escapeRegExp, reduce } from 'lodash-es';
3
+ import PluginError from './utils/PluginError.js';
4
+ function createPageTest(ignorePages, pageExtensions) {
5
+ const extTest = new RegExp(`${pageExtensions.map(escapeRegExp).join('|')}$`);
6
+ const ignoreTest = new RegExp(`${ignorePages.map(escapeRegExp).join('|')}$`);
7
+ return file => !ignoreTest.test(file) && extTest.test(file) && !path.basename(file).startsWith('.');
8
+ }
9
+ const findKeys = (obj, targetProp, pathParts = []) => reduce(obj, (found, value, key) => {
10
+ if (key === targetProp) {
11
+ return found.concat({ $$path: pathParts.concat(String(key)), $$value: value });
12
+ }
13
+ if (typeof value === 'object') {
14
+ const foundParents = findKeys(value, targetProp, pathParts.concat(String(key)));
15
+ return found.concat(...foundParents);
16
+ }
17
+ return found;
18
+ }, []);
19
+ /**
20
+ * Plugin that scrapes `$tag` from page metadata and also applies all aliases stored in `config.data.tags`.
21
+ * Tags ultimately resolve down into refs, but are different from normal refs, in that they are applied to the
22
+ * union filesystem (all merged filesystems), not to the individual source filesystem that they were defined on.
23
+ * Other plugins can use `setData()` and modify the `tags` property, to apply new global refs, as long as
24
+ * they do so before this plugin has reaches `$beforeSend`
25
+ */
26
+ const $TagPlugin = {
27
+ // Check if the updated source has any /.tag aliases that we care about - if it does, we should re-run `afterUpdate` to
28
+ // make sure we pull in the latest pages
29
+ async shouldClearCache(updatedSourceFilesystem, { config }) {
30
+ if (!config.data?.subscribedTags ||
31
+ !(await updatedSourceFilesystem.promises.exists('/.tags'))) {
32
+ return false;
33
+ }
34
+ // Does the updated source have tags we are interested in?
35
+ return (await updatedSourceFilesystem.promises.readdir('/.tags')).some(tag => config.data.subscribedTags.includes(tag));
36
+ },
37
+ // Every source with tags will create symlinks with the tagged pages, inside /.tags
38
+ async $afterSource(pages, { config, ignorePages, pageExtensions }) {
39
+ const isNonHiddenPage = createPageTest(ignorePages, pageExtensions);
40
+ for (const page of pages) {
41
+ try {
42
+ if (!isNonHiddenPage(page.fullPath)) {
43
+ continue;
44
+ }
45
+ const meta = page;
46
+ // Symlink every `tag` item to '/.tags' folder
47
+ if (meta.tags?.length) {
48
+ config.setTags(page.fullPath, meta.tags);
49
+ delete meta.tags;
50
+ }
51
+ // Find any references to $tag
52
+ const foundTags = findKeys(page, '$tag');
53
+ if (foundTags.length) {
54
+ const tags = new Set();
55
+ foundTags.forEach(ref => {
56
+ const [tag, fragment = ''] = ref.$$value.split('#');
57
+ tags.add(tag);
58
+ config.setGlobalRef(page.fullPath, ref.$$path, `${path.posix.join('/.tags', tag, '**')}#${fragment}`);
59
+ });
60
+ config.setData({ subscribedTags: Array.from(tags) });
61
+ }
62
+ }
63
+ catch (e) {
64
+ throw new PluginError(e.message, page.fullPath);
65
+ }
66
+ }
67
+ return pages;
68
+ }
69
+ };
70
+ export default $TagPlugin;
71
+ //# sourceMappingURL=$TagPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"$TagPlugin.js","sourceRoot":"","sources":["../src/$TagPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ import { SidebarPluginPage } from './SidebarPlugin.js';
3
+ export type Breadcrumb = {
4
+ label: string;
5
+ path: string;
6
+ id: string;
7
+ };
8
+ export interface BreadcrumbsPluginPage extends SidebarPluginPage {
9
+ breadcrumbs?: Array<Breadcrumb>;
10
+ layout?: string;
11
+ }
12
+ interface BreadcrumbsPluginOptions {
13
+ indexPageName: string;
14
+ }
15
+ /**
16
+ * Calculates breadcrumbs for pages then embeds a `breadcrumbs` property to the metadata
17
+ */
18
+ declare const BreadcrumbsPlugin: PluginType<BreadcrumbsPluginPage, BreadcrumbsPluginOptions>;
19
+ export default BreadcrumbsPlugin;
@@ -0,0 +1,100 @@
1
+ import path from 'node:path';
2
+ import { escapeRegExp } from 'lodash-es';
3
+ import PluginError from './utils/PluginError.js';
4
+ const createPageTest = (ignorePages, pageExtensions) => {
5
+ const extTest = new RegExp(`${pageExtensions.map(ext => escapeRegExp(ext)).join('|')}$`);
6
+ const ignoreTest = new RegExp(`${ignorePages.map(ignore => escapeRegExp(ignore)).join('|')}$`);
7
+ return file => !ignoreTest.test(file) && extTest.test(file) && !path.basename(file).startsWith('.');
8
+ };
9
+ /**
10
+ * Calculates breadcrumbs for pages then embeds a `breadcrumbs` property to the metadata
11
+ */
12
+ const BreadcrumbsPlugin = {
13
+ async $afterSource(pages, { ignorePages, pageExtensions }, options) {
14
+ const isNonHiddenPage = createPageTest(ignorePages, pageExtensions);
15
+ for (const page of pages) {
16
+ if (!isNonHiddenPage(page.fullPath)) {
17
+ continue;
18
+ }
19
+ try {
20
+ const breadcrumbs = [];
21
+ let currentPage = page;
22
+ let parentDir = path.posix.normalize(path.posix.dirname(currentPage.fullPath));
23
+ const maxBreadcrumbCount = page.fullPath.split('/').length;
24
+ while (currentPage !== undefined && breadcrumbs.length < maxBreadcrumbCount) {
25
+ breadcrumbs.unshift({
26
+ label: currentPage.sidebar?.label || currentPage.title,
27
+ path: currentPage.route,
28
+ id: currentPage.fullPath
29
+ });
30
+ currentPage = pages.find(
31
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
32
+ item => item.fullPath === path.posix.join(parentDir, options.indexPageName));
33
+ if (currentPage) {
34
+ parentDir = path.posix.dirname(path.posix.join(String(currentPage.fullPath), '..'));
35
+ }
36
+ }
37
+ if (!page.breadcrumbs) {
38
+ // filter out any duplicate breadcrumbs
39
+ const map = new Map(breadcrumbs.map(crumb => [crumb.id, crumb]));
40
+ page.breadcrumbs = [...map.values()];
41
+ }
42
+ }
43
+ catch (e) {
44
+ throw new PluginError(e.message, page.fullPath);
45
+ }
46
+ }
47
+ return pages;
48
+ },
49
+ async afterNamespaceSourceUpdate(mutableFilesystem, { serialiser, globalFilesystem, ignorePages }, options) {
50
+ const pages = (await mutableFilesystem.promises.glob('**', {
51
+ onlyFiles: true,
52
+ ignore: ignorePages.map(ignore => `**/${ignore}`),
53
+ cwd: '/'
54
+ }));
55
+ if (pages.length > 0) {
56
+ let updatedBreadcrumbs = [];
57
+ const { breadcrumbs } = await serialiser.deserialise(pages[0], await mutableFilesystem.promises.readFile(pages[0]));
58
+ // the root breadcrumb is the first breadcrumb for all pages in a source. It is essentially the "first" page in a source
59
+ const rootBreadcrumb = breadcrumbs?.[0] || undefined;
60
+ if (rootBreadcrumb) {
61
+ let parentDir = path.posix.join(path.posix.dirname(rootBreadcrumb.id), '../');
62
+ while (parentDir !== '/') {
63
+ const parentDirIndex = path.posix.join(parentDir, options.indexPageName);
64
+ // check for this file in the global fs so we have a holistic view of all site pages
65
+ if (await globalFilesystem.promises.exists(parentDirIndex)) {
66
+ const { breadcrumbs: parentDirBreadcrumbs } = await serialiser.deserialise(rootBreadcrumb.id, await globalFilesystem.promises.readFile(parentDirIndex));
67
+ updatedBreadcrumbs = parentDirBreadcrumbs;
68
+ break;
69
+ }
70
+ parentDir = path.posix.join(path.posix.dirname(parentDirIndex), '../');
71
+ }
72
+ if (updatedBreadcrumbs.length > 0) {
73
+ for (const pagePath of pages) {
74
+ const page = await serialiser.deserialise(pagePath, await mutableFilesystem.promises.readFile(pagePath));
75
+ // append the parent breadcrumbs **before** the current breadcrumbs
76
+ page.breadcrumbs = [...updatedBreadcrumbs, ...page.breadcrumbs];
77
+ await mutableFilesystem.promises.writeFile(pagePath, await serialiser.serialise(pagePath, page));
78
+ }
79
+ }
80
+ }
81
+ }
82
+ },
83
+ async shouldUpdateNamespaceSources(updatedSourceFilesystem, { ignorePages, namespace }) {
84
+ /**
85
+ * Only trigger an update when the updated source happens to be the "root" namespace source
86
+ * This is determined this by checking if the filesystem has files inside the "namespace" directory
87
+ *
88
+ * "child" sources will have the namespace directory but they wont have files until further down the directory hierarchy
89
+ */
90
+ const namespaceDirFiles = (await updatedSourceFilesystem.promises.glob(`${namespace}/*`, {
91
+ onlyFiles: true,
92
+ ignore: ignorePages.map(ignore => `**/${ignore}`),
93
+ cwd: '/'
94
+ }));
95
+ // the root namespace has updated
96
+ return namespaceDirFiles.length > 0;
97
+ }
98
+ };
99
+ export default BreadcrumbsPlugin;
100
+ //# sourceMappingURL=BreadcrumbsPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BreadcrumbsPlugin.js","sourceRoot":"","sources":["../src/BreadcrumbsPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Page, Plugin as PluginType } from '@jpmorganchase/mosaic-types';
2
+ interface BrokenLinksPluginPage extends Page {
3
+ }
4
+ interface BrokenLinksPluginOptions {
5
+ baseUrl: string;
6
+ skipUrlPatterns?: Array<string | RegExp>;
7
+ proxyEndpoint?: string;
8
+ }
9
+ declare const BrokenLinksPlugin: PluginType<BrokenLinksPluginPage, BrokenLinksPluginOptions>;
10
+ export default BrokenLinksPlugin;