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