From ef640752cc13bbf8c16b24639bfe4074e5ab20f6 Mon Sep 17 00:00:00 2001 From: Heerko Date: Sat, 27 Dec 2025 14:51:12 +0100 Subject: [PATCH] import changes from lepa --- filter_registry.py | 18 ++ octomode.py | 86 ++++++--- pad_filters.py | 15 ++ settings.py | 3 +- static/footnotes.js | 55 ++++++ static/imposition.js | 428 +++++++++++++++++++++++++++++++++++++++++ static/main.css | 16 ++ static/pagedjs.css | 11 ++ templates/base.html | 4 +- templates/default.css | 114 +++++++++-- templates/default.md | 80 ++++---- templates/pagedjs.html | 17 +- templates/pdf.html | 11 +- templates/preview.html | 3 +- templates/start.html | 2 + 15 files changed, 780 insertions(+), 83 deletions(-) create mode 100644 filter_registry.py create mode 100644 pad_filters.py create mode 100644 static/footnotes.js create mode 100644 static/imposition.js diff --git a/filter_registry.py b/filter_registry.py new file mode 100644 index 0000000..e68c0a7 --- /dev/null +++ b/filter_registry.py @@ -0,0 +1,18 @@ +# This is an attempt to create a customizable way to +# add filters to the content coming from the etherpad +# get_text api endpoint +# in pad_filters.py do this: +# +# import re +# from filter_registry import register_filter + +# @register_filter +# def remove_star_before_img(text): +# return re.sub(r'\*\s*!?\[\]\(', '![](', text) + +pad_content_filters = [] + +def register_filter(func): + print(f"Registering filter: {func.__name__}") + pad_content_filters.append(func) + return func \ No newline at end of file diff --git a/octomode.py b/octomode.py index e4af7b2..bc928ed 100755 --- a/octomode.py +++ b/octomode.py @@ -3,6 +3,7 @@ import json from flask import Flask, request, render_template, redirect, url_for from urllib.request import urlopen from urllib.parse import urlencode +import html # To sanitize Flask input fields from markupsafe import Markup, escape @@ -14,6 +15,11 @@ import pypandoc # To read the Markdown metadat import markdown + +from filter_registry import pad_content_filters +import pad_filters + + APP = Flask(__name__) APP.config.from_pyfile('settings.py') @@ -40,6 +46,11 @@ def get_pad_content(pad_name, ext=""): response = json.load(urlopen(f"{ APP.config['PAD_API_URL'] }/{ api_call }", data=urlencode(arguments).encode())) content = response['data']['text'] + # print("before: " + content) + print( "GET PAD CONTENT" ) + for f in pad_content_filters: + content = f(content) + # print("after: " + content) return content def all_pads(): @@ -95,6 +106,25 @@ def get_md_metadata(md_pad_content): return metadata +def get_app_root(): + if APP.config['APPLICATION_ROOT'] == '/': + app_root = '' + elif APP.config['APPLICATION_ROOT'].endswith('/'): + app_root = APP.config['APPLICATION_ROOT'][:-1] + else: + app_root = APP.config['APPLICATION_ROOT'] + return app_root + + +# def apply_cover(html_str, cover): +# import html +# html_str = str(html_str) +# html_str = html_str.replace('class="cover"', "class='cover' style='background-image: url("+ cover +")'") +# return Markup(html_str) + +def get_meta(metadata, key, default=None): + return metadata.get(key, [default])[0] + # --- @APP.route('/', methods=['GET', 'POST']) @@ -110,7 +140,7 @@ def index(): create_pad_on_first_run(name, ext) return redirect(url_for("pad", name=name)) else: - return render_template('start.html', pad_url=APP.config['PAD_URL']) + return render_template('start.html', home_pad_url=APP.config['HOME_PAD_URL']) @APP.route('//') def main(name): @@ -128,28 +158,22 @@ def stylesheet(name): @APP.route('//html/') def html(name): - # only here we need application root to make all the URLs work..... - if APP.config['APPLICATION_ROOT'] == '/': - app_root = '' - elif APP.config['APPLICATION_ROOT'].endswith('/'): - app_root = APP.config['APPLICATION_ROOT'][:-1] - else: - app_root = APP.config['APPLICATION_ROOT'] + app_root = get_app_root() url = f"{ app_root }/{ name }/preview.html" return render_template('iframe.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) @APP.route('//pdf/') def pdf(name): - # only here we need application root to make all the URLs work..... - if APP.config['APPLICATION_ROOT'] == '/': - app_root = '' - elif APP.config['APPLICATION_ROOT'].endswith('/'): - app_root = APP.config['APPLICATION_ROOT'][:-1] - else: - app_root = APP.config['APPLICATION_ROOT'] + app_root = get_app_root() url = f"{ app_root }/{name}/pagedjs.html" return render_template('pdf.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) +@APP.route('//impose/') +def impose(name): + app_root = get_app_root() + url = f"{ app_root }/{name}/imposed.html" + return render_template('pdf.html', url=url, name=name.strip(), pad_url=APP.config['PAD_URL']) + # ////////////////// # RENDERED RESOURCES # ////////////////// @@ -168,13 +192,9 @@ def preview(name): md_pad_content = get_pad_content(name, ext='.md') html = md_to_html(md_pad_content) metadata = get_md_metadata(md_pad_content) - if metadata: - lang = metadata['language'][0] - title = metadata['title'][0] - else: - lang = "en" - title = "No title" - + lang = get_meta(metadata, 'language', 'en') + title = get_meta(metadata, 'title', 'Untitled') + return render_template('preview.html', name=name.strip(), pad_content=html, lang=lang, title=title) @APP.route('//pagedjs.html') @@ -183,10 +203,26 @@ def pagedjs(name): md_pad_content = get_pad_content(name, ext='.md') html = md_to_html(md_pad_content) metadata = get_md_metadata(md_pad_content) - lang = metadata['language'][0] - title = metadata['title'][0] + lang = get_meta(metadata, 'language', 'en') + title = get_meta(metadata, 'title', 'Untitled') + cover = get_meta(metadata, 'cover', None) - return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title) + impose = False #request.args.get("impose") == "true" + + return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title, cover=cover, impose=impose) + +@APP.route('//imposed.html') +def imposed(name): + # TO GENERATE THE PAGED.JS WEBPAGE + md_pad_content = get_pad_content(name, ext='.md') + html = md_to_html(md_pad_content) + metadata = get_md_metadata(md_pad_content) + lang = get_meta(metadata, 'language', 'en') + title = get_meta(metadata, 'title', 'Untitled') + + impose = True #request.args.get("impose") == "true" + + return render_template('pagedjs.html', name=name.strip(), pad_content=html, lang=lang, title=title, impose=impose) # ////////////////// diff --git a/pad_filters.py b/pad_filters.py new file mode 100644 index 0000000..a91048b --- /dev/null +++ b/pad_filters.py @@ -0,0 +1,15 @@ +import re +from filter_registry import register_filter + +@register_filter +def remove_star_before_img(text): + # regex version + return re.sub(r'\*\s*!?\[\]\(', '![](', text) + +# @register_filter +# def remove_star_before_img(text): +# # print(">>> filter running") +# # print(">>> before:", repr(text)) +# text = text.replace('*![](', '![](') +# # print(">>> after:", repr(text)) +# return text \ No newline at end of file diff --git a/settings.py b/settings.py index 3382679..52b6f33 100644 --- a/settings.py +++ b/settings.py @@ -9,7 +9,8 @@ APPLICATION_ROOT = os.environ.get('OCTOMODE_APPLICATION_ROOT', '/') PORTNUMBER = int(os.environ.get('OCTOMODE_PORTNUMBER', 5001)) PAD_URL = os.environ.get('OCTOMODE_PAD_URL', 'https://pad.vvvvvvaria.org') PAD_API_URL = os.environ.get('OCTOMODE_PAD_API_URL', 'https://pad.vvvvvvaria.org/api/1.2.15') -PAD_API_KEY = os.environ.get('OCTOMODE_PAD_API_KEY', '') +PAD_API_KEY = "97e3bf6a626eaaa3426833db3d936f3a" +#os.environ.get('OCTOMODE_PAD_API_KEY', '') # Check if API key is provided if not PAD_API_KEY or PAD_API_KEY == "XXX": diff --git a/static/footnotes.js b/static/footnotes.js new file mode 100644 index 0000000..2138352 --- /dev/null +++ b/static/footnotes.js @@ -0,0 +1,55 @@ +/* +Adds a custom css property that switches footnote style +between endnodes (default for Pandoc) and footnotes +modified from: https://pagedjs.org/plugins/endnotes-to-footnotes/ + +*/ + + + +const endNoteCalloutsQuery = ".footnote-ref"; + +// the hook +class endToFootNotes extends Paged.Handler { + constructor(chunker, polisher, caller) { + super(chunker, polisher, caller); + this.notestyle = 'endnotes'; + } + + onDeclaration(declaration, dItem, dList, rule) { + if (declaration.property == "--paged-note-style") { + if (declaration.value.value.includes("footnote")) { + this.notestyle = 'footnotes'; + } + } + } + + beforeParsed(content) { + if (this.notestyle !== 'footnotes') return; + + // Clean up previously injected clones (in case of re-render). + content.querySelectorAll('.pagedjs-footnote-clone').forEach((n) => n.remove()); + + // Optional: hide the original footnote list; we will clone notes inline. + const originalList = content.querySelector('.footnotes'); + if (originalList) { + originalList.classList.add('pagedjs-footnotes-hidden'); + } + + const callouts = content.querySelectorAll(endNoteCalloutsQuery); + callouts.forEach((callout) => { + if (!callout.hash) return; + const note = content.querySelector(callout.hash); + if (!note) { + console.warn(`No footnote found for ${callout.hash}`); + return; + } + // Clone the note content and float it as a footnote. + const clone = document.createElement('span'); + clone.classList.add('pagedjs-footnote-clone'); + clone.innerHTML = note.innerHTML; + callout.insertAdjacentElement('afterend', clone); + }); + } +} +Paged.registerHandlers(endToFootNotes); diff --git a/static/imposition.js b/static/imposition.js new file mode 100644 index 0000000..df092c9 --- /dev/null +++ b/static/imposition.js @@ -0,0 +1,428 @@ +// Imposition for booklet(s) +// +// This script re-arrange the pages of your document in order to make an imposed sheet layouts for printing. +// Two pages per sheet, double-sided +// modified from: https://gitlab.com/pagedjs-plugins/booklet-imposition/-/blob/master/imposition.js?ref_type=heads + +class Booklet extends Paged.Handler { + constructor(chunker, polisher, caller) { + super(chunker, polisher, caller); + this.pagedbooklet; + this.sourceSize; + this.pageStart; + this.pageEnd; + } + onAtPage(node, item, list) { } + onDeclaration(declaration, dItem, dList, rule) { + if (declaration.property == "--paged-layout") { + if (declaration.value.value.includes("booklet")) { + console.log('BOOKLET'); + // console.log(declaration.property, declaration, rule); + this.pagedbooklet = true; + let valuesBooklet = declaration.value.value.trim().split(/\s+/); + let index = valuesBooklet.indexOf("booklet"); + /* Set first page of the imposition */ + const rawStart = valuesBooklet[index + 1]; + if (rawStart) { + const parsedStart = parseInt(rawStart, 10); + this.pageStart = Number.isNaN(parsedStart) ? 1 : parsedStart; + } else { + this.pageStart = 1; + } + + /* Set last page of the imposition */ + const rawEnd = valuesBooklet[index + 2]; + if (rawEnd) { + const parsedEnd = parseInt(rawEnd, 10); + this.pageEnd = Number.isNaN(parsedEnd) ? undefined : parsedEnd; + } else { + this.pageEnd = undefined; + } + console.log(`START: ${this.pageStart} END: ${this.pageEnd}`); + } + } + } + afterRendered(pages) { + + + /* Verify this.pageEnd */ + if (!this.pageEnd) { + let allPagesBefore = document.querySelectorAll(".pagedjs_page").length; + this.pageEnd = allPagesBefore; + } + + /* Verify this.pageStart */ + if (this.pageStart == 0) { + this.pageStart = 1; + } else if (this.pageStart % 2 == 0) { + this.pageStart = this.pageStart - 1; + } + + + /* Launch when printing */ + //window.addEventListener("beforeprint", (evenement) => { + const reorder = (pages) => { + let containerPages = document.querySelector(".pagedjs_pages"); + + + /* Delete pages we don't want*/ + pages.forEach(page => { + let id = parseInt(page.id.replace('page-', '')); + if (id < this.pageStart || id > this.pageEnd) { + let pageSelect = document.querySelector('#' + page.id); + pageSelect.remove(); + } + }); + + /* Reset page counter */ + let reset = parseInt(this.pageStart) - 1; + containerPages.style.counterReset = "page " + reset; + + + let format = document.querySelector(".pagedjs_page"); + + /* Width of page without bleed, extract the first number of calc() function */ + let width = getCSSCustomProp("--pagedjs-width", format); + let numbers = width + .match(/[0-9]+/g) + .map(function (n) { + return + (n); + }); + width = parseInt(numbers[0]); + + /* Height of page with bleed, addition of all the numbers of calc() function*/ + let height = getCSSCustomProp("--pagedjs-height", format); + numbers = height + .match(/[0-9]+/g) + .map(function (n) { + return + (n); + }); + const reducer = (previousValue, currentValue) => previousValue + currentValue; + height = numbers.reduce(reducer); + + /* Bleed of the page */ + let bleed = getCSSCustomProp("--pagedjs-bleed-top", format); + let bleedNum = parseInt(bleed); + + /* Spread and half-spread*/ + let spread = width * 2 + bleedNum * 2; + + let spreadHalf = width + bleedNum; + + // Add CSS to have pages in spread + // + // - change size of the page when printing (actually, sheet size) + // - flex properties + // - delete bleeds inside spread */ + + var newSize = + `@media print{ + @page{ + size: ${spread}mm ${height}mm; + } + .pagedjs_pages { + width: auto; + } + } + @media screen{ + .pagedjs_pages{ + max-width: calc(var(--pagedjs-width) * 2); + } + } + .pagedjs_pages { + display: flex !important; + flex-wrap: wrap; + transform: none !important; + height: 100% !important; + min-height: 100%; + max-height: 100%; + overflow: visible; + } + + .pagedjs_page { + margin: 0; + padding: 0; + max-height: 100%; + min-height: 100%; + height: 100% !important; + + } + + .pagedjs_sheet { + margin: 0; + padding: 0; + max-height: 100%; + min-height: 100%; + height: 100% !important; + } + body{ + --pagedjs-bleed-right-left: 0mm; + } + .pagedjs_left_page{ + z-index: 20; + width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width))!important; + } + + .pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop { + border-color: transparent; + } + + .pagedjs_right_page, + .pagedjs_right_page .pagedjs_sheet{ + width: calc(var(--pagedjs-bleed-right-right) + var(--pagedjs-pagebox-width))!important; + } + + .pagedjs_right_page .pagedjs_sheet{ + grid-template-columns: [bleed-left] var(--pagedjs-bleed-right-left) [sheet-center] 1fr [bleed-right] var(--pagedjs-bleed-right-right); + } + .pagedjs_right_page .pagedjs_bleed-left{ + display: none; + } + + .pagedjs_right_page .pagedjs_bleed-top .pagedjs_marks-crop:nth-child(1), + .pagedjs_right_page .pagedjs_bleed-bottom .pagedjs_marks-crop:nth-child(1){ + width: 0!important; + } + .pagedjs_first_page { + margin-left: 0; + } + body{ + margin: 0 + } + .pagedjs_page:nth-of-type(even){ + break-after: always; + } + .pagedjs_page, + .pagedjs_sheet{ + width: ${spreadHalf - 0.1}mm!important; + } + + `; + + // Add style for the arrangement of the pages + + if (this.pagedbooklet == true) { + let style = document.createElement("style"); + style.textContent = newSize; + document + .head + .appendChild(style); + + var number_of_pages = document.getElementsByClassName("pagedjs_page").length; + var pages_array = []; + + // If the page count isn't a multiple of 4, we need to pad the array with blank + // pages so we have the correct number of pages for a booklet. + // + // ex. [1, 2, 3, 4, 5, 6, 7, 8, 9, blank, blank, blank] + + let modulo = number_of_pages % 4; + let additional_pages = 0; + if (modulo != 0) { + additional_pages = 4 - modulo; + } + + for (i = 0; i < additional_pages; i++) { + let added_page = document.createElement("div"); + added_page + .classList + .add("pagedjs_page", "added"); + added_page.id = `page-${this.pageEnd + i + 1}`; + added_page.innerHTML = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`; + document + .querySelector(".pagedjs_pages") + .appendChild(added_page); + } + + // Push each page in the array + + for (var i = number_of_pages + additional_pages; i >= 1; i--) { + pages_array.push(i); + } + + // get the last page here, and add a 'pagedjs_last_page' class + // it's mixing functionality a bit, but i don't want to iterate + // a second time over the pages + + const pagesList = Array.from(document.querySelectorAll('.pagedjs_page')); + pagesList.forEach(p => p.classList.remove('pagedjs_last_page')); + const last = pagesList.sort((a, b) => (parseInt(a.style.order || 0) - parseInt(b.style.order || 0))).pop(); + console.log("last", last); + if (last) last.classList.add('pagedjs_last_page'); + + + // Split the array in half + // + // ex. [1, 2, 3, 4, 5, 6], [7, 8, 9, blank, blank, blank] + + var split_start = pages_array.length / 2; + + var split_end = pages_array.length; + + var first_array = pages_array.slice(0, split_start); + var second_array = pages_array.slice(split_start, split_end); + + // Reverse the second half of the array. This is the beginning of the back half + // of the booklet (from the center fold, back to the outside last page) + // + // ex. [blank, blank, blank, 9, 8, 7] + + var second_array_reversed = second_array.reverse(); + + // Zip the two arrays together in groups of 2 These will end up being each '2-up + // side' of the final document So, the sub-array at index zero will be the first + // side of physical page one and index 1 will be the back side. However, they + // won't yet be in the proper order. + // + // ex. [[1, blank], [2, blank], [3, blank], [4, 9], [5, 8], [6, 7]] + + var page_groups = []; + for (var i = 0; i < first_array.length; i++) { + page_groups[i] = [ + first_array[i], second_array_reversed[i] + ]; + } + + // We need to reverse every other sub-array starting with the first side. This + // is the final step of aligning our booklet pages in the order with which the + // booklet gets printed and bound. + // + // ex. [[blank, 1], [2, blank], [blank, 3], [4, 9], [8, 5], [6, 7]] final_groups + // = page_groups.each_with_index { |group, index| group.reverse! if (index % + // 2).zero? } + var final_groups = []; + for (var i = 0; i < page_groups.length; i++) { + var group = page_groups[i]; + if (i % 2 != 0) { + final_groups[i] = page_groups[i].reverse(); + } else { + final_groups[i] = page_groups[i]; + } + } + console.log("Final Imposition Order: " + final_groups); + + var allPages = document.querySelectorAll(".pagedjs_page"); + + var final_flat = final_groups.flat(); + + final_flat.forEach((folio, i) => { + folio = folio + reset; + document + .querySelector(`#page-${folio}`) + .style + .order = i; + }); + } + + }; // before print + reorder(pages); + } +} +Paged + .registerHandlers(Booklet); + +/** + * Pass in an element and its CSS Custom Property that you want the value of. + * Optionally, you can determine what datatype you get back. + * + * @param {String} propKey + * @param {HTMLELement} element=document.documentElement + * @param {String} castAs='string' + * @returns {*} + */ +const getCSSCustomProp = ( + propKey, + element = document.documentElement, + castAs = "string" +) => { + let response = getComputedStyle(element).getPropertyValue(propKey); + + // Tidy up the string if there's something to work with + if (response.length) { + response = response + .replace(/\'|"/g, "") + .trim(); + } + + // Convert the response into a whatever type we wanted + switch (castAs) { + case "number": + case "int": + return parseInt(response, 10); + case "float": + return parseFloat(response, 10); + case "boolean": + case "bool": + return response === "true" || response === "1"; + } + + // Return the string response by default + return response; +}; diff --git a/static/main.css b/static/main.css index 9139c36..b344f5b 100644 --- a/static/main.css +++ b/static/main.css @@ -98,3 +98,19 @@ div.pagedjs_pages{ div#nav{ z-index: 11; } + + +.home_pad_iframe { + height: 75vh; + margin: 5rem; + width: calc(100vw - 13rem); + border: 1px solid black; + border-radius: 5px; +} + +@media only screen and (max-width: 600px) { + .home_pad_iframe { + margin: 1rem; + width: 90vw; + } +} diff --git a/static/pagedjs.css b/static/pagedjs.css index ff30f68..ed3cb86 100644 --- a/static/pagedjs.css +++ b/static/pagedjs.css @@ -178,3 +178,14 @@ .pagedjs_bleed-right .pagedjs_marks-crop:last-child{ box-shadow: 0px -1px 0px 0px var(--pagedjs-crop-shadow); } + +/* Footnotes: clone definitions inline and float them to the footer */ +/* .pagedjs-footnote-clone { + float: footnote; + display: block; + margin: 0; + padding: 0; +} +.pagedjs-footnotes-hidden { + display: none; +} */ diff --git a/templates/base.html b/templates/base.html index db3da7b..7cb041d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -34,7 +34,9 @@ window.addEventListener('load', function () { - + + + `; document.body.insertBefore(nav, document.body.firstChild); diff --git a/templates/default.css b/templates/default.css index 6679707..7c60d8e 100644 --- a/templates/default.css +++ b/templates/default.css @@ -2,34 +2,126 @@ @page{ size: A5; - margin: 10mm 20mm 25mm 20mm; + margin: 10mm 15mm 20mm 15mm; @bottom-center{ content: counter(page); - font-family: monospace; + font-family: abordage; + font-size: 150%; } } + +@page :first { + @bottom-center { + content: none; + } +} + +@font-face { + font-family: abordage; + src: url(https://chatty-pub-files.hackersanddesigners.nl/files/2/99/nMPuQi6bsXWzzHQcKzByuHnk/abordage-regular.woff); +} + +@font-face { + font-family: Director-Regular; + src: url(https://chatty-pub-files.hackersanddesigners.nl/files/2/d2/T7cPNlPHYfJD7uGerSbUl2zH/Director-Regular.otf); +} + + +@font-face { + font-family: Latitude; + src: url(https://chatty-pub-files.hackersanddesigners.nl/files/2/f8/52Q5ce2-rtPtoRRQpZrwp0X_/Latitude-Regular.otf); +} + body{ - font-size: 12px; + font-family: Latitude; + font-size: 11px; line-height: 1.5; color: #822b01; + --paged-layout: booklet; } /* ------------------------------------ cover */ -@page:first{ - background-color: #f3c6ff; - color: #822b01; +@page:first { + color: white; + background-size: cover; + background-repeat: no-repeat; + filter: hue-rotate(17deg); } -section#cover{ + +.cover{ break-after: always; + font-family: abordage; + margin-top: 50px; + padding: 15px; + background: #822b01; + background-clip: border-box; + } -section#cover h1#title{ - font-size: 300%; + +.cover h1#title { + font-family: abordage; + font-size: 500%; + line-height: 1.2em; +} + +.cover h2 { + font-family: abordage; + font-size: 200%; } /* ------------------------------------ main */ -section#main pre{ - color: magenta; + +h1 { + font-family: abordage; + font-size: 500%; + line-height: 1.2em; } + +section#main pre{ + color: black; +} + +.main h2 { + font-family: abordage; + font-size: 180%; + line-height: 1.2em; +} + +blockquote{ + margin-right: 0; + font-family: abordage; + font-size: 140%; + line-height: 1.2em; +} + +/* +Images are always grayscale in the main content and +are alone on a page +*/ +.main img { + display: block; + filter: grayscale(100%); + margin-left: auto; + margin-right: auto; + margin-top: 15px; + margin-bottom: 20px; + width: 100%; + page-break-after: always; + page-break-before: always; +} + +/* +*** alone on a line in markdown will be turned into a
+we use this a way to force a page break, and hide the hr itself. +*/ + +hr { + break-after: page; + border: none; + margin: 0; + height: 0; +} + diff --git a/templates/default.md b/templates/default.md index 19f8133..8c75135 100644 --- a/templates/default.md +++ b/templates/default.md @@ -4,57 +4,59 @@ language: en --- - +::: + -
-# *in octomode* { #title } +::: main +# Title +## Author +Everything that goes into the zine -
+::: -
-Octomode is a collective editing space for PDF making, using Etherpad, Paged.js and Flask. - -Inspired by the multi-centered, tentacular cognition capabilities of the octopus, we imagined a space in which the artificial boundaries of writing and design can be crossed; where writing, editing and designing can be done in one environment simultaneously, allowing the format to influence the matter and vice-versa. - -``` -Edit this text in the PAD view. -Edit the styling in the STYLESHEET view. -Preview the page in the HTML view. -Render it on pages in the PDF view. -``` - -
diff --git a/templates/pagedjs.html b/templates/pagedjs.html index 9d17770..e9d6bf1 100644 --- a/templates/pagedjs.html +++ b/templates/pagedjs.html @@ -4,9 +4,22 @@ + + {% if impose %} + + + {% endif %} + {% if cover %} + + {% endif %} - - + {{ title }} diff --git a/templates/pdf.html b/templates/pdf.html index aaf5754..c0fb711 100644 --- a/templates/pdf.html +++ b/templates/pdf.html @@ -1,5 +1,9 @@ {% extends "base.html" %} +{% block head %} +hallo +{% endblock %} + {% block content %} {% endblock %} @@ -20,9 +24,12 @@ window.addEventListener('load', function () { var head = document.getElementsByTagName('head')[0]; head.insertBefore(cssLink, head.firstChild); - // Insert the SAVE button const nav = document.getElementById('buttons'); - const save = ''; + // insert the IMPOSE button + // const impose = ''; + + // Insert the SAVE button + const save = ''; nav.innerHTML = nav.innerHTML + save; }) diff --git a/templates/preview.html b/templates/preview.html index c5fd8c6..270ea99 100644 --- a/templates/preview.html +++ b/templates/preview.html @@ -3,8 +3,7 @@ - - + {{ title }} diff --git a/templates/start.html b/templates/start.html index 890a6c1..e6d21b9 100644 --- a/templates/start.html +++ b/templates/start.html @@ -4,10 +4,12 @@ octomode +

in octomode

+