1 | "use strict";
|
2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6 | return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7 | };
|
8 | Object.defineProperty(exports, "__esModule", { value: true });
|
9 | const FS = require("fs-extra");
|
10 | const Path = require("path");
|
11 | const Marked = require("marked");
|
12 | const HighlightJS = require("highlight.js");
|
13 | const Handlebars = require("handlebars");
|
14 | const components_1 = require("../components");
|
15 | const events_1 = require("../events");
|
16 | const component_1 = require("../../utils/component");
|
17 | const declaration_1 = require("../../utils/options/declaration");
|
18 | const customMarkedRenderer = new Marked.Renderer();
|
19 | customMarkedRenderer.heading = (text, level, _, slugger) => {
|
20 | const slug = slugger.slug(text);
|
21 | return `
|
22 | <a href="#${slug}" id="${slug}" style="color: inherit; text-decoration: none;">
|
23 | <h${level}>${text}</h${level}>
|
24 | </a>
|
25 | `;
|
26 | };
|
27 | let MarkedPlugin = class MarkedPlugin extends components_1.ContextAwareRendererComponent {
|
28 | constructor() {
|
29 | super(...arguments);
|
30 | this.includePattern = /\[\[include:([^\]]+?)\]\]/g;
|
31 | this.mediaPattern = /media:\/\/([^ "\)\]\}]+)/g;
|
32 | }
|
33 | initialize() {
|
34 | super.initialize();
|
35 | this.listenTo(this.owner, events_1.MarkdownEvent.PARSE, this.onParseMarkdown);
|
36 | const that = this;
|
37 | Handlebars.registerHelper('markdown', function (arg) { return that.parseMarkdown(arg.fn(this), this); });
|
38 | Handlebars.registerHelper('relativeURL', (url) => url ? this.getRelativeUrl(url) : url);
|
39 | Marked.setOptions({
|
40 | highlight: (text, lang) => this.getHighlighted(text, lang),
|
41 | renderer: customMarkedRenderer
|
42 | });
|
43 | }
|
44 | getHighlighted(text, lang) {
|
45 | try {
|
46 | if (lang) {
|
47 | return HighlightJS.highlight(lang, text).value;
|
48 | }
|
49 | else {
|
50 | return HighlightJS.highlightAuto(text).value;
|
51 | }
|
52 | }
|
53 | catch (error) {
|
54 | this.application.logger.warn(error.message);
|
55 | return text;
|
56 | }
|
57 | }
|
58 | parseMarkdown(text, context) {
|
59 | if (this.includes) {
|
60 | text = text.replace(this.includePattern, (match, path) => {
|
61 | path = Path.join(this.includes, path.trim());
|
62 | if (FS.existsSync(path) && FS.statSync(path).isFile()) {
|
63 | const contents = FS.readFileSync(path, 'utf-8');
|
64 | if (path.substr(-4).toLocaleLowerCase() === '.hbs') {
|
65 | const template = Handlebars.compile(contents);
|
66 | return template(context);
|
67 | }
|
68 | else {
|
69 | return contents;
|
70 | }
|
71 | }
|
72 | else {
|
73 | return '';
|
74 | }
|
75 | });
|
76 | }
|
77 | if (this.mediaDirectory) {
|
78 | text = text.replace(this.mediaPattern, (match, path) => {
|
79 | if (FS.existsSync(Path.join(this.mediaDirectory, path))) {
|
80 | return this.getRelativeUrl('media') + '/' + path;
|
81 | }
|
82 | else {
|
83 | return match;
|
84 | }
|
85 | });
|
86 | }
|
87 | const event = new events_1.MarkdownEvent(events_1.MarkdownEvent.PARSE, text, text);
|
88 | this.owner.trigger(event);
|
89 | return event.parsedText;
|
90 | }
|
91 | onBeginRenderer(event) {
|
92 | super.onBeginRenderer(event);
|
93 | delete this.includes;
|
94 | if (this.includeSource) {
|
95 | const includes = Path.resolve(this.includeSource);
|
96 | if (FS.existsSync(includes) && FS.statSync(includes).isDirectory()) {
|
97 | this.includes = includes;
|
98 | }
|
99 | else {
|
100 | this.application.logger.warn('Could not find provided includes directory: ' + includes);
|
101 | }
|
102 | }
|
103 | if (this.mediaSource) {
|
104 | const media = Path.resolve(this.mediaSource);
|
105 | if (FS.existsSync(media) && FS.statSync(media).isDirectory()) {
|
106 | this.mediaDirectory = Path.join(event.outputDirectory, 'media');
|
107 | FS.copySync(media, this.mediaDirectory);
|
108 | }
|
109 | else {
|
110 | this.mediaDirectory = undefined;
|
111 | this.application.logger.warn('Could not find provided media directory: ' + media);
|
112 | }
|
113 | }
|
114 | }
|
115 | onParseMarkdown(event) {
|
116 | event.parsedText = Marked(event.parsedText);
|
117 | }
|
118 | };
|
119 | __decorate([
|
120 | component_1.Option({
|
121 | name: 'includes',
|
122 | help: 'Specifies the location to look for included documents (use [[include:FILENAME]] in comments).',
|
123 | hint: declaration_1.ParameterHint.Directory
|
124 | })
|
125 | ], MarkedPlugin.prototype, "includeSource", void 0);
|
126 | __decorate([
|
127 | component_1.Option({
|
128 | name: 'media',
|
129 | help: 'Specifies the location with media files that should be copied to the output directory.',
|
130 | hint: declaration_1.ParameterHint.Directory
|
131 | })
|
132 | ], MarkedPlugin.prototype, "mediaSource", void 0);
|
133 | MarkedPlugin = __decorate([
|
134 | components_1.Component({ name: 'marked' })
|
135 | ], MarkedPlugin);
|
136 | exports.MarkedPlugin = MarkedPlugin;
|
137 |
|
\ | No newline at end of file |