1#!/usr/bin/env node
2
3const fs = require('fs');
4const cheerio = require('cheerio');
5const entities = require('html-entities');
6const hljs = require('./build/highlight.js');
7
8const githublink = `\
9<li class="part-title">\
10<a href="https://github.com/dtolnay/cxx">\
11<i class="fa fa-github"></i>\
12https://github.com/dtolnay/cxx\
13</a>\
14</li>`;
15
16const opengraph = `\
17<meta property="og:image" content="https://cxx.rs/cxx.png" />\
18<meta property="og:site_name" content="CXX" />\
19<meta property="og:title" content="CXX — safe interop between Rust and C++" />\
20<meta name="twitter:image:src" content="https://cxx.rs/cxx.png" />\
21<meta name="twitter:site" content="@davidtolnay" />\
22<meta name="twitter:card" content="summary" />\
23<meta name="twitter:title" content="CXX — safe interop between Rust and C++" />`;
24
25const htmljs = `\
26var html = document.querySelector('html');
27html.classList.remove('no-js');
28html.classList.add('js');`;
29
30const dirs = ['build'];
31while (dirs.length) {
32  const dir = dirs.pop();
33  fs.readdirSync(dir).forEach((entry) => {
34    path = dir + '/' + entry;
35    const stat = fs.statSync(path);
36    if (stat.isDirectory()) {
37      dirs.push(path);
38      return;
39    }
40
41    if (!path.endsWith('.html')) {
42      return;
43    }
44
45    const index = fs.readFileSync(path, 'utf8');
46    const $ = cheerio.load(index, { decodeEntities: false });
47
48    $('head').append(opengraph);
49    $('script:nth-of-type(3)').text(htmljs);
50    $('nav#sidebar ol.chapter').append(githublink);
51    $('head link[href="tomorrow-night.css"]').attr('disabled', true);
52    $('head link[href="ayu-highlight.css"]').attr('disabled', true);
53    $('button#theme-toggle').attr('style', 'display:none');
54    $('pre code').each(function () {
55      const node = $(this);
56      const langClass = node.attr('class').split(' ', 2)[0];
57      if (!langClass.startsWith('language-')) {
58        return;
59      }
60      const lang = langClass.replace('language-', '');
61      const lines = node.html().split('\n');
62      const boring = lines.map((line) =>
63        line.includes('<span class="boring">')
64      );
65      const ellipsis = lines.map((line) => line.includes('// ...'));
66      const target = entities.decode(node.text());
67      const highlighted = hljs.highlight(lang, target).value;
68      const result = highlighted
69        .split('\n')
70        .map(function (line, i) {
71          if (boring[i]) {
72            line = '<span class="boring">' + line;
73          } else if (ellipsis[i]) {
74            line = '<span class="ellipsis">' + line;
75          }
76          if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) {
77            line = '</span>' + line;
78          }
79          return line;
80        })
81        .join('\n');
82      node.text(result);
83      node.removeClass(langClass);
84      if (!node.hasClass('focuscomment')) {
85        node.addClass('hidelines');
86        node.addClass('hide-boring');
87      }
88    });
89    $('code').each(function () {
90      $(this).addClass('hljs');
91    });
92
93    const out = $.html();
94    fs.writeFileSync(path, out);
95  });
96}
97
98fs.copyFileSync('build/highlight.css', 'build/tomorrow-night.css');
99fs.copyFileSync('build/highlight.css', 'build/ayu-highlight.css');
100
101var bookjs = fs.readFileSync('build/book.js', 'utf8');
102bookjs = bookjs
103  .replace('set_theme(theme, false);', '')
104  .replace('document.querySelectorAll("code.hljs")', 'document.querySelectorAll("code.hidelines")');
105fs.writeFileSync('build/book.js', bookjs);
106