UNPKG

3.86 kBJavaScriptView Raw
1'use strict'
2
3const fs = require('fs')
4const path = require('path')
5const async = require('async')
6const stream = require('stream')
7const Showdown = require('showdown')
8
9class Recommendation {
10 constructor (settings) {
11 Object.assign(this, settings)
12 }
13
14 // Iterate over the files and annotate them with the type.
15 [Symbol.iterator] () {
16 const files = []
17
18 files.push({
19 type: 'summary',
20 filepath: this.summary
21 })
22
23 if (this.readMore) {
24 files.push({
25 type: 'read-more',
26 filepath: this.readMore
27 })
28 }
29
30 return files[Symbol.iterator]()
31 }
32}
33
34// Create recommendation object for each category
35const recommendations = [
36 new Recommendation({
37 category: 'gc',
38 issue: true,
39 title: 'a potential Garbage Collection issue',
40 menu: 'Garbage Collection',
41 order: 1,
42 summary: path.resolve(__dirname, 'gc-summary.md'),
43 readMore: path.resolve(__dirname, 'gc-readmore.md')
44 }),
45 new Recommendation({
46 category: 'event-loop',
47 issue: true,
48 title: 'a potential Event Loop issue',
49 menu: 'Event Loop',
50 order: 2,
51 summary: path.resolve(__dirname, 'event-loop-summary.md'),
52 readMore: path.resolve(__dirname, 'event-loop-readmore.md')
53 }),
54 new Recommendation({
55 category: 'io',
56 issue: true,
57 title: 'a potential I/O issue',
58 menu: 'I/O',
59 order: 3,
60 summary: path.resolve(__dirname, 'io-summary.md'),
61 readMore: path.resolve(__dirname, 'io-readmore.md')
62 }),
63 new Recommendation({
64 category: 'data',
65 issue: true,
66 title: 'data analysis issue',
67 menu: 'Bad data',
68 order: 4,
69 summary: path.resolve(__dirname, 'data-summary.md'),
70 readMore: null
71 }),
72 new Recommendation({
73 category: 'unknown',
74 issue: true,
75 title: 'an unknown issue',
76 menu: 'Unknown issue',
77 order: 5,
78 summary: path.resolve(__dirname, 'unknown-summary.md'),
79 readMore: path.resolve(__dirname, 'unknown-readmore.md')
80 }),
81 new Recommendation({
82 category: 'none',
83 issue: false,
84 title: 'no issue',
85 menu: 'No issue',
86 order: 6,
87 summary: path.resolve(__dirname, 'none-summary.md'),
88 readMore: null
89 })
90]
91
92const md = new Showdown.Converter({
93 noHeaderId: true,
94 simplifiedAutoLink: true,
95 excludeTrailingPunctuationFromURLs: true,
96 strikethrough: true,
97 tables: true,
98 ghCodeBlocks: true,
99 simpleLineBreaks: false
100})
101
102class RenderRecommendations extends stream.Readable {
103 constructor (options) {
104 super(options)
105
106 // create a reading queue over all the categories
107 this._readingQueue = recommendations[Symbol.iterator]()
108 }
109
110 _read (size) {
111 const self = this
112 const read = this._readingQueue.next()
113 if (read.done) return this.push(null)
114
115 // read the recommendation files for this category
116 const recommendation = read.value
117 async.map(
118 recommendation,
119 function (file, done) {
120 fs.readFile(file.filepath, 'utf-8', function (err, content) {
121 if (err) return done(err)
122 const template =
123 '<template class="recommendation-text"' +
124 ` data-issue="${recommendation.issue ? 'yes' : 'no'}"` +
125 ` data-type="${file.type}"` +
126 ` data-category="${recommendation.category}"` +
127 ` data-menu="${recommendation.menu}"` +
128 ` data-title="${recommendation.title}"` +
129 ` data-order="${recommendation.order}"` +
130 '>\n' +
131 `${md.makeHtml(content)}\n` +
132 '</template>'
133
134 done(null, template)
135 })
136 },
137 function (err, result) {
138 if (err) return self.emit('error', err)
139
140 // Join summary and read-more text
141 const output = result.join('\n') + '\n'
142
143 // Push output and continue reading if required
144 self.push(output)
145 }
146 )
147 }
148}
149
150module.exports = RenderRecommendations