alchi-book: update config
This commit is contained in:
parent
dd387afb92
commit
7e3eccd3cc
5 changed files with 88 additions and 254 deletions
|
@ -1,3 +1,5 @@
|
|||
const fs = require('fs');
|
||||
|
||||
const staticConfig = {
|
||||
|
||||
// https://github.com/fpapado/eleventy-with-vite/pull/2
|
||||
|
@ -14,7 +16,7 @@ const staticConfig = {
|
|||
|
||||
dir: {
|
||||
input: "src",
|
||||
output: "eleventy-output",
|
||||
output: "build", // not consistent with "default NPM folder layout" where /build contains helper scripts for the build process
|
||||
|
||||
// relative to input https://github.com/11ty/eleventy/issues/232
|
||||
includes: "_includes",
|
||||
|
@ -51,6 +53,8 @@ const staticConfig = {
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = function(eleventyConfig) {
|
||||
|
||||
// make staticConfig reusable outside of eleventy
|
||||
|
@ -407,18 +411,40 @@ module.exports = function(eleventyConfig) {
|
|||
eleventyConfig.addPassthroughCopy({
|
||||
// source paths are relative to the project root
|
||||
// we must copy all files, so css includes can be resolved
|
||||
"node_modules/@fontsource/noto-sans": "css/noto-sans",
|
||||
"node_modules/@fontsource/noto-mono": "css/noto-mono",
|
||||
|
||||
// this would copy too many files
|
||||
//"node_modules/@fontsource/noto-sans": "css/noto-sans",
|
||||
//"node_modules/@fontsource/noto-mono": "css/noto-mono",
|
||||
|
||||
// copy only needed files
|
||||
// what files are needed? see output of: npm run dev
|
||||
"node_modules/@fontsource/noto-sans/latin.css": "css/noto-sans/latin.css",
|
||||
"node_modules/@fontsource/noto-sans/latin-700.css": "css/noto-sans/latin-700.css", // bold font
|
||||
"node_modules/@fontsource/noto-sans/files/noto-sans-latin-400-normal.woff2": "css/noto-sans/files/noto-sans-latin-400-normal.woff2",
|
||||
"node_modules/@fontsource/noto-mono/latin.css": "css/noto-mono/latin.css",
|
||||
}, { expand: true });
|
||||
|
||||
eleventyConfig.addPassthroughCopy({
|
||||
// source paths are relative to the project root
|
||||
// we must copy all files, so css includes can be resolved
|
||||
"src/images": "images",
|
||||
|
||||
// this would copy too many files
|
||||
//"src/images": "images",
|
||||
// svg images are inlined in the build process
|
||||
// raster images (jpg, png, gif) could also be inlined as base64 data urls ...
|
||||
// but for now, we keep them as external files
|
||||
// we only need to inline svg files to fix svg viewports
|
||||
// that would be broken with <img src="img/file.svg">
|
||||
// TODO: make the svg files better accessible in the web interface
|
||||
// -> click to zoom
|
||||
// -> allow to share only the svg image: add public URL to https://milahu.github.io/alchi/src/alchi-book/images/...
|
||||
|
||||
// copy only needed files
|
||||
// what files are needed? see output of: npm run dev
|
||||
"src/images/should-vs-is.disgust-fight.disgusto-pelea.more-contrast.turc-orange.gif": "images/should-vs-is.disgust-fight.disgusto-pelea.more-contrast.turc-orange.gif",
|
||||
"src/images/milahu-orange.jpg": "images/milahu-orange.jpg",
|
||||
}, { expand: true });
|
||||
|
||||
|
||||
|
||||
/* Markdown Overrides */
|
||||
let markdownLibrary = markdownIt({
|
||||
html: true,
|
||||
|
@ -554,8 +580,11 @@ class JsBundle {
|
|||
if (this.staticConfig.isProduction) {
|
||||
return [
|
||||
this.moduleTag(file),
|
||||
this.scriptTag("vite/legacy-polyfills"),
|
||||
this.scriptTag(file.replace(/\.js$/, '-legacy.js'))
|
||||
|
||||
// TODO only needed with @vitejs/plugin-legacy -> auto detect?
|
||||
//this.scriptTag("vite/legacy-polyfills"),
|
||||
//this.scriptTag(file.replace(/\.js$/, '-legacy.js'))
|
||||
|
||||
].join('\n');
|
||||
} else {
|
||||
return [
|
||||
|
|
|
@ -76,19 +76,27 @@ and nonstandard keywords inspired by npm's package.json data format
|
|||
<a class="close" onclick="closeModal('printing')">X</a>
|
||||
<p class="title">Print Settings</p>
|
||||
<div class="content">
|
||||
<span>
|
||||
<p>
|
||||
1. paper format = DIN A4 landscape<br>
|
||||
2. disable margins, scale to 100%<br>
|
||||
3. duplex on, with flip on short edge<br>
|
||||
<br>
|
||||
</p>
|
||||
<p>
|
||||
if you want to print to a different paper format,
|
||||
or if you need to calibrate the page sizes and offsets,
|
||||
see the javascipt source code and change the variables:
|
||||
see the javascipt source code in <code>alchi-book/src/js/main.js</code>
|
||||
and change the variables:
|
||||
page_x, page_y, page_margin, font_size<br>
|
||||
<br>
|
||||
</p>
|
||||
<p>
|
||||
"audit mode" will add space for manual annotations.
|
||||
(should be printed with "linear" layout).
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Print with manual duplex (can be faster than auto duplex):
|
||||
1. print even pages in forward direction.
|
||||
2. print odd pages in reverse direction.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -74,15 +74,15 @@ body {
|
|||
}
|
||||
|
||||
#book-title {
|
||||
font-size: 12mm;
|
||||
line-height: 12mm;
|
||||
font-size: 14mm;
|
||||
line-height: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#book-subtitle {
|
||||
font-size: 6mm;
|
||||
line-height: 6mm;
|
||||
font-size: 8mm;
|
||||
line-height: 100%;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
margin-bottom: 4mm;
|
||||
|
@ -177,6 +177,8 @@ a {
|
|||
position: sticky;
|
||||
top: 0; left: 0; right: 0;
|
||||
background-color: white;
|
||||
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
button {
|
||||
|
@ -406,6 +408,16 @@ del {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* fiduswriter ModTrack */
|
||||
span.approved-insertion {
|
||||
background-color: rgba(0, 255, 0, 0.5);
|
||||
}
|
||||
span.approved-deletion {
|
||||
background-color: rgba(255, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
pre.map16 span.color-1 { color: var(--text1); }
|
||||
pre.map16 span.color-2 { color: var(--text2); }
|
||||
pre.map16 span.color-3 { color: var(--text3); }
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// TODO split into smaller files
|
||||
|
||||
import * as htmldiff from 'htmldiff';
|
||||
import * as Diff from 'diff';
|
||||
|
||||
|
||||
function get_meta() {
|
||||
|
||||
|
@ -639,17 +636,6 @@ function add_language_menu() {
|
|||
}
|
||||
});
|
||||
|
||||
/* this would interfere with the text editor
|
||||
document.addEventListener('keydown', event => {
|
||||
if (event.key == 'l') {
|
||||
event.preventDefault();
|
||||
const sign = +1;
|
||||
const next_lang = lang_list[(lang_list.indexOf(current_lang) + sign) % lang_list.length];
|
||||
set_language(next_lang);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -972,190 +958,6 @@ class Cursor {
|
|||
|
||||
|
||||
|
||||
// text editor
|
||||
|
||||
const debugTextEditor = false;
|
||||
const debugTextEditor2 = false;
|
||||
|
||||
const lastDiffMap = new Map();
|
||||
const editHistoryMap = new Map();
|
||||
let ignoreNextInput = false;
|
||||
let lastInputWasUndo = false;
|
||||
|
||||
function addTextEditor() {
|
||||
|
||||
document.querySelectorAll('span[lang]').forEach(editable => {
|
||||
|
||||
// FIXME? we use 'display: hidden' to hide unused languages
|
||||
if (editable.style.display == 'none') return;
|
||||
//editable.style.display = 'inline-block'; // fix chrome bug https://stackoverflow.com/a/62700928/10440128
|
||||
// problem: 'display: inline-block' breaks float
|
||||
|
||||
editable.setAttribute('data-start-html', editable.innerHTML);
|
||||
editable.setAttribute('contenteditable', 'true');
|
||||
|
||||
const editHistory = [];
|
||||
editHistoryMap.set(editable, editHistory);
|
||||
|
||||
// TODO add input handler only on demand -> editable.onclick
|
||||
|
||||
editable.onkeydown = function(keyboardEvent) {
|
||||
if (debugTextEditor) console.dir(keyboardEvent);
|
||||
const editable = keyboardEvent.target;
|
||||
if (keyboardEvent.ctrlKey && keyboardEvent.key == 'z') { // ctrl + z
|
||||
const editHistory = editHistoryMap.get(editable);
|
||||
if (debugTextEditor) console.log('undo edit on', editable, editHistory.slice());
|
||||
ignoreNextInput = true;
|
||||
if (!lastInputWasUndo) editHistory.pop(); // fix "off by one" bug
|
||||
lastInputWasUndo = true;
|
||||
if (editHistory && editHistory.length > 0) {
|
||||
const { diffHtml, cursor } = editHistory.pop();
|
||||
editable.innerHTML = diffHtml;
|
||||
Cursor.setCurrentCursorPosition(cursor, editable);
|
||||
editable.focus();
|
||||
}
|
||||
else {
|
||||
editable.innerHTML = editable.getAttribute('data-start-html');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
editable.oninput = function(inputEvent) {
|
||||
|
||||
// TODO use InputEvent and cursor
|
||||
// always better than a diff algo
|
||||
// diff algos will always produce false diffs ...
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/InputEvent
|
||||
const inputEventRelevant = {
|
||||
data: inputEvent.data,
|
||||
dataTransfer: inputEvent.dataTransfer,
|
||||
inputType: inputEvent.inputType,
|
||||
// deleteContentBackward
|
||||
// deleteByCut
|
||||
// insertText: insert or replace
|
||||
// insertFromPaste
|
||||
// historyUndo = ctrl + z (todo move handler)
|
||||
// historyRedo = ctrl + y (also without handler)
|
||||
|
||||
isComposing: inputEvent.isComposing,
|
||||
};
|
||||
console.log('inputEventRelevant = ' + JSON.stringify(inputEventRelevant));
|
||||
|
||||
|
||||
|
||||
if (ignoreNextInput) {
|
||||
ignoreNextInput = false;
|
||||
if (debugTextEditor) console.log(`ignore input`);
|
||||
return;
|
||||
}
|
||||
lastInputWasUndo = false;
|
||||
|
||||
if (debugTextEditor) console.dir(inputEvent);
|
||||
|
||||
const editable = inputEvent.target;
|
||||
|
||||
// save cursor position
|
||||
let cursor = Cursor.getCurrentCursorPosition(editable);
|
||||
// NOTE cursor includes html whitespace
|
||||
if (debugTextEditor) console.log(`----`)
|
||||
if (debugTextEditor) console.log(`cursor = ${cursor}`)
|
||||
|
||||
if (debugTextEditor && debugTextEditor2) document.querySelector('textarea[title="diff html"]').innerText = editable.innerHTML.replace(/\n/g, '\\n').replace(/ /g, '·');
|
||||
|
||||
// https://stackoverflow.com/a/23030157/10440128
|
||||
function getText(node) {
|
||||
if (node.nodeType == 3) return node.data; // text node
|
||||
if (!node.childNodes) return '';
|
||||
let s = '';
|
||||
for (let i = 0; i < node.childNodes.length; i++) {
|
||||
s += getText(node.childNodes[i]);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// FIXME inserting into a <del> should be a noop
|
||||
// currently this will move the cursor to the next white-or-green and then start inserting
|
||||
|
||||
if (debugTextEditor && debugTextEditor2) {
|
||||
// FIXME ' ' is printed as ' '
|
||||
// no effect: .replace(/&/g, '&')
|
||||
document.querySelector('textarea[title="diff text"]').innerText = (
|
||||
getText(editable).slice(0, cursor) + '[cursor]' + getText(editable).slice(cursor)
|
||||
).replace(/\n/g, '\\n').replace(/ /g, '·');
|
||||
}
|
||||
|
||||
// diff -> after
|
||||
editable.querySelectorAll('ins').forEach(ins => (ins.outerHTML = ins.innerHTML));
|
||||
editable.querySelectorAll('del').forEach(del => del.remove());
|
||||
|
||||
const htmlA = editable.getAttribute('data-start-html');
|
||||
const htmlB = editable.innerHTML;
|
||||
|
||||
if (debugTextEditor && debugTextEditor2) {
|
||||
document.querySelector('textarea[title="a"]').innerText = htmlA.replace(/\n/g, '\\n').replace(/ /g, '·');
|
||||
document.querySelector('textarea[title="b"]').innerText = htmlB.replace(/\n/g, '\\n').replace(/ /g, '·');
|
||||
}
|
||||
|
||||
const tokensA = htmldiff.htmlToTokens(htmlA);
|
||||
const tokensB = htmldiff.htmlToTokens(htmlB);
|
||||
const diffOps = htmldiff.calculateOperations(tokensA, tokensB);
|
||||
const diffHtml = htmldiff.renderOperations(tokensA, tokensB, diffOps);
|
||||
|
||||
|
||||
|
||||
// get unidiff - quick n dirty
|
||||
const diffUnified = Diff.createTwoFilesPatch('a/file.html', 'b/file.html', htmlA, htmlB)
|
||||
.replace(/^===================================================================\n/s, '');
|
||||
if (debugTextEditor) {
|
||||
document.querySelector('textarea[title="diff -u"]').innerHTML = diffUnified; // .replace(/\n/g, '<br>\n').replace(/ /g, '·');
|
||||
console.log(`diffUnified:\n${diffUnified}`)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//if (debugTextEditor) console.log('diffOps', { diffOps, tokensA, tokensB });
|
||||
|
||||
const lastDiff = lastDiffMap.get(editable);
|
||||
lastDiffMap.set(editable, { tokensA, tokensB, diffOps });
|
||||
|
||||
function getDelsLen(ops, cursor) {
|
||||
return (ops
|
||||
.filter(o => (o.action[0] == 'r' || o.action[0] == 'd'))
|
||||
.map(o => ({
|
||||
posA1: tokensA[o.startInBefore].pos,
|
||||
posA2: tokensA[o.endInBefore].pos + tokensA[o.endInBefore].str.length,
|
||||
}))
|
||||
.filter(o => (o.posA1 <= cursor))
|
||||
.map(o => (o.posA2 - o.posA1))
|
||||
.reduce((acc, val) => (acc + val), 0)
|
||||
);
|
||||
}
|
||||
const cursorOffset = getDelsLen(diffOps, cursor) - (lastDiff ? getDelsLen(lastDiff.diffOps, cursor) : 0);
|
||||
|
||||
if (debugTextEditor) {
|
||||
console.log(`getDelsLen: ${getDelsLen(diffOps, cursor)}, last getDelsLen: ${(lastDiff ? getDelsLen(lastDiff.diffOps, cursor) : 0)}`)
|
||||
console.dir({ diffOps, tokensA, tokensB });
|
||||
console.log(`tok a: |${tokensA.map(t => t.str).join('|').replace(/\n/g, '\\n')}|`)
|
||||
console.log(`tok b: |${tokensB.map(t => t.str).join('|').replace(/\n/g, '\\n')}|`)
|
||||
console.log(`ops:${diffOps.map(o => `\n * ${o.action} ${o.startInBefore}-${o.endInBefore} |${tokensA.slice(o.startInBefore, 1+o.endInBefore).map(t => t.str).join('|').replace(/\n/g, '\\n')}| -> ${o.startInAfter}-${o.endInAfter} |${tokensB.slice(o.startInAfter, 1+o.endInAfter).map(t => t.str).join('|').replace(/\n/g, '\\n')}|`).join('')}`)
|
||||
console.log(`cursorOffset: ${cursorOffset}, cursor: ${cursor} -> ${cursor + cursorOffset}`);
|
||||
}
|
||||
|
||||
cursor += cursorOffset;
|
||||
|
||||
// FIXME if cursor is too lage, we lose focus on the editable
|
||||
|
||||
editHistoryMap.get(editable).push({ diffHtml, cursor })
|
||||
|
||||
editable.innerHTML = diffHtml;
|
||||
Cursor.setCurrentCursorPosition(cursor, editable);
|
||||
editable.focus();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
document.body.onload = function handle_body_loaded() {
|
||||
|
||||
console.log('body loaded');
|
||||
|
@ -1170,26 +972,6 @@ document.body.onload = function handle_body_loaded() {
|
|||
set_language(userLang); // must run after add_layout_menu
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
add_footers();
|
||||
|
||||
|
@ -1497,22 +1279,4 @@ document.body.onload = function handle_body_loaded() {
|
|||
new MutationObserver(handleMutation).observe(head, { childList: true });
|
||||
})();
|
||||
|
||||
/*
|
||||
(new MutationObserver(() => document.body.classList.toggle('dark-reader',
|
||||
document.querySelector('style#dark-reader-style') != null
|
||||
)).observe(document.querySelector('head'), { childList: true }));
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
https://gitter.im/tinymce/tinymce?at=5a8f4dd10202dc012e70e7c7
|
||||
Mike Botsko @viveleroi Feb 23 2018 00:10
|
||||
is there a plugin that shows a "live" diff? For example if a user deletes a word, that word remains visually with a strike-through style, but the resulting textarea value is purely the final result of their edits?
|
||||
if not, is that even remotely possible with the API?
|
||||
*/
|
||||
|
||||
|
||||
addTextEditor(); // must run after set_language
|
||||
|
||||
|
||||
} // handle_body_loaded
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// TODO move to config folder
|
||||
|
||||
import { defineConfig } from "vite";
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
|
||||
|
@ -16,6 +18,20 @@ const rollupOptions = {
|
|||
input: Object.fromEntries(bundlerEntryFiles.map(entryFile => (
|
||||
[assetPath(entryFile), (bundlerEntryDir + entryFile)]
|
||||
))),
|
||||
|
||||
plugins: [],
|
||||
|
||||
// disable "filenames with hash" for assets
|
||||
// so we can commit the "build" folder
|
||||
// and dont have to delete/rename the old build files
|
||||
// https://github.com/vitejs/vite/issues/378#issuecomment-768816653
|
||||
// TODO maybe enable in development mode?
|
||||
output: {
|
||||
entryFileNames: `assets/[name].js`,
|
||||
chunkFileNames: `assets/[name].js`,
|
||||
assetFileNames: `assets/[name].[ext]`
|
||||
},
|
||||
|
||||
};
|
||||
// debug
|
||||
Object.entries(rollupOptions.input).forEach(([key, path]) => {
|
||||
|
@ -25,10 +41,15 @@ console.log(`build.outDir: ${eleventyDirOutput}`);
|
|||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
|
||||
// This is not critical, but I include it because there are more HTML transforms via plugins, that templates must handle
|
||||
// TODO: For legacy() to work without a hitch, we set a known @babel/standalone version in package.json
|
||||
// Remove that once https://github.com/vitejs/vite/issues/2442 is fixed
|
||||
plugins: [legacy()],
|
||||
//plugins: [legacy()],
|
||||
// disabled the legacy plugin cos it generates "filenames with hash" for asset files
|
||||
// https://github.com/vitejs/vite/issues/378
|
||||
// sync with: alchi-book/config/eleventy.config.js footTags(file) {
|
||||
|
||||
build: {
|
||||
// This is important: Generate directly to _site and then assetsDir.
|
||||
// You could opt to build in an intermediate directory,
|
||||
|
|
Loading…
Reference in a new issue