opendoc-theme 2.0.0

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. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +43 -0
  4. data/_includes/directory.html +95 -0
  5. data/_includes/document-title.txt +58 -0
  6. data/_includes/toc.html +107 -0
  7. data/_includes/toolbar.html +53 -0
  8. data/_includes/welcome.html +5 -0
  9. data/_layouts/default.html +147 -0
  10. data/_layouts/home.html +4 -0
  11. data/_layouts/iframe.html +13 -0
  12. data/_layouts/page.html +4 -0
  13. data/_layouts/print.html +27 -0
  14. data/_sass/_base.scss +381 -0
  15. data/_sass/_constants.scss +87 -0
  16. data/_sass/_iframe.scss +7 -0
  17. data/_sass/_layout.scss +419 -0
  18. data/_sass/_nav.scss +592 -0
  19. data/_sass/_print.scss +43 -0
  20. data/_sass/_syntax-highlighting.scss +61 -0
  21. data/_sass/_toolbar.scss +372 -0
  22. data/_sass/_welcome.scss +41 -0
  23. data/assets/export.md +30 -0
  24. data/assets/images/chevron-up-white.svg +1 -0
  25. data/assets/images/chevron-up.svg +1 -0
  26. data/assets/images/close.svg +17 -0
  27. data/assets/images/favicon.ico +0 -0
  28. data/assets/images/feedback-hover.svg +3 -0
  29. data/assets/images/feedback-mobile.svg +1 -0
  30. data/assets/images/feedback.svg +1 -0
  31. data/assets/images/github-hover.svg +3 -0
  32. data/assets/images/github.svg +1 -0
  33. data/assets/images/home.svg +14 -0
  34. data/assets/images/index-img.png +0 -0
  35. data/assets/images/logo.png +0 -0
  36. data/assets/images/menu.svg +1 -0
  37. data/assets/images/opendoc-logo-full.svg +10 -0
  38. data/assets/images/pdf-hover.svg +11 -0
  39. data/assets/images/pdf.svg +9 -0
  40. data/assets/images/search-icon-dark.svg +19 -0
  41. data/assets/images/search-icon-white.svg +12 -0
  42. data/assets/images/share.svg +1 -0
  43. data/assets/images/sidebar-hover.svg +3 -0
  44. data/assets/images/sidebar.svg +1 -0
  45. data/assets/images/vertical-dots.svg +1 -0
  46. data/assets/images/x-mobile.svg +1 -0
  47. data/assets/index.html +5 -0
  48. data/assets/js/banner.js +20 -0
  49. data/assets/js/google_analytics.js +11 -0
  50. data/assets/js/header.js +31 -0
  51. data/assets/js/helpers.js +24 -0
  52. data/assets/js/lunr.min.js +6 -0
  53. data/assets/js/navigation.js +202 -0
  54. data/assets/js/page-index.js +57 -0
  55. data/assets/js/pqueue.js +373 -0
  56. data/assets/js/pre-loader.js +43 -0
  57. data/assets/js/search.js +580 -0
  58. data/assets/js/toolbar.js +130 -0
  59. data/assets/siteIndex.json +56 -0
  60. data/assets/startup/build.sh +18 -0
  61. data/assets/startup/docprint.html +20 -0
  62. data/assets/startup/pdf-gen.js +309 -0
  63. data/assets/startup/prebuild-lunr-index.js +52 -0
  64. data/assets/styles/main.scss +13 -0
  65. data/assets/styles/normalize.css +427 -0
  66. data/assets/vendor/babel-polyfill.min.js +3 -0
  67. data/assets/vendor/dom4.js +2 -0
  68. data/assets/vendor/fetch.umd.js +531 -0
  69. data/assets/vendor/headroom.min.js +7 -0
  70. data/assets/vendor/jump.min.js +2 -0
  71. data/assets/vendor/mark.min.js +7 -0
  72. data/assets/vendor/popper.min.js +5 -0
  73. data/assets/vendor/web-share-shim.bundle.min.js +2 -0
  74. metadata +158 -0
@@ -0,0 +1,130 @@
1
+ ---
2
+ ---
3
+ (function () {
4
+ // Hard coded max-width for mobile view
5
+ window.isMobileView = function () {
6
+ return window.innerWidth < 992
7
+ }
8
+
9
+ // Documents - Section toggle
10
+
11
+ // Site-nav
12
+ // --------------------------
13
+ var menuToggle = document.getElementById('menu-toggle')
14
+ var showMenu = function showMenu() {
15
+ menuToggle.checked = true
16
+ document.body.classList.add('menu-toggled')
17
+ }
18
+ var hideMenu = function hideMenu() {
19
+ menuToggle.checked = false
20
+ document.body.classList.remove('menu-toggled')
21
+ }
22
+ menuToggle.addEventListener('change', function () {
23
+ if (menuToggle.checked) {
24
+ showMenu()
25
+ } else {
26
+ hideMenu()
27
+ }
28
+ })
29
+
30
+ var welcomeButton = document.getElementsByClassName('welcome-button')[0]
31
+ if (welcomeButton) {
32
+ welcomeButton.onclick = showMenu
33
+ }
34
+
35
+ // Hide site-nav on navigation
36
+ window.addEventListener('link-click', function () {
37
+ if (isMobileView()) {
38
+ hideMenu()
39
+ }
40
+ })
41
+
42
+ // Edit button
43
+ // --------------------------
44
+ var editButtons = document.querySelectorAll('.edit-btn')
45
+ editButtons.forEach(function (btn) {
46
+ btn.addEventListener('click', function () {
47
+ var repoUrl = '{{ site.github.repository_url }}' + '/blob/master/'
48
+ var page = pageIndex[window.location.pathname]
49
+ var pageUrl = page ? page.escapedPath : null
50
+ if (pageUrl) {
51
+ console.log('opening:', pageUrl)
52
+ repoUrl += pageUrl
53
+ }
54
+ window.open(repoUrl, '_blank')
55
+ })
56
+ })
57
+
58
+ // Print button
59
+ // --------------------------
60
+ var printButtons = document.querySelectorAll('.print-btn')
61
+
62
+ printButtons.forEach(function (btn) {
63
+ btn.addEventListener('click', function () {
64
+ window.open('./export.pdf', '_blank')
65
+ })
66
+ })
67
+
68
+ // Share button
69
+ // -------------------------
70
+ var shareButtons = document.querySelectorAll('.share-btn')
71
+ shareButtons.forEach(function(btn) {
72
+ btn.addEventListener('click', function() {
73
+ if (navigator.share) {
74
+ navigator.share({
75
+ title: {{ site.title | jsonify }},
76
+ text: document.title,
77
+ url: window.location.href
78
+ }).then()
79
+ }
80
+ })
81
+ })
82
+
83
+ // Floating Action Button
84
+ // -----------------------
85
+ var floatingActionButtonTrigger = document.getElementById('fab-trigger')
86
+ var floatingActionButton = document.getElementById('fab')
87
+ floatingActionButtonTrigger.addEventListener('click', function () {
88
+ floatingActionButton.classList.toggle('open')
89
+ });
90
+
91
+ var fabOverlay = document.getElementById('fab-overlay')
92
+ fabOverlay.addEventListener('click', function() {
93
+ floatingActionButton.classList.remove('open')
94
+ })
95
+
96
+ var backToTopButton = document.getElementById('back-to-top')
97
+ backToTopButton.addEventListener('click', function() {
98
+ // jump.js
99
+ Jump(-(window.pageYOffset || document.documentElement.scrollTop), {
100
+ duration: 300
101
+ })
102
+ })
103
+
104
+ // show/hide back-to-top button on scroll and on load
105
+ function scrollListener() {
106
+ var scrollTop = window.pageYOffset || document.documentElement.scrollTop
107
+ if (scrollTop > (window.innerHeight * 2)) {
108
+ backToTopButton.classList.remove('hidden')
109
+ } else {
110
+ backToTopButton.classList.add('hidden')
111
+ }
112
+ }
113
+
114
+ scrollListener()
115
+
116
+ window.addEventListener("scroll", scrollListener)
117
+
118
+ // Search Button for mobile
119
+ // --------------------------
120
+ var searchButtons = document.querySelectorAll('.search-btn')
121
+ var searchBoxElement = document.getElementById('search-box')
122
+ searchButtons.forEach(function(btn) {
123
+ btn.addEventListener('click', function() {
124
+ document.body.classList.toggle('search-toggled')
125
+ if (document.body.classList.contains('search-toggled')) {
126
+ searchBoxElement.focus()
127
+ }
128
+ })
129
+ })
130
+ })()
@@ -0,0 +1,56 @@
1
+ ---
2
+ ---
3
+ {% assign index_array = "" | split: ',' %}
4
+ {%- for page in site.html_pages -%}
5
+ {%- unless page.exclude -%}
6
+ {% unless page.name == 'index.html' or page.name == 'index.md' %}
7
+ {%- assign page_url = page.url -%}
8
+ {%- assign split_content = page.content | markdownify | split: '<h2' | splice: 1 -%}
9
+
10
+ {%- comment -%}Deal with h1 section{%- endcomment -%}
11
+ {%- assign page_header = split_content.first | split: '>' -%}
12
+ {%- assign page_header = page_header[1] | split: '</h1' -%}
13
+ {%- assign page_header = page_header[0] -%}
14
+ {%- assign header_section = '<h1' | append: split_content.first | strip_html | newline_to_br | strip_newlines | replace: '<br />', ' ' | replace: '\', '' | strip | smartify | normalize_whitespace -%}
15
+ {%- capture item -%}
16
+ {
17
+ "title": "{{ page_header}}",
18
+ "documentTitle": "{%- include_cached document-title.txt dir=page.dir info="title" -%}",
19
+ "url": "{{page_url | relative_url }}",
20
+ "text": "{{ header_section }}"
21
+ }
22
+ {% endcapture %}
23
+ {%- assign index_array = index_array | push: item -%}
24
+
25
+ {%- comment -%}Then deal with h2 sections {%- endcomment -%}
26
+ {%- for section in split_content offset:1 -%}
27
+ {%- assign section_header_html = section | split: 'id="' -%}
28
+ {%- assign section_header_html = section_header_html[1] | split: '">' -%}
29
+
30
+ {%- comment -%}Get section id{%- endcomment -%}
31
+ {%- assign section_id = section_header_html[0] -%}
32
+ {%- comment -%}Get section url{%- endcomment -%}
33
+ {%- assign section_url = page_url | append: '#' | append: section_id -%}
34
+
35
+ {%- comment -%}Get section header{%- endcomment -%}
36
+ {%- assign section_header = section_header_html | shift | join | split: '</h2' -%}
37
+ {%- assign section_header = section_header[0] | strip_html -%}
38
+
39
+ {%- comment -%}Get section body{%- endcomment -%}
40
+ {%- assign full_section = '<h2 ' | append:section | strip_html | newline_to_br | strip_newlines | replace: '<br />', ' ' | replace: '\', '' | strip | smartify | normalize_whitespace -%}
41
+ {%- capture item -%}
42
+ {
43
+ "title": "{{ section_header | smartify }}",
44
+ "documentTitle": "{%- include_cached document-title.txt dir=page.dir info="title" -%}",
45
+ "url": "{{ section_url | relative_url }}",
46
+ "text": "{{ full_section }}"
47
+ }
48
+ {% endcapture %}
49
+ {%- assign index_array = index_array | push: item -%}
50
+
51
+ {%- endfor -%}
52
+ {%- endunless -%}
53
+ {%- endunless -%}
54
+ {%- endfor -%}
55
+
56
+ [{{ index_array | join: ','}}]
@@ -0,0 +1,18 @@
1
+ ---
2
+ ---
3
+ #!/bin/bash
4
+
5
+ echo 'Started script to generate PDFs'
6
+ echo 'Installing node dependencies'
7
+ npm i glob jsdom js-yaml p-all
8
+ if [[ (-z "${PDF_GEN_API_SERVER}") || (-z "${PDF_GEN_API_KEY}") ]]; then
9
+ npm i html-pdf
10
+ fi
11
+ node _site/assets/startup/pdf-gen.js
12
+ if [ "{{ site.offline_search_only }}" == "true" ]; then
13
+ node _site/assets/startup/prebuild-lunr-index.js
14
+ echo 'Generating Lunr Index complete'
15
+ else
16
+ echo 'Skipping Lunr Index'
17
+ fi
18
+ echo 'End script'
@@ -0,0 +1,20 @@
1
+ <!-- layout for printing individual documents-->
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <meta charset="utf-8">
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+
10
+ <link rel="icon" href="./assets/images/favicon.ico">
11
+ <link rel="stylesheet" href="./assets/styles/normalize.css">
12
+ <link rel="stylesheet" href="./assets/styles/main.css">
13
+ </head>
14
+
15
+ <body id=print-content>
16
+ <div id="main-content" class="site-main">
17
+ </div>
18
+ </body>
19
+
20
+ </html>
@@ -0,0 +1,309 @@
1
+ const fs = require('fs')
2
+ const fsp = require('fs').promises
3
+ const pAll = require('p-all')
4
+ const https = require('https')
5
+ const glob = require('glob')
6
+ const path = require('path')
7
+ const jsdom = require('jsdom')
8
+ const jsyaml = require('js-yaml')
9
+ const sitePath = __dirname + '/../..'
10
+
11
+ // Env vars to generate PDFs on AWS Lambda
12
+ let pdfGenVarsPresent = true
13
+ let pdf
14
+ let PDF_GEN_CONCURRENCY
15
+
16
+ if (process.env.PDF_GEN_API_KEY === undefined || process.env.PDF_GEN_API_SERVER === undefined) {
17
+ console.log('Env var PDF_GEN_API_KEY or PDF_GEN_API_SERVER for AWS Lambda not present: Generating PDFs locally instead.')
18
+ pdf = require('html-pdf')
19
+ pdfGenVarsPresent = false
20
+ PDF_GEN_CONCURRENCY = 1 // When generating locally make it synchronous
21
+ } else {
22
+ PDF_GEN_CONCURRENCY = process.env.PDF_GEN_CONCURRENCY !== undefined ?
23
+ parseInt(process.env.PDF_GEN_CONCURRENCY) :
24
+ 50 // Tuned for Netlify
25
+ console.log(`Env vars detected: Generating PDFs on AWS Lambda with concurrency of ${PDF_GEN_CONCURRENCY}`)
26
+ }
27
+
28
+ // These options are only applied when PDFs are built locally
29
+ const localPdfOptions = {
30
+ height: '594mm', // allowed units: mm, cm, in, px
31
+ width: '420mm',
32
+ base: 'file://' + sitePath + '/',
33
+ border: {
34
+ right: '100px', // default is 0, units: mm, cm, in, px
35
+ left: '100px',
36
+ },
37
+ header: {
38
+ height: '80px',
39
+ },
40
+ footer: {
41
+ height: '80px',
42
+ },
43
+ }
44
+
45
+ // List of top-level folder names which may contain html but are not to be printed
46
+ const printIgnoreFolders = ['assets', 'files', 'iframes', 'images']
47
+ // List of top-level .html files which are not to be printed
48
+ const printIgnoreFiles = ['export.html', 'index.html']
49
+
50
+ // Tracking statistics
51
+ let numPdfsStarted = 0
52
+ let numPdfsError = 0
53
+ let numPdfsSuccess = 0
54
+ let numTotalPdfs = 0
55
+ const TIMER = 'Time to create PDFs'
56
+
57
+ const main = async () => {
58
+
59
+ // creating exports of individual documents
60
+ console.time(TIMER)
61
+ const docFolders = getDocumentFolders(sitePath, printIgnoreFolders)
62
+ await exportPdfTopLevelDocs(sitePath)
63
+ await exportPdfDocFolders(sitePath, docFolders)
64
+ console.log(`PDFs created with success:${numPdfsSuccess} error:${numPdfsError} total:${numTotalPdfs}`)
65
+ console.timeEnd(TIMER)
66
+ }
67
+
68
+ const exportPdfTopLevelDocs = async (sitePath) => {
69
+ let htmlFilePaths = glob.sync('*.html', { cwd: sitePath })
70
+ htmlFilePaths = htmlFilePaths.filter((filepath) => !printIgnoreFiles.includes(filepath))
71
+ htmlFilePaths = htmlFilePaths.map((filepath) => path.join(sitePath, filepath))
72
+ // Remove folders without HTML files (don't want empty pdfs)
73
+ if (htmlFilePaths.length === 0) return
74
+ numTotalPdfs++
75
+ const configFilepath = path.join(sitePath, '..', '_config.yml')
76
+ if (configFileHasValidOrdering(configFilepath)) {
77
+ const configYml = yamlToJs(configFilepath)
78
+ htmlFilePaths = reorderHtmlFilePaths(htmlFilePaths, configYml.order)
79
+ }
80
+ await createPdf(htmlFilePaths, sitePath)
81
+ }
82
+
83
+ const exportPdfDocFolders = (sitePath, docFolders) => {
84
+ const actions = []
85
+ for (let folder of docFolders) {
86
+ // find all the folders containing html files
87
+ const folderPath = path.join(sitePath, folder)
88
+ let htmlFilePaths = glob.sync('*.html', { cwd: folderPath })
89
+ htmlFilePaths = htmlFilePaths.filter((filepath) => !printIgnoreFiles.includes(filepath))
90
+ htmlFilePaths = htmlFilePaths.map((filepath) => path.join(folderPath, filepath))
91
+
92
+ // Remove folders without HTML files (don't want empty pdfs)
93
+ if (htmlFilePaths.length === 0) return
94
+ numTotalPdfs++
95
+ const indexFilepath = path.join(sitePath, '..', folder, 'index.md')
96
+ if (indexFileHasValidOrdering(indexFilepath)) {
97
+ const configMd = markdownToJs(indexFilepath)
98
+ const order = configMd.order
99
+ htmlFilePaths = reorderHtmlFilePaths(htmlFilePaths, order)
100
+ }
101
+ actions.push((() => createPdf(htmlFilePaths, folderPath)))
102
+ }
103
+ return pAll(actions, { concurrency: PDF_GEN_CONCURRENCY })
104
+ }
105
+
106
+ // Concatenates the contents in .html files, and outputs export.pdf in the specified output folder
107
+ const createPdf = (htmlFilePaths, outputFolderPath) => {
108
+ logStartedPdf(outputFolderPath)
109
+ // docprint.html is our template to build pdf up from.
110
+ const exportHtmlFile = fs.readFileSync(__dirname + '/docprint.html')
111
+ const exportDom = new jsdom.JSDOM(exportHtmlFile)
112
+ const exportDomBody = exportDom.window.document.body
113
+ const exportDomMain = exportDom.window.document.getElementById('main-content')
114
+ let addedTitle = false
115
+ let addedDocTitle = false
116
+
117
+ htmlFilePaths.forEach(function (filePath) {
118
+ const file = fs.readFileSync(filePath)
119
+ const dom = new jsdom.JSDOM(file, {
120
+ resources: 'usable' // to get JSDOM to load stylesheets
121
+ })
122
+
123
+ // html-pdf can't deal with these
124
+ removeTagsFromDom(dom, 'script')
125
+ removeTagsFromDom(dom, 'iframe')
126
+
127
+ // If a <img src=...> link src begins with '/', it is a relative link
128
+ // and needs to be prepended with '.' to show up in the pdf. Does not
129
+ // work for Lambda functions as the images are not available server side.
130
+ const imgsrcs = dom.window.document.getElementsByTagName('img')
131
+ for (let i = 0; i < imgsrcs.length; i++) {
132
+ const imgsrc = imgsrcs[i]
133
+ if (imgsrc.src.startsWith('/')) {
134
+ imgsrc.src = '.' + imgsrc.src
135
+ } else if (imgsrc.src.startsWith('.')) {
136
+ imgsrc.src = outputFolderPath + imgsrc.src.substr(1)
137
+ }
138
+ }
139
+
140
+ // Site titles needs only be added once
141
+ if (!addedTitle) {
142
+ try {
143
+ const oldTitle = dom.window.document.getElementsByClassName('site-header-text')[0]
144
+ exportDomBody.insertBefore(oldTitle, exportDomMain)
145
+ addedTitle = true
146
+ } catch (error) {
147
+ console.log('Failed to append Title, skipping: ' + error)
148
+ }
149
+ }
150
+ // Document titles too
151
+ if (!addedDocTitle) {
152
+ try {
153
+ const oldDocTitle = dom.window.document.getElementsByClassName('description-container')[0]
154
+ exportDomBody.insertBefore(oldDocTitle, exportDomMain)
155
+ const hr = dom.window.document.createElement('HR')
156
+ exportDomBody.insertBefore(hr, exportDomMain)
157
+ addedDocTitle = true
158
+ } catch (error) {
159
+ console.log('Failed to append Doc Title, skipping: ' + error)
160
+ }
161
+ }
162
+
163
+ // Concat all the id:main-content divs
164
+ try {
165
+ const oldNode = dom.window.document.getElementById('main-content')
166
+ exportDomMain.innerHTML += oldNode.innerHTML
167
+ } catch (error) {
168
+ console.log('Failed to append Node, skipping: ' + error)
169
+ }
170
+ dom.window.close()
171
+ })
172
+
173
+ if (!pdfGenVarsPresent) {
174
+ return new Promise((resolve, reject) => {
175
+ pdf.create(exportDom.serialize(), localPdfOptions).toFile(path.join(outputFolderPath, 'export.pdf'), (err, res) => {
176
+ if (err) {
177
+ logErrorPdf('Creating PDFs locally', err)
178
+ return reject()
179
+ }
180
+ logSuccessPdf(res.filename)
181
+ resolve()
182
+ })
183
+ exportDom.window.close()
184
+ })
185
+ } else {
186
+ // Code for this API lives at https://github.com/opendocsg/pdf-lambda
187
+ const requestOptions = {
188
+ method: 'POST',
189
+ responseType: 'arraybuffer',
190
+ headers: {
191
+ 'x-api-key': process.env.PDF_GEN_API_KEY,
192
+ 'content-type': 'application/json',
193
+ },
194
+ }
195
+ return new Promise(function(resolve, reject) {
196
+ const request = https.request(process.env.PDF_GEN_API_SERVER, requestOptions, function(res) {
197
+ if (res.statusCode < 200 || res.statusCode >= 300) {
198
+ logErrorPdf('Request status code', res.statusCode)
199
+ reject()
200
+ }
201
+ const chunks = []
202
+ res.on('data', function(d) {
203
+ chunks.push(d)
204
+ })
205
+ res.on('end', function() {
206
+ const buf = Buffer.concat(chunks)
207
+ resolve(buf)
208
+ })
209
+ })
210
+ request.on('error', (err) => {
211
+ logErrorPdf('Request encountered error', err)
212
+ reject()
213
+ })
214
+ // POST request body
215
+ request.write(JSON.stringify({
216
+ 'serializedDom': exportDom.serialize()
217
+ }))
218
+ request.end()
219
+ exportDom.window.close()
220
+ }).then((buffer) => {
221
+ const outputPdfPath = path.join(outputFolderPath, 'export.pdf')
222
+ return fsp.writeFile(outputPdfPath, buffer)
223
+ .then(() => {
224
+ logSuccessPdf(outputPdfPath)
225
+ }).catch((err) => {
226
+ logErrorPdf('Writing out file', err)
227
+ })
228
+ }).catch((error) => {
229
+ logErrorPdf('Request promise', error)
230
+ })
231
+ }
232
+ }
233
+
234
+ const logStartedPdf = (outputFolderPath) => {
235
+ numPdfsStarted++
236
+ console.log(`createpdf started for:${outputFolderPath} (${numPdfsStarted}/${numTotalPdfs})`)
237
+ }
238
+
239
+ const logErrorPdf = (origin, error) => {
240
+ numPdfsError++
241
+ console.log(`createpdf error for: ${origin}: ${error}(${numPdfsError}/${numTotalPdfs})`)
242
+ }
243
+
244
+ const logSuccessPdf = (outputPdfPath) => {
245
+ numPdfsSuccess++
246
+ console.log(`createpdf success for:${outputPdfPath} (${numPdfsSuccess}/${numTotalPdfs})`)
247
+ }
248
+
249
+ // Returns a list of the valid document (i.e. folder) paths
250
+ const getDocumentFolders = (sitePath, printIgnoreFolders) => {
251
+ return fs.readdirSync(sitePath).filter(function (filePath) {
252
+ return fs.statSync(path.join(sitePath, filePath)).isDirectory() &&
253
+ !printIgnoreFolders.includes(filePath)
254
+ })
255
+ }
256
+
257
+ // Returns true if config file contains section_order field
258
+ const configFileHasValidOrdering = (configFilepath) => {
259
+ try {
260
+ const configYml = yamlToJs(configFilepath)
261
+ return 'order' in configYml
262
+ } catch (error) {
263
+ return false
264
+ }
265
+ }
266
+
267
+ // Returns true if index.md exists and contains order field
268
+ const indexFileHasValidOrdering = (indexFilepath) => {
269
+ try {
270
+ const configMd = markdownToJs(indexFilepath)
271
+ return 'order' in configMd
272
+ } catch (error) {
273
+ return false
274
+ }
275
+ }
276
+
277
+ // Mutates the htmlFilepath array to match order provided in order
278
+ const reorderHtmlFilePaths = (htmlFilePaths, order) => {
279
+ const orderedHtmlFilePaths = []
280
+ for (let i = 0; i < order.length; i++) {
281
+ const name = path.basename(order[i], '.md')
282
+ htmlFilePaths.some((filePath) => {
283
+ if (path.basename(filePath, '.html') === name) {
284
+ orderedHtmlFilePaths.push(filePath)
285
+ }
286
+ })
287
+ }
288
+ return orderedHtmlFilePaths
289
+ }
290
+
291
+ // Removes <tag></tag> from dom and everything in between them
292
+ const removeTagsFromDom = (dom, tagname) => {
293
+ const tags = dom.window.document.getElementsByTagName(tagname)
294
+ for (let i = tags.length - 1; i >= 0; i--) {
295
+ tags[i].parentNode.removeChild(tags[i])
296
+ }
297
+ }
298
+
299
+ // converts .md to JS Object
300
+ const markdownToJs = (filepath) => {
301
+ const configString = fs.readFileSync(filepath).toString().replace(/---/g, '')
302
+ return jsyaml.safeLoad(configString)
303
+ }
304
+
305
+ const yamlToJs = (filepath) => {
306
+ return jsyaml.safeLoad(fs.readFileSync(filepath))
307
+ }
308
+
309
+ main()