@podlite/publisher 0.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +22 -0
  3. package/README.md +41 -0
  4. package/esm/breadcrumb-plugin.d.ts +3 -0
  5. package/esm/breadcrumb-plugin.js +34 -0
  6. package/esm/breadcrumb-plugin.js.map +1 -0
  7. package/esm/constants.d.ts +27 -0
  8. package/esm/constants.js +28 -0
  9. package/esm/constants.js.map +1 -0
  10. package/esm/images-plugin.d.ts +3 -0
  11. package/esm/images-plugin.js +60 -0
  12. package/esm/images-plugin.js.map +1 -0
  13. package/esm/index.d.ts +4 -0
  14. package/esm/index.js +5 -0
  15. package/esm/index.js.map +1 -0
  16. package/esm/links-plugin.d.ts +3 -0
  17. package/esm/links-plugin.js +87 -0
  18. package/esm/links-plugin.js.map +1 -0
  19. package/esm/node-utils.d.ts +50 -0
  20. package/esm/node-utils.js +376 -0
  21. package/esm/node-utils.js.map +1 -0
  22. package/esm/plugins.d.ts +138 -0
  23. package/esm/plugins.js +147 -0
  24. package/esm/plugins.js.map +1 -0
  25. package/esm/pubdate-plugin.d.ts +9 -0
  26. package/esm/pubdate-plugin.js +137 -0
  27. package/esm/pubdate-plugin.js.map +1 -0
  28. package/esm/react-plugin.d.ts +3 -0
  29. package/esm/react-plugin.js +109 -0
  30. package/esm/react-plugin.js.map +1 -0
  31. package/esm/shared.d.ts +36 -0
  32. package/esm/shared.js +157 -0
  33. package/esm/shared.js.map +1 -0
  34. package/esm/site-data-plugin.d.ts +25 -0
  35. package/esm/site-data-plugin.js +135 -0
  36. package/esm/site-data-plugin.js.map +1 -0
  37. package/esm/state-version-plugin.d.ts +3 -0
  38. package/esm/state-version-plugin.js +23 -0
  39. package/esm/state-version-plugin.js.map +1 -0
  40. package/esm/template-plugin.d.ts +3 -0
  41. package/esm/template-plugin.js +10 -0
  42. package/esm/template-plugin.js.map +1 -0
  43. package/esm/terms-index-plugin.d.ts +5 -0
  44. package/esm/terms-index-plugin.js +108 -0
  45. package/esm/terms-index-plugin.js.map +1 -0
  46. package/lib/breadcrumb-plugin.d.ts +3 -0
  47. package/lib/breadcrumb-plugin.js +36 -0
  48. package/lib/constants.d.ts +27 -0
  49. package/lib/constants.js +34 -0
  50. package/lib/images-plugin.d.ts +3 -0
  51. package/lib/images-plugin.js +84 -0
  52. package/lib/index.d.ts +4 -0
  53. package/lib/index.js +17 -0
  54. package/lib/links-plugin.d.ts +3 -0
  55. package/lib/links-plugin.js +89 -0
  56. package/lib/node-utils.d.ts +50 -0
  57. package/lib/node-utils.js +412 -0
  58. package/lib/plugins.d.ts +138 -0
  59. package/lib/plugins.js +153 -0
  60. package/lib/pubdate-plugin.d.ts +9 -0
  61. package/lib/pubdate-plugin.js +143 -0
  62. package/lib/react-plugin.d.ts +3 -0
  63. package/lib/react-plugin.js +130 -0
  64. package/lib/shared.d.ts +36 -0
  65. package/lib/shared.js +169 -0
  66. package/lib/site-data-plugin.d.ts +25 -0
  67. package/lib/site-data-plugin.js +159 -0
  68. package/lib/state-version-plugin.d.ts +3 -0
  69. package/lib/state-version-plugin.js +44 -0
  70. package/lib/template-plugin.d.ts +3 -0
  71. package/lib/template-plugin.js +12 -0
  72. package/lib/terms-index-plugin.d.ts +5 -0
  73. package/lib/terms-index-plugin.js +129 -0
  74. package/package.json +52 -0
package/lib/plugins.js ADDED
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.composePlugins = exports.processPlugin = exports.filterFiles = void 0;
4
+ /**
5
+ =begin pod
6
+ =head1 filterFiles
7
+
8
+ This function filters an array of file names based on provided include and exclude patterns. It first converts the includePatterns and excludePatterns arguments into arrays, if they aren't already. The function then filters through the files array, including a file if it matches any of the include patterns (or if no include patterns are provided) and excluding it if it matches any of the exclude patterns. The function returns a new array containing the files that match the include criteria and do not match the exclude criteria.
9
+
10
+ =head2 Parameters
11
+
12
+ =begin item
13
+ B<files>
14
+
15
+ An array of strings, each representing a file name to be filtered.
16
+ =end item
17
+ =begin item
18
+ B<includePatterns>
19
+
20
+ Optional. A string or an array of strings representing the pattern(s) files must match to be included. If not provided, all files are considered to match the include criteria.
21
+ =end item
22
+ =begin item
23
+ B<excludePatterns>
24
+
25
+ Optional. A string or an array of strings representing the pattern(s) files must match to be excluded. If not provided, no files are excluded based on patterns.
26
+ =end item
27
+
28
+ =head2 Returns
29
+
30
+ An array of strings, each representing a file name that matched the include criteria and did not match the exclude criteria.
31
+
32
+ =end pod
33
+ */
34
+ function filterFiles(files, includePatterns, excludePatterns) {
35
+ const patternArray = includePatterns ? (Array.isArray(includePatterns) ? includePatterns : [includePatterns]) : ['.*'];
36
+ const excludePatternArray = excludePatterns
37
+ ? Array.isArray(excludePatterns)
38
+ ? excludePatterns
39
+ : [excludePatterns]
40
+ : [];
41
+ return files.filter(file => {
42
+ const include = patternArray.length === 0 ? true : patternArray.some(pattern => new RegExp(pattern).test(file));
43
+ const exclude = excludePatternArray.length === 0 ? false : excludePatternArray.some(pattern => new RegExp(pattern).test(file));
44
+ return include && !exclude;
45
+ });
46
+ }
47
+ exports.filterFiles = filterFiles;
48
+ /**
49
+ =begin pod
50
+ =head1 processPlugin
51
+
52
+ The function `processPlugin` processes a collection of publishing records based on a given
53
+ plugin configuration. It filters the items to determine which ones match specified inclusion
54
+ and exclusion patterns. Items that match are processed by the provided plugin function, while
55
+ items that do not match are passed through unchanged. Finally, it returns a tuple containing
56
+ the processed items and the result of calling the `onClose` function with a context object.
57
+
58
+ =head2 Parameters
59
+
60
+ =begin item
61
+ B<pluginConf>
62
+
63
+ An object of type `PluginConfig` that provides configuration for the plugin, including
64
+ the plugin processing function, inclusion patterns, and exclusion patterns.
65
+ =end item
66
+ =begin item
67
+ B<items>
68
+
69
+ An array of `publishRecord` objects representing the items to be processed by the plugin.
70
+ =end item
71
+
72
+ =head2 Returns
73
+
74
+ A tuple where the first element is an array of `publishRecord` objects representing
75
+ the processed and unprocessed items, and the second element is an object resulting
76
+ from calling the plugin's `onClose` function with a context object. This object may
77
+ contain arbitrary data based on the plugin's implementation.
78
+
79
+ =end pod
80
+ */
81
+ const processPlugin = (pluginConf, items, ctx = {}) => {
82
+ const [processItems, onClose] = pluginConf.plugin;
83
+ // process items
84
+ const allPaths = items.map(i => i.file);
85
+ const matchedPaths = filterFiles(allPaths, pluginConf.includePatterns || '.*', pluginConf.excludePatterns || []);
86
+ const matchedItems = items.filter(i => matchedPaths.includes(i.file));
87
+ const notMatchedPaths = allPaths.filter(i => !matchedPaths.includes(i));
88
+ const notMatchedItems = items.filter(i => notMatchedPaths.includes(i.file));
89
+ const nextState = [...notMatchedItems, ...processItems(matchedItems)];
90
+ return [nextState, onClose(ctx)];
91
+ };
92
+ exports.processPlugin = processPlugin;
93
+ /**
94
+ =begin pod
95
+ =head1 composePlugins
96
+
97
+ This function takes an array of PluginConfig objects and combines them into a single PluginConfig.
98
+ It does this by sequentially processing each PluginConfig in the array with the next,
99
+ effectively composing their behaviors into a single plugin configuration.
100
+ Each PluginConfig is expected to modify a shared state and context. The composition
101
+ is achieved by chaining the plugin functions within each PluginConfig, so that the
102
+ output (both state and context) of one plugin function becomes the input to the next.
103
+
104
+ =head2 Parameters
105
+
106
+ =begin item
107
+ B<configs>
108
+
109
+ An array of PluginConfig objects. Each PluginConfig is an object that represents
110
+ configuration for a plugin, which includes a plugin processing function and
111
+ potentially other settings.
112
+ =end item
113
+
114
+ =head2 Returns
115
+
116
+ Returns a single PluginConfig object that represents the composed configuration
117
+ of all the PluginConfig objects passed in the 'configs' array. This resulting
118
+ PluginConfig can be used to process items with the combined logic of all the
119
+ plugins defined in the input array.
120
+
121
+ =end pod
122
+ */
123
+ const composePlugins = (configs, inintCtx = {}) => {
124
+ const result = configs.reduce((acc, config) => {
125
+ if (acc.config?.plugin) {
126
+ const accCtx = acc.ctx || {};
127
+ let resultCtx = {};
128
+ const resultConfig = {
129
+ plugin: [
130
+ items => {
131
+ const [processedAccState, processedAccCtx] = (0, exports.processPlugin)(acc.config, items, accCtx);
132
+ const [processedState, processedCtx] = (0, exports.processPlugin)(config, processedAccState, {
133
+ ...accCtx,
134
+ ...processedAccCtx,
135
+ });
136
+ resultCtx = { ...accCtx, ...processedAccCtx, ...processedCtx };
137
+ return processedState;
138
+ },
139
+ () => {
140
+ return { ...accCtx, ...resultCtx };
141
+ },
142
+ ],
143
+ };
144
+ return { config: resultConfig, ctx: resultCtx };
145
+ }
146
+ else {
147
+ return { config, ctx: inintCtx };
148
+ }
149
+ }, { config: {}, ctx: {} });
150
+ return result.config;
151
+ };
152
+ exports.composePlugins = composePlugins;
153
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1,9 @@
1
+ import { publishRecord, PodliteWebPlugin } from '.';
2
+ export interface PodliteWebPluginParams {
3
+ [name: string]: any;
4
+ }
5
+ export declare function getArticles(item: publishRecord): publishRecord[];
6
+ export declare function getNotes(item: publishRecord): publishRecord[];
7
+ export declare function getPages(item: publishRecord): publishRecord[];
8
+ declare const plugin: () => PodliteWebPlugin;
9
+ export default plugin;
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPages = exports.getNotes = exports.getArticles = void 0;
4
+ const schema_1 = require("@podlite/schema");
5
+ const node_utils_1 = require("./node-utils");
6
+ const shared_1 = require("./shared");
7
+ function getArticles(item) {
8
+ let articles = [];
9
+ const { file } = item;
10
+ const _getArticles = array => {
11
+ // // collect alias
12
+ // const aliases = array.filter(i => i.type == 'alias')
13
+ // at first collect all levels
14
+ const levels = array.filter(node => node.level && node.name === 'head') || [];
15
+ const nodesWithPubdate = levels.filter(node => {
16
+ return (0, schema_1.makeAttrs)(node, {}).exists('pubdate');
17
+ });
18
+ if (nodesWithPubdate.length > 0) {
19
+ for (const nodePublished of nodesWithPubdate) {
20
+ // get next header with same level
21
+ const nextHeader = levels
22
+ .slice(levels.indexOf(nodePublished) + 1) // ignore this and previous nodes
23
+ .filter(node => node.level <= nodePublished.level) // stop then found the same or lower level
24
+ .shift();
25
+ let lastIndexOfArticleNode = !nextHeader ? array.length : array.indexOf(nextHeader);
26
+ const articleContent = array.slice(array.indexOf(nodePublished) + 1, lastIndexOfArticleNode);
27
+ if (articleContent.length) {
28
+ const description = (0, schema_1.getFromTree)(articleContent, 'para')[0];
29
+ const pubdate = (0, schema_1.makeAttrs)(nodePublished, {}).getFirstValue('pubdate');
30
+ //TODO: use footer and header of document for generated articles
31
+ articles.push({
32
+ pubdate,
33
+ title: (0, schema_1.getTextContentFromNode)(nodePublished).trim(),
34
+ type: 'page',
35
+ publishUrl: '',
36
+ sources: [],
37
+ node: (0, schema_1.mkRootBlock)({}, articleContent),
38
+ description,
39
+ file,
40
+ });
41
+ }
42
+ }
43
+ }
44
+ array.forEach(node => {
45
+ if (Array.isArray(node.content)) {
46
+ _getArticles(node.content);
47
+ }
48
+ });
49
+ };
50
+ if (typeof item.node !== 'string') {
51
+ _getArticles(item.node.content);
52
+ }
53
+ return articles;
54
+ }
55
+ exports.getArticles = getArticles;
56
+ function getNotes(item) {
57
+ const { file } = item;
58
+ const notes = (0, schema_1.getFromTree)(item.node, 'para')
59
+ .filter(n => (0, schema_1.makeAttrs)(n, {}).exists('pubdate'))
60
+ .map((n) => {
61
+ const a_pubdate = (0, schema_1.makeAttrs)(n, {}).getFirstValue('pubdate');
62
+ // Due to cover some cases whan new Date fail on safari, i.e.
63
+ // new Date("2022-05-07 10:00:00").getFullYear() -> NaN
64
+ // convert to ISO 8601 "2022-05-07 10:00:00" -> "2022-05-07T10:00:00"
65
+ const pubdate = a_pubdate.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/)
66
+ ? a_pubdate.replace(' ', 'T')
67
+ : a_pubdate;
68
+ //TODO: use footer and header of document for generated notes
69
+ return {
70
+ pubdate,
71
+ type: 'note',
72
+ title: null,
73
+ node: (0, schema_1.mkRootBlock)({}, [n]),
74
+ description: n,
75
+ file,
76
+ publishUrl: '',
77
+ sources: [],
78
+ };
79
+ });
80
+ return notes;
81
+ }
82
+ exports.getNotes = getNotes;
83
+ function getPages(item) {
84
+ const { file, sources } = item;
85
+ const pages = (0, schema_1.getFromTree)(item.node, 'pod')
86
+ .filter(n => (0, schema_1.makeAttrs)(n, {}).exists('pubdate'))
87
+ .map((n) => {
88
+ const { title, description, puburl, pubdate } = (0, node_utils_1.getPublishAttributes)(n);
89
+ //TODO: use footer and header of document for generated pages
90
+ return {
91
+ pubdate: pubdate || '',
92
+ type: 'page',
93
+ title,
94
+ node: (0, schema_1.mkRootBlock)({}, [n]),
95
+ description,
96
+ file,
97
+ publishUrl: puburl || '',
98
+ sources,
99
+ };
100
+ });
101
+ return pages;
102
+ }
103
+ exports.getPages = getPages;
104
+ const plugin = () => {
105
+ const outCtx = {};
106
+ const onExit = ctx => ({ ...ctx, ...outCtx });
107
+ const onProcess = (recs) => {
108
+ // extract articles and notes from documents
109
+ const rects1 = recs.reduce((acc, item) => {
110
+ const articles = getArticles(item);
111
+ const notes = getNotes(item);
112
+ const pages = getPages(item);
113
+ return [...acc, ...articles, ...notes, ...pages];
114
+ }, []);
115
+ //filter items with pubdate and sort all by pubdate
116
+ //@ts-ignore
117
+ const allItemForPublish = rects1
118
+ .filter(a => a.pubdate)
119
+ .sort((a, b) => {
120
+ //@ts-ignore
121
+ return new Date(a.pubdate) - new Date(b.pubdate);
122
+ });
123
+ // now filter out items for publish in future
124
+ const isDateInFuture = dateString => {
125
+ return new Date().getTime() < new Date(dateString).getTime();
126
+ };
127
+ // save additional info
128
+ const nextPublishTime = (allItemForPublish.filter(a => isDateInFuture(a.pubdate))[0] || {}).pubdate;
129
+ outCtx.nextPublishTime = nextPublishTime;
130
+ // get not "pages" ( not have publishUrl)
131
+ let notPages = allItemForPublish
132
+ .filter(a => !a.publishUrl)
133
+ .filter(a => !!a.pubdate)
134
+ .filter(a => !isDateInFuture(a.pubdate));
135
+ let Pages = allItemForPublish.filter(a => a.publishUrl).filter(a => !(a.pubdate && isDateInFuture(a.pubdate)));
136
+ const notPagesWithPublishAttrs = (0, shared_1.addUrl)(notPages);
137
+ const allRecords = [...notPagesWithPublishAttrs, ...Pages];
138
+ return allRecords;
139
+ };
140
+ return [onProcess, onExit];
141
+ };
142
+ exports.default = plugin;
143
+ //# sourceMappingURL=pubdate-plugin.js.map
@@ -0,0 +1,3 @@
1
+ import { PodliteWebPlugin } from '.';
2
+ declare const plugin: () => PodliteWebPlugin;
3
+ export default plugin;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ const schema_1 = require("@podlite/schema");
23
+ const constants_1 = require("./constants");
24
+ const fs = __importStar(require("fs"));
25
+ const node_utils_1 = require("./node-utils");
26
+ const shared_1 = require("./shared");
27
+ const plugin = () => {
28
+ const componensMap = new Map();
29
+ const processedNodes = new WeakSet();
30
+ const outCtx = {};
31
+ const onExit = ctx => {
32
+ if (!ctx.testing) {
33
+ // process Components
34
+ let componensFileContent = '';
35
+ for (const key of componensMap.keys()) {
36
+ const componentName = componensMap.get(key);
37
+ componensFileContent += `import ${Array.isArray(componentName) ? `{ ${componentName} }` : componentName} from "${key}"
38
+ export { ${componentName} }
39
+ `;
40
+ }
41
+ componensFileContent += `
42
+ export default {}
43
+ `;
44
+ fs.writeFileSync(constants_1.COMPONENTS_LIB, componensFileContent, 'utf8');
45
+ }
46
+ return { ...ctx, ...outCtx, ...{ componensMap: Object.fromEntries(componensMap) } };
47
+ };
48
+ const processNode = (node, file) => {
49
+ const rules = {
50
+ // process JSX
51
+ useReact: (node, ctx, interator) => {
52
+ const text = (0, schema_1.getTextContentFromNode)(node);
53
+ const importMatchResult = text.match(/^\s*(?<component>\S+)\s*from\s*['"](?<source>\S+)['"]/);
54
+ if (importMatchResult) {
55
+ //@ts-ignore
56
+ const { component, source } = (importMatchResult || {
57
+ groups: { component: undefined, source: undefined },
58
+ }).groups;
59
+ const { path } = source.match(/^\.?\//) ? (0, node_utils_1.getPathToOpen)(source, file) : { path: source };
60
+ // save absolute Component path and Component name
61
+ const notDefaultImport = component.match(/{(.*)}/);
62
+ if (notDefaultImport) {
63
+ const components = notDefaultImport[1].split(/\s*,\s*/);
64
+ // check if already exists
65
+ if (componensMap.has(path)) {
66
+ const savedComponents = componensMap.get(path);
67
+ const onlyUnique = (value, index, self) => self.indexOf(value) === index;
68
+ const newComponents = [...savedComponents, ...components].filter(onlyUnique);
69
+ componensMap.set(path, newComponents);
70
+ }
71
+ else {
72
+ componensMap.set(path, components);
73
+ }
74
+ }
75
+ else {
76
+ componensMap.set(path, component);
77
+ }
78
+ }
79
+ else {
80
+ console.warn(`can't parse =React body. Expected =React Component from './somefile.tsx', but got: ${text}`);
81
+ }
82
+ return;
83
+ },
84
+ React: (node, ctx, interator) => {
85
+ const text = (0, schema_1.getTextContentFromNode)(node);
86
+ const doc = (0, shared_1.makeAstFromSrc)(text);
87
+ return { ...node, content: [interator(doc.content, ctx)] };
88
+ },
89
+ };
90
+ return (0, schema_1.makeInterator)(rules)(node, {});
91
+ };
92
+ const onProcess = (recs) => {
93
+ console.log('react-plugin start');
94
+ const res = recs.map(item => {
95
+ const node = processNode(item.node, item.file);
96
+ // process images inside description
97
+ let extra = {};
98
+ if (item.description) {
99
+ extra.description = processNode(item.description, item.file);
100
+ }
101
+ if (item.template && !processedNodes.has(item.template)) {
102
+ const { footer, header } = item.template;
103
+ const processedTemplate = processNode(item.template.node, item.template.file);
104
+ extra.template = item.template;
105
+ extra.template.node = processedTemplate;
106
+ if (footer) {
107
+ extra.template.footer = processNode(footer, item.template.file);
108
+ }
109
+ if (header) {
110
+ extra.template.header = processNode(header, item.template.file);
111
+ }
112
+ processedNodes.add(item.template);
113
+ }
114
+ // process file header and footer
115
+ const { footer, header } = item;
116
+ if (footer) {
117
+ extra.footer = processNode(footer, item.file);
118
+ }
119
+ if (header) {
120
+ extra.header = processNode(header, item.file);
121
+ }
122
+ return { ...item, node, ...extra };
123
+ });
124
+ return res;
125
+ };
126
+ console.log('react-plugin finished');
127
+ return [onProcess, onExit];
128
+ };
129
+ exports.default = plugin;
130
+ //# sourceMappingURL=react-plugin.js.map
@@ -0,0 +1,36 @@
1
+ import { PodNode } from '@podlite/schema';
2
+ import { publishRecord, pubRecord } from '.';
3
+ export declare const getLangFromFilename: (filename?: string) => any;
4
+ export declare const defaultLangForFile: {
5
+ '.rakudoc': string;
6
+ '.pl': string;
7
+ '.pm': string;
8
+ '.rakumod': string;
9
+ };
10
+ export declare const makeAstFromSrc: (src: string) => import("@podlite/schema").RootBlock;
11
+ export declare function isExistsDocBlocks(node: PodNode): boolean;
12
+ export declare function isExistsPubdate(node: PodNode): boolean;
13
+ export declare function getAllArticles(array: any): Omit<pubRecord, "file">[];
14
+ export declare const addUrl: (items: publishRecord[]) => {
15
+ shortUrl: string;
16
+ publishUrl: string;
17
+ sources: string[];
18
+ type: string;
19
+ pubdate: string;
20
+ node: import("@podlite/schema").RootBlock | (string & import("@podlite/schema").RootBlock) | (import("@podlite/schema").BlockNamed & import("@podlite/schema").RootBlock);
21
+ description?: PodNode;
22
+ file: string;
23
+ title: string;
24
+ template?: publishRecord;
25
+ header?: PodNode;
26
+ footer?: PodNode;
27
+ subtitle?: string;
28
+ pluginsData?: {
29
+ [name: string]: any;
30
+ };
31
+ template_file?: string;
32
+ number?: number;
33
+ sxd: string;
34
+ sequence?: number;
35
+ slug?: string;
36
+ }[];
package/lib/shared.js ADDED
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addUrl = exports.getAllArticles = exports.isExistsPubdate = exports.isExistsDocBlocks = exports.makeAstFromSrc = exports.defaultLangForFile = exports.getLangFromFilename = void 0;
7
+ const schema_1 = require("@podlite/schema");
8
+ const podlite_1 = require("podlite");
9
+ // now we add base60 letters
10
+ const iso_9_1 = __importDefault(require("iso_9"));
11
+ const newbase60_1 = __importDefault(require("newbase60"));
12
+ const getLangFromFilename = (filename) => {
13
+ if (!filename)
14
+ return;
15
+ const ext = filename.split('.').pop();
16
+ return exports.defaultLangForFile[`.${ext}`];
17
+ };
18
+ exports.getLangFromFilename = getLangFromFilename;
19
+ exports.defaultLangForFile = {
20
+ '.rakudoc': 'raku',
21
+ '.pl': 'perl',
22
+ '.pm': 'perl',
23
+ '.rakumod': 'raku',
24
+ };
25
+ const makeAstFromSrc = (src) => {
26
+ let podlite = (0, podlite_1.podlite)({ importPlugins: true }).use({});
27
+ let tree = podlite.parse(src);
28
+ const asAst = podlite.toAstResult(tree).interator;
29
+ return asAst;
30
+ };
31
+ exports.makeAstFromSrc = makeAstFromSrc;
32
+ function isExistsDocBlocks(node) {
33
+ let isExistsDocBlocks = false;
34
+ const markAsDocBlock = (node, ctx, interator) => {
35
+ // skip root block
36
+ if (node.type === 'block' && node.name === 'root') {
37
+ if (node.content) {
38
+ return interator(node.content, ctx);
39
+ }
40
+ return;
41
+ }
42
+ isExistsDocBlocks = true;
43
+ };
44
+ const rules = {
45
+ ':para': markAsDocBlock,
46
+ ':block': markAsDocBlock,
47
+ };
48
+ (0, schema_1.makeInterator)(rules)(node, {});
49
+ return isExistsDocBlocks;
50
+ }
51
+ exports.isExistsDocBlocks = isExistsDocBlocks;
52
+ function isExistsPubdate(node) {
53
+ let isShouldBePublished = false;
54
+ const rules = {
55
+ ':block': (node, ctx, interator) => {
56
+ const config = (0, schema_1.makeAttrs)(node, ctx);
57
+ if (config.exists('pubdate')) {
58
+ isShouldBePublished = true;
59
+ return;
60
+ }
61
+ if (Array.isArray(node.content)) {
62
+ interator(node.content);
63
+ }
64
+ },
65
+ };
66
+ const transformer = (0, schema_1.makeInterator)(rules);
67
+ const res = transformer(node, {});
68
+ return isShouldBePublished;
69
+ }
70
+ exports.isExistsPubdate = isExistsPubdate;
71
+ function getAllArticles(array) {
72
+ let articles = [];
73
+ const getArticles = array => {
74
+ // collect alias
75
+ const aliases = array.filter(i => i.type == 'alias');
76
+ // at first collect all levels
77
+ const levels = array.filter(node => node.level && node.name === 'head') || [];
78
+ const nodesWithPubdate = levels.filter(node => {
79
+ return (0, schema_1.makeAttrs)(node, {}).exists('pubdate');
80
+ });
81
+ if (nodesWithPubdate.length > 0) {
82
+ const nodePublished = nodesWithPubdate[0];
83
+ // get next header with same level
84
+ const nextHeader = levels
85
+ .slice(levels.indexOf(nodePublished) + 1) // ignore this and previous nodes
86
+ .filter(node => node.level <= nodePublished.level) // stop then found the same or lower level
87
+ .shift();
88
+ let lastIndexOfArticleNode = !nextHeader ? array.length : array.indexOf(nextHeader);
89
+ const articleContent = array.slice(array.indexOf(nodePublished) + 1, lastIndexOfArticleNode);
90
+ if (articleContent.length) {
91
+ const description = (0, schema_1.getFromTree)(articleContent, 'para')[0];
92
+ const pubdate = (0, schema_1.makeAttrs)(nodePublished, {}).getFirstValue('pubdate');
93
+ articles.push({
94
+ pubdate,
95
+ type: 'page',
96
+ node: articleContent,
97
+ description,
98
+ });
99
+ }
100
+ }
101
+ array.forEach(node => {
102
+ if (Array.isArray(node.content)) {
103
+ getArticles(node.content);
104
+ }
105
+ });
106
+ };
107
+ getArticles(array);
108
+ return articles;
109
+ }
110
+ exports.getAllArticles = getAllArticles;
111
+ const addUrl = (items) => {
112
+ const withSxd = items.map(i => {
113
+ const { file: f } = i;
114
+ const attrs = i;
115
+ const pubDate = new Date(i.pubdate);
116
+ const sxd = newbase60_1.default.DateToSxg(pubDate);
117
+ const type = i.type === 'note' ? 'n' : 'a';
118
+ // make short name from title
119
+ let words = (attrs.title || '').split(/\s/);
120
+ let res = [];
121
+ while ([...res, words[0]].join(' ').length < 120) {
122
+ //@ts-ignore
123
+ res.push(words.shift());
124
+ }
125
+ let shortTitle = res.join(' ');
126
+ // translit only cyrillic
127
+ const translit2 = /[а-яА-ЯЁё]/.test(shortTitle) ? (0, iso_9_1.default)(shortTitle, 5) : shortTitle;
128
+ // make url clean
129
+ const slug = ((translit2.replace(/`/, '') || '').replace(/\W+/g, '-') || '')
130
+ .replace(/(^[-]+|[-]+$)/g, '')
131
+ .toLowerCase();
132
+ return { ...attrs, type, sxd, slug, file: f };
133
+ });
134
+ // get count of each type on corresponding date
135
+ withSxd.reduce((acc, item) => {
136
+ const { sxd, type } = item;
137
+ acc[sxd] = acc[sxd] || {};
138
+ acc[sxd][type] = acc[sxd][type] || 0;
139
+ acc[sxd][type]++;
140
+ item.number = acc[sxd][type];
141
+ return acc;
142
+ }, {});
143
+ // sequence - index of record at all in that day
144
+ withSxd.reduce((acc, item) => {
145
+ const { sxd } = item;
146
+ acc[sxd] = acc[sxd] || 0;
147
+ acc[sxd]++;
148
+ item.sequence = acc[sxd];
149
+ return acc;
150
+ }, {});
151
+ return withSxd.map(item => {
152
+ const { type, number, sxd, slug, pubdate, sequence } = item;
153
+ const shortUrl = `/${type}${sxd}${number}`;
154
+ // /2019/12/34/a1/WriteAt-my-opensource-startup-on-Perl-6-Pod
155
+ const date = new Date(pubdate);
156
+ const month = date.getMonth() + 1;
157
+ const year = date.getFullYear();
158
+ const day = date.getDate();
159
+ // !!!!! publishUrl may exists
160
+ const publishUrl = `/${year}/${month}/${day}/${sequence}/${slug}`.replace(/\/$/, '');
161
+ const sources = [
162
+ shortUrl,
163
+ // `/${year}/${month}/${day}/${sequence}`,
164
+ ];
165
+ return { ...item, shortUrl, publishUrl, sources };
166
+ });
167
+ };
168
+ exports.addUrl = addUrl;
169
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1,25 @@
1
+ import { PodliteWebPlugin, publishRecord } from '.';
2
+ export interface SiteInfo {
3
+ redirects: {
4
+ source: string;
5
+ destination: string;
6
+ statusCode: number;
7
+ }[];
8
+ postsPerPage: number;
9
+ favicon: string;
10
+ url: string;
11
+ node: any;
12
+ title: string;
13
+ globalStyles: string;
14
+ footer: string;
15
+ gtmId: string;
16
+ item: publishRecord;
17
+ }
18
+ interface siteDataPluginInitParams {
19
+ public_path: string;
20
+ indexFilePath: string;
21
+ built_path: string;
22
+ site_url?: string;
23
+ }
24
+ declare const plugin: ({ public_path, indexFilePath, built_path, site_url, }: siteDataPluginInitParams) => PodliteWebPlugin;
25
+ export default plugin;