@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.
- package/CHANGELOG.md +10 -0
- package/LICENSE +22 -0
- package/README.md +41 -0
- package/esm/breadcrumb-plugin.d.ts +3 -0
- package/esm/breadcrumb-plugin.js +34 -0
- package/esm/breadcrumb-plugin.js.map +1 -0
- package/esm/constants.d.ts +27 -0
- package/esm/constants.js +28 -0
- package/esm/constants.js.map +1 -0
- package/esm/images-plugin.d.ts +3 -0
- package/esm/images-plugin.js +60 -0
- package/esm/images-plugin.js.map +1 -0
- package/esm/index.d.ts +4 -0
- package/esm/index.js +5 -0
- package/esm/index.js.map +1 -0
- package/esm/links-plugin.d.ts +3 -0
- package/esm/links-plugin.js +87 -0
- package/esm/links-plugin.js.map +1 -0
- package/esm/node-utils.d.ts +50 -0
- package/esm/node-utils.js +376 -0
- package/esm/node-utils.js.map +1 -0
- package/esm/plugins.d.ts +138 -0
- package/esm/plugins.js +147 -0
- package/esm/plugins.js.map +1 -0
- package/esm/pubdate-plugin.d.ts +9 -0
- package/esm/pubdate-plugin.js +137 -0
- package/esm/pubdate-plugin.js.map +1 -0
- package/esm/react-plugin.d.ts +3 -0
- package/esm/react-plugin.js +109 -0
- package/esm/react-plugin.js.map +1 -0
- package/esm/shared.d.ts +36 -0
- package/esm/shared.js +157 -0
- package/esm/shared.js.map +1 -0
- package/esm/site-data-plugin.d.ts +25 -0
- package/esm/site-data-plugin.js +135 -0
- package/esm/site-data-plugin.js.map +1 -0
- package/esm/state-version-plugin.d.ts +3 -0
- package/esm/state-version-plugin.js +23 -0
- package/esm/state-version-plugin.js.map +1 -0
- package/esm/template-plugin.d.ts +3 -0
- package/esm/template-plugin.js +10 -0
- package/esm/template-plugin.js.map +1 -0
- package/esm/terms-index-plugin.d.ts +5 -0
- package/esm/terms-index-plugin.js +108 -0
- package/esm/terms-index-plugin.js.map +1 -0
- package/lib/breadcrumb-plugin.d.ts +3 -0
- package/lib/breadcrumb-plugin.js +36 -0
- package/lib/constants.d.ts +27 -0
- package/lib/constants.js +34 -0
- package/lib/images-plugin.d.ts +3 -0
- package/lib/images-plugin.js +84 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +17 -0
- package/lib/links-plugin.d.ts +3 -0
- package/lib/links-plugin.js +89 -0
- package/lib/node-utils.d.ts +50 -0
- package/lib/node-utils.js +412 -0
- package/lib/plugins.d.ts +138 -0
- package/lib/plugins.js +153 -0
- package/lib/pubdate-plugin.d.ts +9 -0
- package/lib/pubdate-plugin.js +143 -0
- package/lib/react-plugin.d.ts +3 -0
- package/lib/react-plugin.js +130 -0
- package/lib/shared.d.ts +36 -0
- package/lib/shared.js +169 -0
- package/lib/site-data-plugin.d.ts +25 -0
- package/lib/site-data-plugin.js +159 -0
- package/lib/state-version-plugin.d.ts +3 -0
- package/lib/state-version-plugin.js +44 -0
- package/lib/template-plugin.d.ts +3 -0
- package/lib/template-plugin.js +12 -0
- package/lib/terms-index-plugin.d.ts +5 -0
- package/lib/terms-index-plugin.js +129 -0
- 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,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
|
package/lib/shared.d.ts
ADDED
|
@@ -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;
|