initial commit
This commit is contained in:
commit
21711bd5dd
253 changed files with 78415 additions and 0 deletions
1
public/csspageweaver/plugins/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Hi! Just need to ensure folder remain tracked, even empty.
|
||||
1
public/csspageweaver/plugins/baseline/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/baseline/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
8
public/csspageweaver/plugins/baseline/README.md
Normal file
8
public/csspageweaver/plugins/baseline/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: baseline
|
||||
tags: recommended, stable, boilerplate, gui
|
||||
description: A simple helper to see custom baseline grid.
|
||||
---
|
||||
|
||||
|
||||
|
||||
21
public/csspageweaver/plugins/baseline/baseline.css
Normal file
21
public/csspageweaver/plugins/baseline/baseline.css
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* BASELINE -------------------------------------------*/
|
||||
|
||||
:root {
|
||||
--pagedjs-baseline: 12px;
|
||||
--pagedjs-baseline-position: 0px;
|
||||
--pagedjs-baseline-color: cyan;
|
||||
}
|
||||
|
||||
@media screen{
|
||||
.pagedjs_pagebox {
|
||||
background: linear-gradient(transparent 0%, transparent calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) calc(var(--pagedjs-baseline) - 1px), var(--pagedjs-baseline-color) var(--pagedjs-baseline)), transparent;
|
||||
background-size: 100% var(--pagedjs-baseline);
|
||||
background-repeat: repeat-y;
|
||||
background-position-y: var(--pagedjs-baseline-position);
|
||||
|
||||
}
|
||||
|
||||
.no-baseline .pagedjs_pagebox{
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
100
public/csspageweaver/plugins/baseline/baseline.js
Normal file
100
public/csspageweaver/plugins/baseline/baseline.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* @name Baseline
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/baseline/ }
|
||||
*/
|
||||
|
||||
|
||||
export default function baseline() {
|
||||
let body = cssPageWeaver.ui.body
|
||||
let fileTitle = cssPageWeaver.docTitle;
|
||||
let parameters = cssPageWeaver.features.baseline.parameters || {}
|
||||
let isParametersSet = Object.keys(parameters).length > 0
|
||||
|
||||
/* BASELINE ----------------------------------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
/* Set baseline onload */
|
||||
let baseline = {}
|
||||
|
||||
// set default value
|
||||
baseline.default = {
|
||||
size: 32 ,
|
||||
position: 0
|
||||
}
|
||||
|
||||
baseline.toggle = {}
|
||||
baseline.toggle.value = localStorage.getItem('baselineToggle_' + fileTitle)
|
||||
baseline.toggle.input = cssPageWeaver.ui.baseline.toggleInput
|
||||
|
||||
baseline.button = cssPageWeaver.ui.baseline.toggleLabel
|
||||
|
||||
baseline.size = {}
|
||||
baseline.size.value = parameters.size || baseline.default.size
|
||||
baseline.size.input = document.querySelector('#size-baseline')
|
||||
|
||||
baseline.position = {}
|
||||
baseline.position.value = parameters.position || baseline.default.position
|
||||
baseline.position.input = document.querySelector('#position-baseline')
|
||||
|
||||
|
||||
/* */
|
||||
/* Retrieve previous sessions */
|
||||
baseline.size.value = localStorage.getItem('baselineSize_' + fileTitle) || baseline.size.value
|
||||
baseline.position.value = localStorage.getItem('baselinePosition_' + fileTitle) || baseline.position.value
|
||||
|
||||
/* */
|
||||
/* DOM edit */
|
||||
|
||||
/* Toggle */
|
||||
if(baseline.toggle.value == "no-baseline"){
|
||||
body.classList.add('no-baseline');
|
||||
baseline.toggle.input.checked = false;
|
||||
}else if(baseline.toggle.value == "baseline"){
|
||||
body.classList.remove('no-baseline');
|
||||
baseline.toggle.input.checked = true;
|
||||
}else{
|
||||
body.classList.add('no-baseline');
|
||||
localStorage.setItem('baselineToggle_' + fileTitle, 'no-baseline'); //baselineButton.querySelector(".button-hide").classList.remove("button-not-selected");
|
||||
baseline.toggle.input.checked = false;
|
||||
}
|
||||
|
||||
/* Set baseline size and position on load */
|
||||
baseline.size.input.value = baseline.size.value
|
||||
document.documentElement.style.setProperty('--pagedjs-baseline', baseline.size.value + 'px');
|
||||
baseline.position.input.value = baseline.position.value
|
||||
document.documentElement.style.setProperty('--pagedjs-baseline-position', baseline.position.value + 'px');
|
||||
|
||||
|
||||
/* */
|
||||
/* Event listenner */
|
||||
|
||||
/* Toggle event */
|
||||
baseline.toggle.input.addEventListener("input", (e) => {
|
||||
if(e.target.checked){
|
||||
/* see baseline */
|
||||
body.classList.remove('no-baseline');
|
||||
localStorage.setItem('baselineToggle_' + fileTitle, 'baseline');
|
||||
}else{
|
||||
/* hide baseline */
|
||||
body.classList.add('no-baseline');
|
||||
localStorage.setItem('baselineToggle_' + fileTitle, 'no-baseline');
|
||||
}
|
||||
});
|
||||
|
||||
/* Change baseline size on input */
|
||||
document.querySelector("#size-baseline").addEventListener("input", (e) => {
|
||||
baseline.size.value = e.target.value
|
||||
document.documentElement.style.setProperty('--pagedjs-baseline', baseline.size.value + 'px');
|
||||
localStorage.setItem('baselineSize_' + fileTitle, baseline.size.value);
|
||||
});
|
||||
|
||||
|
||||
/* Change baseline position on input */
|
||||
document.querySelector("#position-baseline").addEventListener("input", (e) => {
|
||||
baseline.position.value = e.target.value
|
||||
document.documentElement.style.setProperty('--pagedjs-baseline-position', baseline.position.value + 'px');
|
||||
localStorage.setItem('baselinePosition_' + fileTitle, baseline.position.value);
|
||||
});
|
||||
|
||||
}
|
||||
13
public/csspageweaver/plugins/baseline/config.json
Normal file
13
public/csspageweaver/plugins/baseline/config.json
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "Baseline",
|
||||
"description": "",
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"title": "Baseline Grid",
|
||||
"description": "This Toogle a baseline on pages",
|
||||
"template": "template.html",
|
||||
"toggle": true
|
||||
},
|
||||
"script": "baseline.js",
|
||||
"stylesheet": "baseline.css"
|
||||
}
|
||||
8
public/csspageweaver/plugins/baseline/template.html
Normal file
8
public/csspageweaver/plugins/baseline/template.html
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<div class="panel-group-values">
|
||||
<label for="size-baseline">Size (px)</label>
|
||||
<input type="number" id="size-baseline" name="size-baseline" min="1" max="100" value="12">
|
||||
</div>
|
||||
<div class="panel-group-values">
|
||||
<label for="position-baseline" id="label-position">Position (px)</label>
|
||||
<input type="number" id="position-baseline" name="position-baseline" value="0">
|
||||
</div>
|
||||
1
public/csspageweaver/plugins/floatPage/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/floatPage/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
0
public/csspageweaver/plugins/floatPage/.hugo_build.lock
Normal file
0
public/csspageweaver/plugins/floatPage/.hugo_build.lock
Normal file
74
public/csspageweaver/plugins/floatPage/README.md
Normal file
74
public/csspageweaver/plugins/floatPage/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
name: floatPage
|
||||
tags: early-stage, feedback-wanted
|
||||
description: Handles floats that are positioned at the top or bottom of pages.
|
||||
---
|
||||
|
||||
|
||||
# Float page elements (paged.js)
|
||||
|
||||
This plugin handles floats that are positioned at the top or bottom of pages.
|
||||
This feature has traditionally been used in print publications in which figures and photos are moved to the top or bottom of columns or pages, along with their captions.
|
||||
|
||||
You need to use [csstree.js](https://github.com/csstree/csstree) in order to transform custom properties.
|
||||
If you use CSS Page Weaver is inclued by default
|
||||
|
||||
|
||||
## How to install
|
||||
|
||||
**With CSS Page Weaver**
|
||||
|
||||
Register the `floatPage` plugin in your `manifest.json`:
|
||||
|
||||
```json
|
||||
[
|
||||
"floatPage",
|
||||
// other plugins
|
||||
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
|
||||
**Without CSS Page Weaver**
|
||||
|
||||
Include both csstree and the fullPage script in your HTML `<head>`:
|
||||
|
||||
```html
|
||||
<script src="js/csstree.min.js"></script>
|
||||
<script type="module" src="path/to/fullPage/floatPage.js"></script>
|
||||
```
|
||||
|
||||
Don’t forget to update the path to the paged.esm.js module in the import statement before using the script.
|
||||
|
||||
```js
|
||||
import { Handler } from '/path/to/paged.esm.js'
|
||||
```
|
||||
|
||||
## How to use it
|
||||
|
||||
In the CSS, add the following custom property to the elements (using IDs or classes) that you want to float to the top or bottom of pages:
|
||||
|
||||
```css
|
||||
elem{
|
||||
--pagedjs-float-page: top;
|
||||
}
|
||||
```
|
||||
|
||||
- `--pagedjs-float-page: top` → The element will be placed at the top of the current page.
|
||||
- `--pagedjs-float-page: bottom` → The element will be placed at the bottom of the current page.
|
||||
- `--pagedjs-float-page: next-page` → The element will be placed at the top of the next page.
|
||||
|
||||
Notes:
|
||||
- this script works on any elements, even if the element contains several child elements;
|
||||
- the element will be reinserted into its original parent if that parent still exists on the page.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [pagedjs.org](https://www.pagedjs.org/)
|
||||
- [csstree.js](https://github.com/csstree/csstree)
|
||||
|
||||
MIT licence, Julie Blanc, 2025
|
||||
|
||||
|
||||
8
public/csspageweaver/plugins/floatPage/config.json
Normal file
8
public/csspageweaver/plugins/floatPage/config.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Float PAge",
|
||||
"description": "",
|
||||
"author": ["Julie Blanc"],
|
||||
"license": "MIT License",
|
||||
"version": "1.0",
|
||||
"hook": "floatPage.js"
|
||||
}
|
||||
153
public/csspageweaver/plugins/floatPage/floatPage.js
Normal file
153
public/csspageweaver/plugins/floatPage/floatPage.js
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* @name Float Page v1.0
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/floatPage }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export class floatPage extends Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.selectorBottom = new Set();
|
||||
this.selectorTop = new Set();
|
||||
this.selectorNextPage = new Set();
|
||||
this.nextPageElem = new Set();
|
||||
this.nextPageElemTemp = new Set();
|
||||
}
|
||||
|
||||
|
||||
onDeclaration(declaration, dItem, dList, rule) {
|
||||
// Read customs properties
|
||||
if (declaration.property == "--pagedjs-float-page") {
|
||||
// get selector of the declaration (NOTE: need csstree.js)
|
||||
let selector = csstree.generate(rule.ruleNode.prelude);
|
||||
// Push selector in correct set
|
||||
if(declaration.value.value.includes("bottom")) {
|
||||
this.selectorBottom.add(selector);
|
||||
}else if(declaration.value.value.includes("top")) {
|
||||
this.selectorTop.add(selector);
|
||||
}else if(declaration.value.value.includes("next-page")) {
|
||||
this.selectorNextPage.add(selector);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
afterParsed(parsed){
|
||||
// bottom
|
||||
for (let item of this.selectorBottom) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("float-page_bottom");
|
||||
}
|
||||
}
|
||||
|
||||
// top
|
||||
for (let item of this.selectorTop) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("float-page_top");
|
||||
}
|
||||
}
|
||||
|
||||
// next-page
|
||||
for (let item of this.selectorNextPage) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("float-page_next-page");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
afterPageLayout(pageElement, page, breakToken){
|
||||
|
||||
// TOP (positionning)
|
||||
let floatTopPage = pageElement.querySelector(".float-page_top");
|
||||
if(floatTopPage){
|
||||
let selector = buildCssSelector(floatTopPage.parentNode);
|
||||
parent = pageElement.querySelector(selector)
|
||||
parent.insertBefore(floatTopPage, parent.firstChild);
|
||||
}
|
||||
|
||||
// BOTTOM (positionning)
|
||||
let floatBottomPage = pageElement.querySelector(".float-page_bottom");
|
||||
if(floatBottomPage){
|
||||
let selector = buildCssSelector(floatBottomPage.parentNode);
|
||||
parent = pageElement.querySelector(selector);
|
||||
parent.insertBefore(floatBottomPage, parent.firstChild);
|
||||
floatBottomPage.style.position = "absolute";
|
||||
floatBottomPage.style.bottom = "0px";
|
||||
}
|
||||
|
||||
// NEXT PAGE (positionning into parent section)
|
||||
for (let elem of this.nextPageElemTemp) {
|
||||
let cleanedSelector = elem.parentSelector.replace(/^#document-fragment\s*>\s*/, '');
|
||||
let parent = pageElement.querySelector(cleanedSelector);
|
||||
|
||||
let node = elem.elem;
|
||||
if(parent){
|
||||
parent.insertBefore(node, parent.firstChild);
|
||||
}
|
||||
}
|
||||
this.nextPageElemTemp.clear();
|
||||
|
||||
|
||||
}
|
||||
|
||||
// NEXT PAGE (pass to next page) -------------------
|
||||
|
||||
renderNode(clone, node) {
|
||||
if (node.nodeType == 1 && node.classList.contains("float-page_next-page")) {
|
||||
clone.remove();
|
||||
this.nextPageElem.add({ elem: node, parentSelector: buildCssSelector(node.parentNode) });
|
||||
}
|
||||
}
|
||||
|
||||
onPageLayout(page, Token, layout) {
|
||||
for (let elem of this.nextPageElem) {
|
||||
page.insertBefore(elem.elem, page.firstChild);
|
||||
this.nextPageElemTemp.add(elem);
|
||||
}
|
||||
this.nextPageElem.clear();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// FONCTIONS --------------------------------------------------------------------------
|
||||
|
||||
// Function to build the CSS selector from the element and its parents
|
||||
function buildCssSelector(element) {
|
||||
let selector = [];
|
||||
let current = element;
|
||||
|
||||
while (current) {
|
||||
if (current.classList && current.classList.contains('pagedjs_page_content')) {
|
||||
break; // Stop if the parent with class 'pagedjs_page_content' is found
|
||||
}
|
||||
|
||||
let currentSelector = current.nodeName.toLowerCase();
|
||||
|
||||
if (current.id) {
|
||||
currentSelector += `[data-id="${current.id}"]`;
|
||||
}
|
||||
|
||||
if (current.className) {
|
||||
currentSelector += `.${current.className.split(' ').join('.')}`;
|
||||
}
|
||||
|
||||
selector.unshift(currentSelector);
|
||||
current = current.parentNode;
|
||||
}
|
||||
|
||||
selector = selector.join(' > ');
|
||||
// selector = selector.replace(/#document-fragment( > )?/g, ''); // Clean the CSS selector by removing '#document-fragment'
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Categories on </title>
|
||||
<link>//localhost:1313/categories/</link>
|
||||
<description>Recent content in Categories on </description>
|
||||
<generator>Hugo</generator>
|
||||
<language>en</language>
|
||||
<atom:link href="//localhost:1313/categories/index.xml" rel="self" type="application/rss+xml" />
|
||||
</channel>
|
||||
</rss>
|
||||
11
public/csspageweaver/plugins/floatPage/public/index.xml
Normal file
11
public/csspageweaver/plugins/floatPage/public/index.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title></title>
|
||||
<link>//localhost:1313/</link>
|
||||
<description>Recent content on </description>
|
||||
<generator>Hugo</generator>
|
||||
<language>en</language>
|
||||
<atom:link href="//localhost:1313/index.xml" rel="self" type="application/rss+xml" />
|
||||
</channel>
|
||||
</rss>
|
||||
11
public/csspageweaver/plugins/floatPage/public/sitemap.xml
Normal file
11
public/csspageweaver/plugins/floatPage/public/sitemap.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||
<url>
|
||||
<loc>//localhost:1313/</loc>
|
||||
</url><url>
|
||||
<loc>//localhost:1313/categories/</loc>
|
||||
</url><url>
|
||||
<loc>//localhost:1313/tags/</loc>
|
||||
</url>
|
||||
</urlset>
|
||||
11
public/csspageweaver/plugins/floatPage/public/tags/index.xml
Normal file
11
public/csspageweaver/plugins/floatPage/public/tags/index.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Tags on </title>
|
||||
<link>//localhost:1313/tags/</link>
|
||||
<description>Recent content in Tags on </description>
|
||||
<generator>Hugo</generator>
|
||||
<language>en</language>
|
||||
<atom:link href="//localhost:1313/tags/index.xml" rel="self" type="application/rss+xml" />
|
||||
</channel>
|
||||
</rss>
|
||||
1
public/csspageweaver/plugins/footnotesFix/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/footnotesFix/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
95
public/csspageweaver/plugins/footnotesFix/README.md
Normal file
95
public/csspageweaver/plugins/footnotesFix/README.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# Plugin to fix footnotes reset issue
|
||||
|
||||
This plugin fix the issue of footnote reset.
|
||||
|
||||
You can use the current method to declare footnotes:
|
||||
|
||||
```CSS
|
||||
@page {
|
||||
@footnote {
|
||||
float: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.pagedjs_footnote {
|
||||
float: footnote;
|
||||
}
|
||||
```
|
||||
|
||||
This style is also added to the default stylesheet `footnotes.css` of this plugin. You can delete it if you have already declared footnotes in your own stylesheet (don't forget to remove it from the `config.json` as well).
|
||||
|
||||
|
||||
## How to use the plugin
|
||||
|
||||
Add this folder to `csspageweaver/plugins/`.
|
||||
|
||||
Call the plugin in `csspageweaver/manifest.json`:
|
||||
|
||||
```json
|
||||
"plugins": [
|
||||
"footnotesFix",
|
||||
// other plugins ...
|
||||
],
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
In `manifest.json`, you can modify/add some parameters:
|
||||
|
||||
```json
|
||||
"plugins":{
|
||||
"footnotesFix"
|
||||
},
|
||||
"pluginsParameters":{
|
||||
"footnotesFix": {
|
||||
"selector": ".footnote",
|
||||
"reset": ".chapter"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
All the parameters are optional.
|
||||
|
||||
- `selector` → CSS selector for the note element (must be inline in the HTML), by default is `.footnote`
|
||||
- `reset` → CSS selector where you want reset note counter. If you want to reset on the page: `page`
|
||||
|
||||
|
||||
## Notes in HTML
|
||||
|
||||
In your HTML, the note must be a `<span>` inserted in the text, like this:
|
||||
|
||||
```HTML
|
||||
Donec tincidunt, odio vel vestibulum sollicitudin, nibh dolor tempor sapien, ac laoreet
|
||||
sem felis ut purus. <span class=".footnote">Vestibulum neque ex, ullamcorper sit
|
||||
amet diam sed, pharetra laoreet sem.</span> Morbi cursus bibendum consectetur. Nullam vel
|
||||
lacus congue nibh pulvinar maximus sit amet eu risus. Curabitur semper odio mauris, nec
|
||||
imperdiet velit pharetra non. Aenean accumsan nulla ac ex iaculis interdum.
|
||||
```
|
||||
|
||||
You can use the [inline_notes` plugin](https://gitlab.com/csspageweaver/plugins/inline_notes) to create these span elements from listed notes, which are more common in conversion tools like Pandoc.
|
||||
|
||||
The inline_notes plugin should be called before the footnotes plugin in the `manifest.json`:
|
||||
|
||||
|
||||
```json
|
||||
"plugins": [
|
||||
"inline_notes",
|
||||
"footnotes_fix",
|
||||
// other plugins ...
|
||||
],
|
||||
```
|
||||
|
||||
## Styling call & footer
|
||||
|
||||
It's possible to change the styles of call notes and marker notes directly in your stylesheet like in the following code:
|
||||
|
||||
```CSS
|
||||
::footnote-call{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
::footnote-marker{
|
||||
font-weight: bold;
|
||||
}
|
||||
```
|
||||
|
||||
9
public/csspageweaver/plugins/footnotesFix/config.json
Normal file
9
public/csspageweaver/plugins/footnotesFix/config.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "Footnotes",
|
||||
"description": "Fix footnote reset",
|
||||
"author": ["Julie Blanc"],
|
||||
"licence": "MIT",
|
||||
"version": "1.0",
|
||||
"hook": "footnotes.js",
|
||||
"stylesheet": "footnotes.css"
|
||||
}
|
||||
9
public/csspageweaver/plugins/footnotesFix/footnotes.css
Normal file
9
public/csspageweaver/plugins/footnotesFix/footnotes.css
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
@page {
|
||||
@footnote {
|
||||
float: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.footnote {
|
||||
float: footnote;
|
||||
}
|
||||
85
public/csspageweaver/plugins/footnotesFix/footnotes.js
Normal file
85
public/csspageweaver/plugins/footnotesFix/footnotes.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @name Footnotes
|
||||
* @file Reset the way footnote are counted
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/footnotesFix/ }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class footnotes extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.parameters = cssPageWeaver.features.footnotesFix.parameters;
|
||||
this.reset = this.parameters?.reset ;
|
||||
this.counter = 0;
|
||||
this.selector = this.parameters?.selector || ".footnote";
|
||||
}
|
||||
|
||||
beforeParsed(content) {
|
||||
|
||||
|
||||
let notes = content.querySelectorAll(this.selector);
|
||||
notes.forEach(function (note, index) {
|
||||
note.classList.add("pagedjs_footnote");
|
||||
});
|
||||
|
||||
|
||||
|
||||
if(this.reset){
|
||||
let elems = content.querySelectorAll(this.reset);
|
||||
elems.forEach(function (elem, index) {
|
||||
var span = document.createElement('span');
|
||||
span.classList.add("reset-fix-footnote");
|
||||
span.style.position = "absolute";
|
||||
elem.insertBefore(span, elem.firstChild);
|
||||
});
|
||||
}else{
|
||||
console.log("[footnotesFix] no reset")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
afterPageLayout(pageElement, page, breakToken){
|
||||
|
||||
if(this.reset){
|
||||
|
||||
// reset on pages
|
||||
if(this.reset === "page"){
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
// reset on specific element
|
||||
let newchapter = pageElement.querySelector('.reset-fix-footnote');
|
||||
if(newchapter){
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
let footnotes = pageElement.querySelectorAll(".pagedjs_footnote_content [data-note]");
|
||||
|
||||
let callnotes = pageElement.querySelectorAll('a.pagedjs_footnote');
|
||||
callnotes.forEach((call, index) => {
|
||||
|
||||
this.counter = this.counter + 1; // increment
|
||||
let num = this.counter - 1;
|
||||
|
||||
// update data-counter for call
|
||||
call.setAttribute('data-counter-footnote-increment', num);
|
||||
call.style.counterReset = "footnote " + num;
|
||||
|
||||
// update data-counter for marker
|
||||
let footnote = footnotes[index];
|
||||
let dataCounter = num + 1;
|
||||
footnote.setAttribute('data-counter-note', dataCounter);
|
||||
footnote.style.counterReset = "footnote-marker " + num;
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1
public/csspageweaver/plugins/frenchTypoRegex/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/frenchTypoRegex/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
10
public/csspageweaver/plugins/frenchTypoRegex/config.json
Normal file
10
public/csspageweaver/plugins/frenchTypoRegex/config.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "French Typography Regex",
|
||||
"description": "A collection of regex rules for French text normalization. This file provides a set of regular expressions to clean and standardize French typography. It automatically fixes spacing, quotation marks, apostrophes, ellipses, and common orthotypographic conventions (non-breaking spaces before punctuation, French guillemets, etc.).",
|
||||
"author": ["Julie Blanc"],
|
||||
"license": "MIT License",
|
||||
"version": "1.0",
|
||||
"created": "2025-08-26",
|
||||
"updated": "2025-08-26",
|
||||
"hook": "frenchTypoRegex.js"
|
||||
}
|
||||
169
public/csspageweaver/plugins/frenchTypoRegex/frenchTypoRegex.js
Normal file
169
public/csspageweaver/plugins/frenchTypoRegex/frenchTypoRegex.js
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/**
|
||||
* @name French Typography Regex
|
||||
* @file A collection of regex rules for French text normalization
|
||||
* @description
|
||||
* This file provides a set of regular expressions to clean and standardize
|
||||
* French typography. It automatically fixes spacing, quotation marks,
|
||||
* apostrophes, ellipses, and common orthotypographic conventions
|
||||
* (non-breaking spaces before punctuation, French guillemets, etc.).
|
||||
*
|
||||
* @author Julie Blanc (contact@julie-blanc.fr)
|
||||
* @created 2025-08-26
|
||||
* @updated 2025-08-26
|
||||
* @see {@link https://gitlab.com/csspageweaver/frenchTypoRegex/ }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class frenchTypoRegex extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
}
|
||||
|
||||
beforeParsed(content) {
|
||||
|
||||
// SPECIFIC, delete span with apostroph
|
||||
content.querySelectorAll('span[dir="rtl"]').forEach(span => {
|
||||
if (span.textContent.trim() === '’' || span.textContent.trim() === '"’"' ) {
|
||||
span.replaceWith(document.createTextNode('’'));
|
||||
}
|
||||
});
|
||||
|
||||
applyRegex(content);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
const arrayRegexFrenchTypo = [
|
||||
{
|
||||
// Remplacement des doubles espaces (ou plus) par un seul espace normal
|
||||
reg: /\s{2,}/g,
|
||||
repl: " ",
|
||||
},
|
||||
{
|
||||
// XIème = XIe
|
||||
reg: /(X|I|V)ème/g,
|
||||
repl: "$1e",
|
||||
},
|
||||
{
|
||||
// guillemets français ouvrants
|
||||
reg: /"([^\s])/g,
|
||||
repl: "«"
|
||||
},
|
||||
{
|
||||
// guillemets français fermants
|
||||
reg: /([^\s])"/g,
|
||||
repl: "»"
|
||||
},
|
||||
{
|
||||
// espace insécable avant ; : ? ! »
|
||||
reg: /\s+([;:?!»])/g,
|
||||
repl: "\u00A0$1",
|
||||
},
|
||||
{
|
||||
// espace insécable après «
|
||||
reg: /(«)\s+/g,
|
||||
repl: "$1\u00A0",
|
||||
},
|
||||
{
|
||||
// real apostrophe
|
||||
reg: /(\w)'(\w)/g,
|
||||
repl: '$1’$2'
|
||||
},
|
||||
{
|
||||
// real suspension points
|
||||
reg: /\.{3,}/g,
|
||||
repl: '\u2026'
|
||||
},
|
||||
{
|
||||
// espace insécable après certains mots de deux lettres
|
||||
reg: /\b(le|la|ce|on|il|de|du|un|au|en)\s+/gi,
|
||||
repl: '$1\u00A0'
|
||||
},
|
||||
{
|
||||
// no break space after one letter words
|
||||
reg: /\s+([a-zà])\s+/gi,
|
||||
repl: ' $1\u00A0'
|
||||
},
|
||||
{
|
||||
// no break space after first word (2-3 letter) of the sentence
|
||||
reg: /\.\s([A-ZÀ-Ö])([A-Za-zÀ-ÖØ-öø-ÿœŒ]{1,3})\s+/g,
|
||||
repl: '. $1$2\u00A0'
|
||||
},
|
||||
{
|
||||
// delete all spaces before punctuation !?;:»›”%€)].,
|
||||
reg: /\s+([!?;:»›”%€$)\]\.\,])/g,
|
||||
repl: '$1'
|
||||
},
|
||||
{
|
||||
// add narrow no break space before !?;:»›%€ (sauf http://)
|
||||
reg: /(?<!https?)[:!?;»›%€$]/g,
|
||||
repl: '\u202F$&'
|
||||
},
|
||||
{
|
||||
// delete all spaces after «‹“[(
|
||||
reg: /([«‹“\[(])\s+/g,
|
||||
repl: '$1'
|
||||
},
|
||||
{
|
||||
// add narrow no break space after «‹
|
||||
reg: /([«‹])/g,
|
||||
repl: '$1\u202F'
|
||||
},
|
||||
{
|
||||
// no break space before 'siècle'
|
||||
reg: /(X|I|V)(er|e)\s+siècle/g,
|
||||
repl: '$1$2\u00A0siècle'
|
||||
},
|
||||
{
|
||||
// Espaces insécables pour les nombres
|
||||
reg: /(\d)(?=(\d{3})+(?!\d))/g,
|
||||
repl: '$1\u202F'
|
||||
},
|
||||
{
|
||||
// no break space after figures table page chapitre ect. + number
|
||||
reg: /(figures?|tables?|planches?|chapitres?|pages?|parties?|sections?|volumes?|vol\.)\s+(\d|I|X|V)/g,
|
||||
repl: '$1\u00A0$2'
|
||||
},
|
||||
{
|
||||
// Espace insécable après "p." ou "pp." en bibliographie
|
||||
reg: /\b(pp?)\.\s*(\d+)/gi,
|
||||
repl: '$1.\u00A0$2'
|
||||
},
|
||||
{
|
||||
// Coupures possibles dans les URLs (ajout d’un zero-width space après / - _ . sauf les // initiaux)
|
||||
reg: /(https?:\/\/[^\s]+)/g,
|
||||
repl: (match) => match.replace(/(?<!:)\/(?!\/)|[-_.]/g, "$&\u200B")
|
||||
},
|
||||
];
|
||||
|
||||
function applyRegex(content) {
|
||||
|
||||
// TREE WALKER
|
||||
const walker = document.createTreeWalker(
|
||||
content,
|
||||
NodeFilter.SHOW_TEXT,
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
let node;
|
||||
while ((node = walker.nextNode())) {
|
||||
// Exclure <code> ou <pre>
|
||||
const codeParent = node.parentElement?.closest("code, pre");
|
||||
if (codeParent) continue;
|
||||
|
||||
// APPLY REGEX FROM ARRAY
|
||||
for (let i = 0; i < arrayRegexFrenchTypo.length; i++) {
|
||||
node.textContent = node.textContent.replace(arrayRegexFrenchTypo[i].reg, arrayRegexFrenchTypo[i].repl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
public/csspageweaver/plugins/fullPage/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/fullPage/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
126
public/csspageweaver/plugins/fullPage/README.md
Executable file
126
public/csspageweaver/plugins/fullPage/README.md
Executable file
|
|
@ -0,0 +1,126 @@
|
|||
---
|
||||
name: fullPage
|
||||
tags: recommended, stable
|
||||
description: Create full page elements and full spread elements in the flow of your book.
|
||||
|
||||
---
|
||||
|
||||
|
||||
# Full page elements (paged.js)
|
||||
|
||||
This script help you to create full page elements and full spread elements in the flow of your book.
|
||||
|
||||
You need to use [csstree.js](https://github.com/csstree/csstree) in order to transform custom properties.
|
||||
If you use CSS Page Maker is inclued by default
|
||||
|
||||
|
||||
## How to install
|
||||
|
||||
**With CSS Page Marker**
|
||||
|
||||
Make sure the csstree library is included in the `<head>` of your HTML:
|
||||
|
||||
|
||||
```html
|
||||
<script src="/csspageweaver/lib/csstree.min.js"></script>
|
||||
```
|
||||
|
||||
|
||||
Register the `fullPage` plugin in your `manifest.json`:
|
||||
|
||||
```json
|
||||
[
|
||||
"fullPage",
|
||||
// other plugins
|
||||
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
|
||||
**Without CSS Page Maker**
|
||||
|
||||
Include both csstree and the fullPage script in your HTML `<head>`:
|
||||
|
||||
```html
|
||||
<script src="js/csstree.min.js"></script>
|
||||
<script src="path/to/fullPage/fullPage.js"></script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## How to use it
|
||||
|
||||
In the CSS, on the element(s) you want in full page add the following custom property(works with id and classes):
|
||||
|
||||
```css
|
||||
elem{
|
||||
--pagedjs-full-page: page
|
||||
}
|
||||
```
|
||||
|
||||
You have multiple keywords for the custom property:
|
||||
- `--pagedjs-full-page: page` → The element will be remove from flow and put in the next page.
|
||||
- `--pagedjs-full-page: left` → The element will be remove from flow and put in the next left page.
|
||||
- `--pagedjs-full-page: right` → The element will be remove from flow and put in the next right page.
|
||||
- `--pagedjs-full-page: spread` → The element will be remove from flow and put in the next spread.
|
||||
- `--pagedjs-full-page: <number>` → The element will be remove from flow and put in the page you specify (with `--pagedjs-full-page: 4`, the element is put on page number 4).
|
||||
|
||||
Note that this script works on any elements, even if the element contains several child elements.
|
||||
|
||||
|
||||
### Images in full page
|
||||
|
||||
If you want an image in full page, we advise you to use the usual `objet-fit` properties.
|
||||
|
||||
```css
|
||||
#figure{
|
||||
--pagedjs-full-page: page;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
img {
|
||||
object-fit: cover;
|
||||
object-position: 0px 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
```
|
||||
|
||||
- To change the size of you image, use `width` and `height`.
|
||||
- To change the position of your image, use `object-position`.
|
||||
- In the case of the `spread` option, all the spread will be considered, i.e. `width: 100%` cover all the spread.
|
||||
|
||||
|
||||
### Spread and central fold
|
||||
|
||||
Sometimes, when a book is binding, the elements that cover the spread need to be offset from the central fold. A custom value can be added to the page to take it into account.
|
||||
|
||||
```css
|
||||
@page {
|
||||
--pagedjs-fold: 10mm;
|
||||
}
|
||||
```
|
||||
|
||||
### Bleeds of full page and full spread elements
|
||||
|
||||
In order to avoid that your elements moves when you change the bleeds and the crop marks of your document, the bleeds of full page elements was set up to `6mm`. This is due to the way Paged.js modifies the DOM (full page elements are contained in the page sheet and depend on the dimensions of this page sheet).
|
||||
If you want to change the dimensions of these specific bleeds, you just have to change the value of the `bleedFull` variable in the first line of the `full-page.js` file
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
You can find examples of use in `css/full-page.css`.
|
||||
|
||||

|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [pagedjs.org](https://www.pagedjs.org/)
|
||||
- [csstree.js](https://github.com/csstree/csstree)
|
||||
|
||||
MIT licence, Julie Blanc, 2021
|
||||
|
||||
|
||||
9
public/csspageweaver/plugins/fullPage/config.json
Normal file
9
public/csspageweaver/plugins/fullPage/config.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "Full page",
|
||||
"description": "Create full page elements and full spread elements in the flow of your book",
|
||||
"licence": "MIT",
|
||||
"author": ["Julie Blanc"],
|
||||
"version": "2.0",
|
||||
"hook": "fullPage.js",
|
||||
"stylesheet": "fullPage.css"
|
||||
}
|
||||
49
public/csspageweaver/plugins/fullPage/fullPage.css
Normal file
49
public/csspageweaver/plugins/fullPage/fullPage.css
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
.pagedjs_page_fullLeft .pagedjs_full-spread_container{
|
||||
margin: 0;
|
||||
width: calc(var(--pagedjs-pagebox-width) + var(--bleed-images));
|
||||
height: calc(var(--pagedjs-pagebox-height) + var(--bleed-images)*2)!important;
|
||||
position: absolute;
|
||||
top: calc((var(--pagedjs-margin-top) + var(--bleed-images))*-1);
|
||||
left: calc((var(--pagedjs-margin-left) + var(--bleed-images))*-1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.pagedjs_page_fullRight .pagedjs_full-spread_container{
|
||||
margin: 0;
|
||||
width: calc(var(--pagedjs-pagebox-width) + var(--bleed-images));
|
||||
height: calc(var(--pagedjs-pagebox-height) + var(--bleed-images)*2)!important;
|
||||
position: absolute;
|
||||
top: calc((var(--pagedjs-margin-top) + var(--bleed-images))*-1);
|
||||
left: calc(var(--pagedjs-margin-left)*-1);
|
||||
overflow: hidden;
|
||||
}
|
||||
.pagedjs_full-spread_content{
|
||||
margin: 0;
|
||||
width: calc(var(--pagedjs-pagebox-width)*2 + var(--bleed-images)*2);
|
||||
height: calc(var(--pagedjs-pagebox-height) + var(--bleed-images)*2)!important;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.pagedjs_page_fullLeft .pagedjs_full-spread_content{
|
||||
left: calc(var(--pagedjs-fold)*-1);
|
||||
}
|
||||
.pagedjs_page_fullRight .pagedjs_full-spread_content{
|
||||
left: calc((var(--pagedjs-pagebox-width) + var(--bleed-images))*-1 + var(--pagedjs-fold))
|
||||
}
|
||||
|
||||
.pagedjs_full-page_content {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: calc((var(--pagedjs-margin-top) + var(--bleed-images))*-1);
|
||||
}
|
||||
.pagedjs_left_page .pagedjs_full-page_content {
|
||||
width: calc(var(--pagedjs-pagebox-width) + var(--bleed-images));
|
||||
height: calc(var(--pagedjs-pagebox-height) + var(--bleed-images) + var(--bleed-images))!important;
|
||||
left: calc((var(--pagedjs-margin-left) + var(--bleed-images))*-1);
|
||||
|
||||
}
|
||||
.pagedjs_right_page .pagedjs_full-page_content {
|
||||
width: calc(var(--pagedjs-pagebox-width) + var(--bleed-images));
|
||||
height: calc(var(--pagedjs-pagebox-height) + var(--bleed-images) * 2)!important;
|
||||
left: calc(var(--pagedjs-margin-left)*-1);
|
||||
}
|
||||
294
public/csspageweaver/plugins/fullPage/fullPage.js
Normal file
294
public/csspageweaver/plugins/fullPage/fullPage.js
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
/**
|
||||
* @name Full page
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/fullPage }
|
||||
*/
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
|
||||
let bleedFull = '6mm';
|
||||
|
||||
export default class fullPage extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.selectorFullSpread = new Set();
|
||||
this.fullSpreadEls = new Set();
|
||||
this.selectorFullPage = new Set();
|
||||
this.fullPageEls = new Set();
|
||||
this.selectorFullRight = new Set();
|
||||
this.fullRightEls = new Set();
|
||||
this.selectorFullLeft= new Set();
|
||||
this.fullLeftEls = new Set();
|
||||
this.usedPagedEls = new Set();
|
||||
this.specificPage = new Set();
|
||||
this.specificPageClone = new Set();
|
||||
}
|
||||
|
||||
|
||||
|
||||
onDeclaration(declaration, dItem, dList, rule) {
|
||||
// Read customs properties
|
||||
if (declaration.property == "--pagedjs-full-page") {
|
||||
// get selector of the declaration (NOTE: need csstree.js)
|
||||
let selector = csstree.generate(rule.ruleNode.prelude);
|
||||
// Push selector in correct set
|
||||
if (declaration.value.value.includes("page")) {
|
||||
this.selectorFullPage.add(selector);
|
||||
}else if(declaration.value.value.includes("spread")) {
|
||||
this.selectorFullSpread.add(selector);
|
||||
}else if(declaration.value.value.includes("right")) {
|
||||
this.selectorFullRight.add(selector);
|
||||
}else if(declaration.value.value.includes("left")) {
|
||||
this.selectorFullLeft.add(selector);
|
||||
}else{
|
||||
let obj = { page: declaration.value.value, elem: selector };
|
||||
this.specificPage.add(JSON.stringify(obj));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
afterParsed(parsed){
|
||||
|
||||
console.log("FULL PAGE loaded");
|
||||
|
||||
// ADD pagedjs classes to elements
|
||||
for (let item of this.selectorFullPage) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("pagedjs_full-page-elem");
|
||||
}
|
||||
}
|
||||
for (let item of this.selectorFullSpread) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("pagedjs_full-spread-elem");
|
||||
}
|
||||
}
|
||||
for (let item of this.selectorFullLeft) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("pagedjs_full-page-left-elem");
|
||||
}
|
||||
}
|
||||
for (let item of this.selectorFullRight) {
|
||||
let elems = parsed.querySelectorAll(item);
|
||||
for (let elem of elems) {
|
||||
elem.classList.add("pagedjs_full-page-right-elem");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SPECIFIC PAGE ------------------------------------
|
||||
this.specificPage.forEach(entry => {
|
||||
const obj = JSON.parse(entry);
|
||||
const elements = parsed.querySelectorAll(obj.elem);
|
||||
if (elements.length > 0) {
|
||||
// pourquoi c’est ajouté même si l’élément n’existe pas ?
|
||||
elements[0].classList.add("pagedjs_full-page-specific");
|
||||
const clone = elements[0].cloneNode(true);
|
||||
obj.elemClone = clone.outerHTML;
|
||||
elements[0].remove();
|
||||
}
|
||||
this.specificPageClone.add(JSON.stringify(obj));
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
renderNode(clone, node) {
|
||||
// FULL SPREAD
|
||||
// if you find a full page element, move it in the array
|
||||
if (node.nodeType == 1 && node.classList.contains("pagedjs_full-spread-elem")) {
|
||||
this.fullSpreadEls.add(node);
|
||||
this.usedPagedEls.add(node);
|
||||
|
||||
// remove the element from the flow by hiding it.
|
||||
clone.style.display = "none";
|
||||
}
|
||||
|
||||
// FULL PAGE
|
||||
if (node.nodeType == 1 && node.classList.contains("pagedjs_full-page-left-elem")) {
|
||||
this.fullLeftEls.add(node);
|
||||
this.usedPagedEls.add(node);
|
||||
clone.style.display = "none";
|
||||
}else if (node.nodeType == 1 && node.classList.contains("pagedjs_full-page-right-elem")) {
|
||||
this.fullRightEls.add(node);
|
||||
this.usedPagedEls.add(node);
|
||||
clone.style.display = "none";
|
||||
}else if (node.nodeType == 1 && node.classList.contains("pagedjs_full-page-elem")) {
|
||||
this.fullPageEls.add(node);
|
||||
this.usedPagedEls.add(node);
|
||||
clone.style.display = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
afterPageLayout(pageElement, page, breakToken, chunker) {
|
||||
|
||||
if(page.id == "page-1"){
|
||||
let allPages = document.querySelector(".pagedjs_pages");
|
||||
allPages.style.setProperty('--bleed-images', bleedFull);
|
||||
}
|
||||
|
||||
// ADD --pagedjs-fold on body if doesn't exist
|
||||
if(pageElement.classList.contains("pagedjs_first_page")){
|
||||
let body = document.getElementsByTagName("body")[0];
|
||||
let style = window.getComputedStyle(body);
|
||||
let fold = style.getPropertyValue('--pagedjs-fold');
|
||||
if(!fold){
|
||||
body.style.setProperty('--pagedjs-fold', '0mm')
|
||||
}
|
||||
}
|
||||
|
||||
// FULL SPREAD
|
||||
// if there is an element in the fullSpreadEls Set, (goodbye arrays!)
|
||||
|
||||
for (let img of this.fullSpreadEls) {
|
||||
|
||||
if (page.element.classList.contains("pagedjs_right_page")) {
|
||||
|
||||
let imgLeft;
|
||||
let imgRight;
|
||||
|
||||
if (img.nodeName == "IMG") {
|
||||
/* Add outside + inside container if the element is an img */
|
||||
let containerLeft = document.createElement("div");
|
||||
containerLeft.classList.add("pagedjs_full-spread_container");
|
||||
let containerLeftInside = document.createElement("div");
|
||||
containerLeftInside.classList.add("pagedjs_full-spread_content");
|
||||
containerLeft.appendChild(containerLeftInside).appendChild(img);
|
||||
imgLeft = containerLeft;
|
||||
|
||||
let containerRight = document.createElement("div");
|
||||
containerRight.classList.add("pagedjs_full-spread_container");
|
||||
let containerRightInside = document.createElement("div");
|
||||
containerRightInside.classList.add("pagedjs_full-spread_content");
|
||||
containerRight.appendChild(containerRightInside).appendChild(img.cloneNode(true));
|
||||
imgRight = containerRight;
|
||||
|
||||
} else {
|
||||
/* Add outside container if the element is an img */
|
||||
let containerLeft = document.createElement("div");
|
||||
containerLeft.classList.add("pagedjs_full-spread_container");
|
||||
img.classList.add("pagedjs_full-spread_content");
|
||||
containerLeft.appendChild(img);
|
||||
imgLeft = containerLeft;
|
||||
let containerRight = document.createElement("div");
|
||||
containerRight.classList.add("pagedjs_full-spread_container");
|
||||
img.classList.add("pagedjs_full-spread_content");
|
||||
containerRight.appendChild(img.cloneNode(true));
|
||||
imgRight = containerRight;
|
||||
|
||||
}
|
||||
|
||||
// put the first element on the page
|
||||
let fullPage = chunker.addPage();
|
||||
fullPage.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", imgLeft);
|
||||
fullPage.element.classList.add("pagedjs_page_fullLeft");
|
||||
|
||||
// page right
|
||||
let fullPageRight = chunker.addPage();
|
||||
fullPageRight.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", imgRight);
|
||||
fullPageRight.element.classList.add("pagedjs_page_fullRight");
|
||||
img.style.removeProperty("display");
|
||||
|
||||
this.fullSpreadEls.delete(img);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FULL PAGE
|
||||
// if there is an element in the fullPageEls Set
|
||||
for (let img of this.fullPageEls) {
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("pagedjs_full-page_content");
|
||||
container.appendChild(img);
|
||||
let fullPage = chunker.addPage();
|
||||
|
||||
fullPage.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", container);
|
||||
fullPage.element.classList.add("pagedjs_page_fullPage");
|
||||
img.style.removeProperty("display");
|
||||
|
||||
this.fullPageEls.delete(img);
|
||||
}
|
||||
|
||||
// FULL Left PAGE
|
||||
// if there is an element in the fullLeftEls Set
|
||||
for (let img of this.fullLeftEls) {
|
||||
|
||||
if (page.element.classList.contains("pagedjs_right_page")) {
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("pagedjs_full-page_content");
|
||||
container.appendChild(img);
|
||||
let fullPage = chunker.addPage();
|
||||
|
||||
fullPage.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", container);
|
||||
fullPage.element.classList.add("pagedjs_page_fullPage");
|
||||
img.style.removeProperty("display");
|
||||
|
||||
this.fullLeftEls.delete(img);
|
||||
}
|
||||
}
|
||||
|
||||
// FULL RIGHT PAGE
|
||||
// if there is an element in the fullRightEls Set
|
||||
for (let img of this.fullRightEls) {
|
||||
|
||||
if (page.element.classList.contains("pagedjs_left_page")) {
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("pagedjs_full-page_content");
|
||||
container.appendChild(img);
|
||||
let fullPage = chunker.addPage();
|
||||
|
||||
fullPage.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", container);
|
||||
fullPage.element.classList.add("pagedjs_page_fullPage");
|
||||
img.style.removeProperty("display");
|
||||
|
||||
this.fullRightEls.delete(img);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// SPECIFIC PAGE ------------------------------------
|
||||
let pageNum = pageElement.id.split('page-')[1];
|
||||
pageNum = parseInt(pageNum);
|
||||
|
||||
this.specificPageClone.forEach(entry => {
|
||||
const obj = JSON.parse(entry);
|
||||
let targetedPage = obj.page;
|
||||
let prevPage = parseInt(targetedPage) - 1;
|
||||
|
||||
let elem = obj.elemClone;
|
||||
|
||||
if(prevPage == pageNum){
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("pagedjs_full-page_content");
|
||||
container.innerHTML = elem;
|
||||
let fullPage = chunker.addPage();
|
||||
|
||||
fullPage.element
|
||||
.querySelector(".pagedjs_page_content")
|
||||
.insertAdjacentElement("afterbegin", container);
|
||||
fullPage.element.classList.add("pagedjs_page_fullPage");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
1
public/csspageweaver/plugins/grid/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/grid/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
7
public/csspageweaver/plugins/grid/README.md
Normal file
7
public/csspageweaver/plugins/grid/README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
name: grid
|
||||
tags: experimental, boilerplate, gui
|
||||
description: A simple helper to see custom grid (1-12 columns)
|
||||
---
|
||||
|
||||
Caution: This plugin is not yet fully functional and requires further work.
|
||||
13
public/csspageweaver/plugins/grid/config.json
Normal file
13
public/csspageweaver/plugins/grid/config.json
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "Grid",
|
||||
"description": "",
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"title": "Grid",
|
||||
"description": "This Toogle a 12 columns grid",
|
||||
"toggle": true
|
||||
},
|
||||
"stylesheet": "grid.css",
|
||||
"script": "grid-ui.js",
|
||||
"hook": "grid-hook.js"
|
||||
}
|
||||
17
public/csspageweaver/plugins/grid/grid-hook.js
Normal file
17
public/csspageweaver/plugins/grid/grid-hook.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @name Grid
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/grid/ }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class GridPage extends Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
45
public/csspageweaver/plugins/grid/grid-ui.js
Normal file
45
public/csspageweaver/plugins/grid/grid-ui.js
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @name Grid
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/grid/ }
|
||||
*/
|
||||
|
||||
|
||||
export default function gridEvents(){
|
||||
let body = cssPageWeaver.ui.body;
|
||||
let fileTitle = cssPageWeaver.docTitle;
|
||||
|
||||
let grid = {};
|
||||
|
||||
// valeur par défaut → grille désactivée
|
||||
grid.default = {
|
||||
toggle: 'no-grid'
|
||||
};
|
||||
|
||||
grid.toggle = {};
|
||||
grid.toggle.input = cssPageWeaver.ui.grid.toggleInput;
|
||||
grid.toggle.label = cssPageWeaver.ui.grid.toggleLabel;
|
||||
|
||||
/* Récupération de la session précédente */
|
||||
grid.toggle.value = localStorage.getItem('gridToggle_' + fileTitle) || grid.default.toggle;
|
||||
|
||||
if(grid.toggle.value === "grid"){
|
||||
body.classList.add('grid'); // on indique qu'il y a la grille
|
||||
grid.toggle.input.checked = true;
|
||||
} else {
|
||||
body.classList.remove('grid'); // grille désactivée
|
||||
grid.toggle.input.checked = false;
|
||||
}
|
||||
|
||||
/* Événement toggle */
|
||||
grid.toggle.input.addEventListener("input", (e) => {
|
||||
if(e.target.checked){
|
||||
body.classList.add('grid'); // grille activée
|
||||
localStorage.setItem('gridToggle_' + fileTitle, 'grid');
|
||||
} else {
|
||||
body.classList.remove('grid'); // grille désactivée
|
||||
localStorage.setItem('gridToggle_' + fileTitle, 'no-grid');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
127
public/csspageweaver/plugins/grid/grid.css
Normal file
127
public/csspageweaver/plugins/grid/grid.css
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
@media screen{
|
||||
|
||||
|
||||
/* .pagedjs_sheet{
|
||||
--grid-bold: #888;
|
||||
--grid-light: #cfcfcf;
|
||||
background-color: #e5e5f7;
|
||||
opacity: 0.8;
|
||||
background-image: linear-gradient(90deg, var(--grid-bold) 1px, transparent 1px), linear-gradient(transparent 1px, transparent 1px), linear-gradient(90deg, var(--grid-light) 1px, white 1px);
|
||||
|
||||
background-size: 40px 40px, 40px 40px, 10px 10px, 10px 10px;
|
||||
background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
|
||||
} */
|
||||
|
||||
|
||||
body.grid .pagedjs_sheet {
|
||||
|
||||
|
||||
--grid-bold: #cfcfcf;
|
||||
--grid-light: #efefef;
|
||||
|
||||
--bold-step: 56px;
|
||||
--light-step: 14px;
|
||||
--shift-x: 28px;
|
||||
|
||||
background-color: white;
|
||||
opacity: 0.8;
|
||||
|
||||
background-image:
|
||||
/* Traits bold */
|
||||
repeating-linear-gradient(
|
||||
90deg,
|
||||
var(--grid-bold) 0 1px,
|
||||
transparent 1px var(--bold-step)
|
||||
),
|
||||
repeating-linear-gradient(
|
||||
0deg,
|
||||
var(--grid-bold) 0 1px,
|
||||
transparent 1px var(--bold-step)
|
||||
),
|
||||
|
||||
/* Traits fins (3 traits → 4 carrés) */
|
||||
repeating-linear-gradient(
|
||||
90deg,
|
||||
var(--grid-light) 0 1px,
|
||||
transparent 1px var(--light-step)
|
||||
),
|
||||
repeating-linear-gradient(
|
||||
0deg,
|
||||
var(--grid-light) 0 1px,
|
||||
transparent 1px var(--light-step)
|
||||
);
|
||||
|
||||
background-position:
|
||||
var(--shift-x) 0,
|
||||
var(--shift-x) 0,
|
||||
var(--shift-x) 0,
|
||||
var(--shift-x) 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.grid-page{
|
||||
--nbr-columns: 8;
|
||||
width: var(--pagedjs-pagebox-width);
|
||||
height: var(--pagedjs-pagebox-height);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(var(--nbr-columns), calc(100%/var(--nbr-columns)));
|
||||
|
||||
box-shadow: 1px 0px 0px 0px var(--grid-color);
|
||||
|
||||
--grid-color: magenta;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.pagedjs_right_page .grid-page{
|
||||
padding-left: var(--pagedjs-margin-left);
|
||||
padding-right: var(--pagedjs-margin-right);
|
||||
}
|
||||
|
||||
.pagedjs_left_page .grid-page{
|
||||
padding-left: var(--pagedjs-margin-left);
|
||||
padding-right: var(--pagedjs-margin-right);
|
||||
}
|
||||
|
||||
|
||||
.grid-page .grid-column{
|
||||
box-shadow: 1px 0px 0px 0px var(--grid-color);
|
||||
grid-row: 1/end;
|
||||
width: 100%;
|
||||
justify-self: right;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.grid-column-0{
|
||||
grid-column: 1;
|
||||
box-shadow: -1px 0px 0px 0px var(--grid-color)!important;
|
||||
justify-self: left;
|
||||
}
|
||||
|
||||
.grid-column-1{ grid-column: 1; }
|
||||
.grid-column-2{ grid-column: 2; }
|
||||
.grid-column-3{ grid-column: 3; }
|
||||
.grid-column-4{ grid-column: 4; }
|
||||
.grid-column-5{ grid-column: 5; }
|
||||
.grid-column-6{ grid-column: 6; }
|
||||
.grid-column-7{ grid-column: 7; }
|
||||
.grid-column-8{ grid-column: 8; }
|
||||
.grid-column-9{ grid-column: 9; }
|
||||
.grid-column-10{ grid-column: 10; }
|
||||
.grid-column-11{ grid-column: 11; }
|
||||
.grid-column-12{ grid-column: 12; }
|
||||
}
|
||||
|
||||
.no-grid .grid-page{
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
1
public/csspageweaver/plugins/imposition/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/imposition/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
17
public/csspageweaver/plugins/imposition/config.json
Normal file
17
public/csspageweaver/plugins/imposition/config.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "Booklet Imposition",
|
||||
"description": " This script re-arrange the pages of your document in order to make an imposed sheet layouts for printing. ",
|
||||
"author": ["Quentin Juhel", "Julien Taquet", "Julien Bidoret", "Julie Blanc"],
|
||||
"licence": "MIT",
|
||||
"repository": "https://gitlab.coko.foundation/pagedjs/pagedjs-plugins/booklet-imposition",
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"title": "Imposition",
|
||||
"description": "Re-arrange the pages in order to make an imposed sheet layouts for printing.",
|
||||
"toggle": false,
|
||||
"template": "template.html"
|
||||
},
|
||||
"hook": "index.js"
|
||||
}
|
||||
|
||||
|
||||
363
public/csspageweaver/plugins/imposition/index.js
Normal file
363
public/csspageweaver/plugins/imposition/index.js
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
/**
|
||||
* @file 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
|
||||
* @author Originally developped by Julien Bidoret,Quentin Juhel and Julien Taquet,
|
||||
* @author adapted for this project by Julie Blanc
|
||||
* @see { @link https://gitlab.coko.foundation/pagedjs/pagedjs-plugins/booklet-imposition }
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/imposition/}
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class booklet extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.pagedbooklet;
|
||||
this.pagedspread;
|
||||
this.sourceSize;
|
||||
this.pageStart;
|
||||
this.pageEnd;
|
||||
}
|
||||
|
||||
afterRendered(pages) {
|
||||
|
||||
/* Launch when printing */
|
||||
window.addEventListener("beforeprint", (evenement) => {
|
||||
|
||||
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;
|
||||
let onePage = width + bleedNum*2;
|
||||
|
||||
// get values
|
||||
let inputBooklet = document.querySelector("#input-booklet");
|
||||
let inputSpread = document.querySelector("#input-spread");
|
||||
let inputRange = document.querySelector("#imposition-range");
|
||||
let inputBookletStart = document.querySelector("#booklet-start").value;
|
||||
let inputBookletEnd = document.querySelector("#booklet-end").value;
|
||||
|
||||
let containerPages = document.querySelector(".pagedjs_pages");
|
||||
|
||||
|
||||
|
||||
if(inputBooklet.checked){
|
||||
this.pagedbooklet = true;
|
||||
this.pageStart = 1;
|
||||
this.pageEnd = pages.length;
|
||||
|
||||
if(inputRange.checked){
|
||||
this.pageStart = parseInt(inputBookletStart);
|
||||
this.pageEnd = parseInt(inputBookletEnd);
|
||||
}
|
||||
}else if(inputSpread.checked){
|
||||
this.pagedspread = true;
|
||||
this.pageStart = 1;
|
||||
this.pageEnd = pages.length;
|
||||
|
||||
if(inputRange.checked){
|
||||
this.pageStart = parseInt(inputBookletStart);
|
||||
this.pageEnd = parseInt(inputBookletEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
var twoPageView = `.pagedjs_page:nth-of-type(1){
|
||||
bakground-color: red;
|
||||
margin-left: ${spreadHalf}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}`;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (this.pagedspread == true) {
|
||||
console.log("double page view please");
|
||||
let style = document.createElement("style");
|
||||
style.textContent = newSize;
|
||||
document
|
||||
.head
|
||||
.appendChild(style);
|
||||
let styleBis = document.createElement("style");
|
||||
styleBis.textContent = twoPageView;
|
||||
document
|
||||
.head
|
||||
.appendChild(styleBis);
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
0
public/csspageweaver/plugins/imposition/stylesheet.css
Normal file
0
public/csspageweaver/plugins/imposition/stylesheet.css
Normal file
22
public/csspageweaver/plugins/imposition/template.html
Normal file
22
public/csspageweaver/plugins/imposition/template.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<input type="radio" id="input-spread" data-open-container="imposition-details" name="radio-imposition">
|
||||
<label for="input-spread" class="label-block">Two-page view</label>
|
||||
|
||||
<input type="radio" id="input-booklet" data-open-container="imposition-details" name="radio-imposition">
|
||||
<label for="input-booklet" class="label-block">Booklet <span></span></label>
|
||||
|
||||
<div id="imposition-details">
|
||||
|
||||
<div id="radio-imposition-pages">
|
||||
<input type="radio" id="imposition-all" name="radio-imposition-pages" value="all" checked />
|
||||
<label for="imposition-all" class="label-block">All pages</label>
|
||||
<input type="radio" id="imposition-range" name="radio-imposition-pages" value="booklet" />
|
||||
<label for="imposition-range" class="label-block">Range</label>
|
||||
</div>
|
||||
|
||||
<div id="booklet-sheets" class="panel-group-values">
|
||||
<p>from</p>
|
||||
<input type="number" id="booklet-start" name="booklet-start" min="1" max="1000" value="1">
|
||||
<p>to</p>
|
||||
<input type="number" id="booklet-end" name="booklet-end" min="1" max="1000" value="16">
|
||||
</div>
|
||||
</div>
|
||||
1
public/csspageweaver/plugins/inlineNotes/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/inlineNotes/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
77
public/csspageweaver/plugins/inlineNotes/README.md
Normal file
77
public/csspageweaver/plugins/inlineNotes/README.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
name: InlineNotes
|
||||
tags: recommended, stable
|
||||
description: This script moves listed notes to inline elements at the place of the call.
|
||||
|
||||
---
|
||||
|
||||
# Inline notes
|
||||
|
||||
To move notes in the correct place in the page, Paged.js needs to have the note element in the flow. But in convert tools like Pandoc, it’s common to have the notes elements presented in a list with link elements in the flow pointing to the correponding note.
|
||||
|
||||
This script moves listed notes to inline elements at the place of the call.
|
||||
|
||||
|
||||
|
||||
## How to use
|
||||
|
||||
Add this folder in `csspageweaver/plugins/`.
|
||||
|
||||
Call the plugin in `csspageweaver/manifest.json`:
|
||||
|
||||
```json
|
||||
"plugins": [
|
||||
"inlineNotes",
|
||||
// other plugins ...
|
||||
],
|
||||
```
|
||||
|
||||
## Config.json
|
||||
|
||||
In `manifest.json`, you can modify/add some parameters:
|
||||
|
||||
```
|
||||
"pluginsParameters": {
|
||||
// parameters of other plugins ...
|
||||
"inlineNotes": {
|
||||
"input": ".footnote-ref",
|
||||
"containerNotes": ".footnotes"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
- `input` → CSS selector of the original call element (by default: `.footnote-ref`)
|
||||
- `containerNotes` → CSS selector of the original container of the footnote list, this container is deleted after moving notes (by default: `#footnotes`)
|
||||
- `` → Class of the new span created for the note
|
||||
|
||||
|
||||
## Exemple
|
||||
|
||||
Before :
|
||||
|
||||
```HTML
|
||||
<p>Gutenberg in 1439 was the first European to use movable type.
|
||||
Among his many contributions to printing are: the invention of
|
||||
a process for mass-producing movable type; the use of oil-based
|
||||
ink for printing books; <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> adjustable molds; mechanical movable type; and the use of a wooden printing press similar to the agricultural screw presses of the period.</p>
|
||||
<aside id="#footnotes">
|
||||
<hr>
|
||||
<ol>
|
||||
<li id="fn1">Soap, Sex, and Cigarettes: A Cultural History of American Advertising By Juliann Sivulka, page 5</li>
|
||||
</ol>
|
||||
</aside>
|
||||
|
||||
```
|
||||
|
||||
|
||||
After (wiht the plugin):
|
||||
|
||||
```HTML
|
||||
<p>Gutenberg in 1439 was the first European to use movable type.
|
||||
Among his many contributions to printing are: the invention of
|
||||
a process for mass-producing movable type; the use of oil-based
|
||||
ink for printing books; <span class="inline-note" data-counter-note="1">Soap, Sex, and Cigarettes: A Cultural History of American Advertising By Juliann Sivulka, page 5</span>
|
||||
adjustable molds; mechanical movable type; and the use
|
||||
of a wooden printing press similar to the agricultural
|
||||
screw presses of the period.</p>
|
||||
```
|
||||
8
public/csspageweaver/plugins/inlineNotes/config.json
Normal file
8
public/csspageweaver/plugins/inlineNotes/config.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Inline notes",
|
||||
"description": "This script moves listed notes to inline elements at the place of the call",
|
||||
"author": ["Julie Blanc"],
|
||||
"license": "MIT License",
|
||||
"version": "1.0",
|
||||
"hook": "inlineNotes.js"
|
||||
}
|
||||
140
public/csspageweaver/plugins/inlineNotes/inlineNotes.js
Normal file
140
public/csspageweaver/plugins/inlineNotes/inlineNotes.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @name Inline Notes
|
||||
* @author Julien Bidoret
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/inlineNotes }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class inlineNotes extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.input = cssPageWeaver.features.inlineNotes.parameters?.input || ".footnote-ref"; // ← CSS selector of the call element
|
||||
this.containerNotes = cssPageWeaver.features.inlineNotes.parameters?.containerNotes || "#footnotes"; // ← CSS selector of the container of the footnote
|
||||
this.newClass = cssPageWeaver.features.inlineNotes.parameters?.newClass || "inline-note"; // ← Class of the span create for the note
|
||||
}
|
||||
|
||||
beforeParsed(content) {
|
||||
|
||||
// ---- HUGO SPECIFIC // Correction des ids et href 'fn:' en 'fn-' ----
|
||||
// 1. Tous les éléments avec un id commençant par "fn:"
|
||||
content.querySelectorAll('[id^="fn:"]').forEach(el => {
|
||||
el.id = el.id.replace(/:/g, '-');
|
||||
});
|
||||
|
||||
// 2. Tous les éléments avec un id commençant par "fnref:"
|
||||
content.querySelectorAll('[id^="fnref:"]').forEach(el => {
|
||||
el.id = el.id.replace(/:/g, '-');
|
||||
});
|
||||
|
||||
// 3. Tous les éléments avec un href commençant par "#fn:"
|
||||
content.querySelectorAll('[href^="#fn:"]').forEach(el => {
|
||||
el.href = el.href.replace(/:/g, '-');
|
||||
});
|
||||
|
||||
// 4. Tous les éléments avec un href commençant par "#fnref:"
|
||||
content.querySelectorAll('[href^="#fnref:"]').forEach(el => {
|
||||
el.href = el.href.replace(/:/g, '-');
|
||||
});
|
||||
|
||||
// 5. (optionnel) Tous les 'for' dans labels, si jamais (pas typique)
|
||||
content.querySelectorAll('[for^="fn:"]').forEach(el => {
|
||||
el.htmlFor = el.htmlFor.replace(/:/g, '-');
|
||||
});
|
||||
|
||||
|
||||
|
||||
inlineNotesHandler({
|
||||
content: content,
|
||||
input: this.input,
|
||||
containerNotes: this.containerNotes,
|
||||
type: this.newClass
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function inlineNotesHandler(params){
|
||||
|
||||
let content = params.content;
|
||||
let input = params.input;
|
||||
let type = params.type;
|
||||
let container = params.containerNotes;
|
||||
|
||||
createNotes(content, input, type, container);
|
||||
|
||||
// let noteContainer = content.querySelector(params.containerNotes);
|
||||
// if(noteContainer){
|
||||
// noteContainer.remove();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getBlocks(element){
|
||||
return element.querySelectorAll('div,p,blockquote,section,article,h1,h2,h3,h4,h5,h6,figure');
|
||||
}
|
||||
|
||||
// get only inline-level tags
|
||||
function unwrapBlockChildren(element) {
|
||||
let blocks = getBlocks(element);
|
||||
|
||||
blocks.forEach(block => {
|
||||
block.insertAdjacentHTML("beforebegin", block.innerHTML);
|
||||
block.remove();
|
||||
});
|
||||
let remainingblocks = getBlocks(element);
|
||||
if(remainingblocks.length) unwrapBlockChildren(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
function createNotes(content, input, type, container){
|
||||
|
||||
let containers = content.querySelectorAll(container);
|
||||
|
||||
containers.forEach(function (container, index) {
|
||||
let section = container.parentNode;
|
||||
|
||||
let calls = section.querySelectorAll(input);
|
||||
calls.forEach( (call, index) => {
|
||||
|
||||
let href = call.getAttribute('href');
|
||||
let hashIndex = href.indexOf('#');
|
||||
let selector = href.slice(hashIndex);
|
||||
|
||||
let note = section.querySelector(selector);
|
||||
if (!note) {
|
||||
console.warn('Note non trouvée pour', selector);
|
||||
return;
|
||||
}
|
||||
|
||||
let back = note.querySelector(".footnote-back");
|
||||
if(back){
|
||||
back.remove();
|
||||
}
|
||||
|
||||
|
||||
|
||||
let inline_note = document.createElement('span');
|
||||
inline_note.className = type;
|
||||
let num = index + 1;
|
||||
inline_note.dataset.counterNote = num;
|
||||
inline_note.dataset.chapter = section.id;
|
||||
|
||||
inline_note.innerHTML = unwrapBlockChildren(note).innerHTML;
|
||||
call.after(inline_note);
|
||||
|
||||
call.parentElement.removeChild(call);
|
||||
|
||||
|
||||
})
|
||||
|
||||
container.remove();
|
||||
});
|
||||
|
||||
}
|
||||
1
public/csspageweaver/plugins/marginBox/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/marginBox/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
10
public/csspageweaver/plugins/marginBox/config.json
Normal file
10
public/csspageweaver/plugins/marginBox/config.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"title": "Margin boxes",
|
||||
"description": "This Toogle border around margin box",
|
||||
"toggle": true
|
||||
},
|
||||
"script": "marginBox.js",
|
||||
"stylesheet": "marginBox.css"
|
||||
}
|
||||
7
public/csspageweaver/plugins/marginBox/marginBox.css
Normal file
7
public/csspageweaver/plugins/marginBox/marginBox.css
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
:root {
|
||||
--color-marginBox: purple;
|
||||
}
|
||||
|
||||
.no-marginBoxes{
|
||||
--color-marginBox: transparent;
|
||||
}
|
||||
26
public/csspageweaver/plugins/marginBox/marginBox.js
Normal file
26
public/csspageweaver/plugins/marginBox/marginBox.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* @name Margin Box
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/marginBox }
|
||||
*/
|
||||
|
||||
export default function marginBoxEvents(){
|
||||
|
||||
let body = cssPageWeaver.ui.body
|
||||
|
||||
/* MARGIN BOXES ----------------------------------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------------------------------------------*/
|
||||
let marginButton = document.querySelector('#label-marginBox-toggle');
|
||||
|
||||
body.classList.add('no-marginBoxes');
|
||||
|
||||
cssPageWeaver.ui.marginBox.toggleInput.addEventListener("input", (e) => {
|
||||
if(e.target.checked){
|
||||
/* see baseline */
|
||||
body.classList.remove('no-marginBoxes');
|
||||
}else{
|
||||
/* hide baseline */
|
||||
body.classList.add('no-marginBoxes');
|
||||
}
|
||||
});
|
||||
}
|
||||
82
public/csspageweaver/plugins/moveElems/README.md
Normal file
82
public/csspageweaver/plugins/moveElems/README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
name: Move Elems
|
||||
tags: stable, feedback-wanted
|
||||
description: Moves elements within the DOM structure during rendering.
|
||||
---
|
||||
|
||||
|
||||
# Move Elems (paged.js)
|
||||
|
||||
This plugin moves elements within the DOM structure during rendering. Usefull with other script like [Full page](https://gitlab.com/csspageweaver/plugins/fullPage) or [Float page](https://gitlab.com/csspageweaver/plugins/floatPage).
|
||||
|
||||
This plugin moves elements relative to their sibling elements in the DOM — either forward or backward — based on the integer value you provide.
|
||||
|
||||
You need to use [csstree.js](https://github.com/csstree/csstree) in order to transform custom properties.
|
||||
If you use CSS Page Weaver is inclued by default
|
||||
|
||||
|
||||
## How to install
|
||||
|
||||
**With CSS Page Weaver**
|
||||
|
||||
Register the `moveElems` plugin in your `manifest.json`:
|
||||
|
||||
```json
|
||||
[
|
||||
"moveElems",
|
||||
// other plugins
|
||||
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
⚠️ It’s recommended to load this plugin first to prevent any conflicts with other plugins.
|
||||
|
||||
|
||||
**Without CSS Page Weaver**
|
||||
|
||||
Include both csstree and the fullPage script in your HTML `<head>`:
|
||||
|
||||
```html
|
||||
<script src="js/csstree.min.js"></script>
|
||||
<script type="module" src="path/to/fullPage/floatPage.js"></script>
|
||||
```
|
||||
|
||||
Don’t forget to update the path to the paged.esm.js module in the import statement before using the script.
|
||||
|
||||
```js
|
||||
import { Handler } from '/path/to/paged.esm.js'
|
||||
```
|
||||
|
||||
|
||||
## How to use it
|
||||
|
||||
In your CSS, add the following custom property to the elements you want to move, using an ID or class:
|
||||
|
||||
```css
|
||||
elem{
|
||||
--x-move-elem: 2;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
In this example, the element will be moved after its second next sibling.
|
||||
You can also use negative values to move elements backward, e.g.:
|
||||
|
||||
```css
|
||||
elem{
|
||||
--x-move-elem: -3;
|
||||
}
|
||||
```
|
||||
|
||||
This would move the element before its third previous sibling.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [pagedjs.org](https://www.pagedjs.org/)
|
||||
- [csstree.js](https://github.com/csstree/csstree)
|
||||
|
||||
MIT licence, Julie Blanc, 2025
|
||||
|
||||
|
||||
8
public/csspageweaver/plugins/moveElems/config.json
Normal file
8
public/csspageweaver/plugins/moveElems/config.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Move Elems",
|
||||
"description": "Moves elements within the DOM structure during rendering",
|
||||
"author": ["Julie Blanc"],
|
||||
"license": "MIT License",
|
||||
"version": "1.0",
|
||||
"hook": "moveElems.js"
|
||||
}
|
||||
81
public/csspageweaver/plugins/moveElems/moveElems.js
Normal file
81
public/csspageweaver/plugins/moveElems/moveElems.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* @name Move Elems v1.0
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/moveElems }
|
||||
*/
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
|
||||
export class moveElems extends Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.selectorMoveElem = new Set();
|
||||
}
|
||||
|
||||
onDeclaration(declaration, dItem, dList, rule) {
|
||||
|
||||
if (declaration.property == "--x-move-elem") {
|
||||
let selector = csstree.generate(rule.ruleNode.prelude);
|
||||
let value = declaration.value.value
|
||||
let doubleArray = [selector, value];
|
||||
this.selectorMoveElem.add(doubleArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
afterParsed(parsed){
|
||||
|
||||
console.log("MOVE ELEMS LOADED");
|
||||
|
||||
// ADD data to move elements
|
||||
for (let item of this.selectorMoveElem) {
|
||||
let elem = parsed.querySelector(item[0]);
|
||||
if(elem){
|
||||
elem.dataset.moveImg = item[1];
|
||||
}
|
||||
}
|
||||
|
||||
moveElem(parsed);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function moveElem(parsed){
|
||||
let elems = parsed.querySelectorAll('[data-move-img]');
|
||||
for (let elem of elems) {
|
||||
let n = parseInt(elem.getAttribute('data-move-img'));
|
||||
let newPlace
|
||||
if(n < 0){
|
||||
newPlace = elem.previousSibling;
|
||||
if (newPlace.nodeType !== Node.ELEMENT_NODE) {
|
||||
newPlace = newPlace.previousSibling
|
||||
}
|
||||
n = n*-1 - 1;
|
||||
for(let i = 0; i < n; i++){
|
||||
newPlace = newPlace.previousSibling
|
||||
if (newPlace.nodeType !== Node.ELEMENT_NODE) {
|
||||
newPlace = newPlace.previousSibling
|
||||
}
|
||||
}
|
||||
}else{
|
||||
newPlace = elem.nextSibling;
|
||||
if (newPlace.nodeType !== Node.ELEMENT_NODE) {
|
||||
newPlace = newPlace.nextSibling;
|
||||
}
|
||||
for(let i = 0; i < n; i++){
|
||||
newPlace = newPlace.nextSibling;
|
||||
if (newPlace.nodeType !== Node.ELEMENT_NODE) {
|
||||
newPlace = newPlace.nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newPlace.parentNode.insertBefore(elem, newPlace);
|
||||
// do next = next.nextSibling; while(next && next.nodeType !== 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
1
public/csspageweaver/plugins/previewPage/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/previewPage/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
19
public/csspageweaver/plugins/previewPage/config.json
Normal file
19
public/csspageweaver/plugins/previewPage/config.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "Preview",
|
||||
"description": "",
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"toggle": false,
|
||||
"template": "template.html",
|
||||
"shortcut": [
|
||||
{
|
||||
"active": true,
|
||||
"tutorial": false,
|
||||
"keys": ["shiftKey", "W"],
|
||||
"description": "Toggle Preview"
|
||||
}
|
||||
]
|
||||
},
|
||||
"stylesheet": "stylesheet.css",
|
||||
"script": "event.js"
|
||||
}
|
||||
52
public/csspageweaver/plugins/previewPage/event.js
Normal file
52
public/csspageweaver/plugins/previewPage/event.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* @name Preview page
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/previewPage }
|
||||
*/
|
||||
|
||||
export default function previewEvents(){
|
||||
const body = cssPageWeaver.ui.body
|
||||
|
||||
// set a "unique" filename based on title element, in case several books are opened
|
||||
const fileTitle = document.getElementsByTagName("title")[0].text;
|
||||
|
||||
const previewToggle = document.querySelector("#preview-toggle");
|
||||
const previewButton = document.querySelector("#button-preview");
|
||||
|
||||
// Check localStorage for user's preference and apply it
|
||||
const preference = localStorage.getItem('previewToggle' + fileTitle);
|
||||
if (preference === "preview") {
|
||||
body.classList.add('interface-preview');
|
||||
previewToggle.checked = true;
|
||||
} else {
|
||||
body.classList.remove('interface-preview');
|
||||
previewToggle.checked = false;
|
||||
}
|
||||
|
||||
function preview(){
|
||||
const isPreview = body.classList.contains('interface-preview');
|
||||
body.classList.toggle('interface-preview');
|
||||
previewToggle.checked = !isPreview;
|
||||
localStorage.setItem('previewToggle' + fileTitle, isPreview ? 'no-preview' : 'preview');
|
||||
|
||||
}
|
||||
// Toggle preview mode when the button is clicked
|
||||
previewButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
preview()
|
||||
});
|
||||
|
||||
// Add keydown listener based on configuration
|
||||
cssPageWeaver.features.previewPage.ui.shortcut.forEach( shortcut => {
|
||||
// if user do not have disable plugin
|
||||
if(shortcut.active){
|
||||
|
||||
// Get shortcut combinaison from config
|
||||
const keys = shortcut.keys
|
||||
|
||||
// CSS Page Weaver has a simple function to help you register your keyboard shortcut
|
||||
cssPageWeaver.helpers.addKeydownListener(keys, preview)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
39
public/csspageweaver/plugins/previewPage/stylesheet.css
Normal file
39
public/csspageweaver/plugins/previewPage/stylesheet.css
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* PREVIEW MODE */
|
||||
|
||||
.interface-preview {
|
||||
background-color: var(--color-preview);
|
||||
--color-pageBox: #999;
|
||||
}
|
||||
|
||||
.interface-preview .pagedjs_page{
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.interface-preview .pagedjs_right_page .pagedjs_bleed,
|
||||
.interface-preview .pagedjs_left_page .pagedjs_bleed-top,
|
||||
.interface-preview .pagedjs_left_page .pagedjs_bleed-bottom,
|
||||
.interface-preview .pagedjs_left_page .pagedjs_bleed-left{
|
||||
background-color: var(--color-preview);
|
||||
z-index:999999;
|
||||
}
|
||||
|
||||
.interface-preview .pagedjs_marks-crop,
|
||||
.interface-preview .pagedjs_marks-crop{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
.interface-preview .pagedjs_pagebox {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
.button-print{ display: none; }
|
||||
|
||||
.interface-preview{
|
||||
--color-marginBox: transparent;
|
||||
}
|
||||
|
||||
.interface-preview .grid-page{
|
||||
display: none;
|
||||
}
|
||||
31
public/csspageweaver/plugins/previewPage/template.html
Normal file
31
public/csspageweaver/plugins/previewPage/template.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<div id="buttons-preview" class="buttons-group align-right">
|
||||
|
||||
<input type="checkbox" id="preview-toggle" name="preview-toggle">
|
||||
<button id="button-preview" title="Preview">
|
||||
|
||||
<svg class="icon-preview" width="100%" height="100%" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g>
|
||||
<polyline fill="none" points=" 649,137.999 675,137.999 675,155.999 661,155.999 " stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"></polyline>
|
||||
<polyline fill="none" points=" 653,155.999 649,155.999 649,141.999 " stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"></polyline>
|
||||
<polyline fill="none" points=" 661,156 653,162 653,156 " stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"></polyline>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M16,25c-4.265,0-8.301-1.807-11.367-5.088c-0.377-0.403-0.355-1.036,0.048-1.413c0.404-0.377,1.036-0.355,1.414,0.048 C8.778,21.419,12.295,23,16,23c4.763,0,9.149-2.605,11.84-7c-2.69-4.395-7.077-7-11.84-7c-4.938,0-9.472,2.801-12.13,7.493 c-0.272,0.481-0.884,0.651-1.363,0.377c-0.481-0.272-0.649-0.882-0.377-1.363C5.147,10.18,10.333,7,16,7 c5.668,0,10.853,3.18,13.87,8.507c0.173,0.306,0.173,0.68,0,0.985C26.853,21.819,21.668,25,16,25z"></path>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M16,21c-2.757,0-5-2.243-5-5s2.243-5,5-5s5,2.243,5,5S18.757,21,16,21z M16,13c-1.654,0-3,1.346-3,3s1.346,3,3,3 s3-1.346,3-3S17.654,13,16,13z"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
</button>
|
||||
<button title="Print" id="button-print" onclick="window.print()" data-ready="false" data-text="Print">
|
||||
<svg class="reset-this icon-printer" width="100%" height="100%" viewBox="0 0 478 478" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M460.8,119.467L375.467,119.467L375.467,17.067C375.467,7.641 367.826,0 358.4,0L119.467,0C110.041,0 102.4,7.641 102.4,17.067L102.4,119.467L17.067,119.467C7.641,119.467 0,127.108 0,136.533L0,358.4C0,367.826 7.641,375.467 17.067,375.467L102.4,375.467L102.4,460.8C102.4,470.226 110.041,477.867 119.467,477.867L358.4,477.867C367.826,477.867 375.467,470.226 375.467,460.8L375.467,375.467L460.8,375.467C470.226,375.467 477.867,367.826 477.867,358.4L477.867,136.533C477.867,127.108 470.226,119.467 460.8,119.467ZM136.533,34.133L341.333,34.133L341.333,119.466L136.533,119.466L136.533,34.133ZM341.333,443.733L136.533,443.733L136.533,290.133L341.333,290.133L341.333,443.733ZM443.733,341.333L375.466,341.333L375.466,290.133L392.533,290.133C401.959,290.133 409.6,282.492 409.6,273.066C409.6,263.64 401.959,256 392.533,256L85.333,256C75.907,256 68.266,263.641 68.266,273.067C68.266,282.493 75.907,290.134 85.333,290.134L102.4,290.134L102.4,341.334L34.133,341.334L34.133,153.6L443.733,153.6L443.733,341.333Z" style="fill-rule:nonzero;"></path>
|
||||
<path d="M409.6,187.733L392.533,187.733C383.107,187.733 375.466,195.374 375.466,204.8C375.466,214.226 383.107,221.867 392.533,221.867L409.6,221.867C419.026,221.867 426.667,214.226 426.667,204.8C426.667,195.374 419.026,187.733 409.6,187.733Z" style="fill-rule:nonzero;"></path>
|
||||
<path d="M290.133,324.267L187.733,324.267C178.307,324.267 170.666,331.908 170.666,341.334C170.666,350.76 178.307,358.401 187.733,358.401L290.133,358.401C299.559,358.401 307.2,350.76 307.2,341.334C307.2,331.908 299.559,324.267 290.133,324.267Z" style="fill-rule:nonzero;"></path>
|
||||
<path d="M290.133,375.467L187.733,375.467C178.307,375.467 170.666,383.108 170.666,392.534C170.666,401.96 178.307,409.601 187.733,409.601L290.133,409.601C299.559,409.601 307.2,401.96 307.2,392.534C307.2,383.108 299.559,375.467 290.133,375.467Z" style="fill-rule:nonzero;"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
1
public/csspageweaver/plugins/reloadInPlace/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/reloadInPlace/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
17
public/csspageweaver/plugins/reloadInPlace/Readme.md
Normal file
17
public/csspageweaver/plugins/reloadInPlace/Readme.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Reload In Place
|
||||
|
||||
## Configuration
|
||||
|
||||
In `manifest.json`
|
||||
|
||||
```json
|
||||
"plugins":{
|
||||
"inlineNotes"
|
||||
},
|
||||
"pluginsParameters":{
|
||||
"reloadInPlace": {
|
||||
"blur": false,
|
||||
"behavior": "instant"
|
||||
}
|
||||
},
|
||||
```
|
||||
9
public/csspageweaver/plugins/reloadInPlace/config.json
Normal file
9
public/csspageweaver/plugins/reloadInPlace/config.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "Reload In Place",
|
||||
"description": "A simple script to add your CSS Page Weaver project. On reload, it will make the web browser scroll to the place it was before reload. ",
|
||||
"author": ["Nicolas Taffin", "Sameh Chafik"],
|
||||
"licence": "MIT",
|
||||
"version": 2,
|
||||
"repository": "https://gitlab.com/nicolastaf/pagedjs-reload-in-place",
|
||||
"hook": "reloadInPlace.js"
|
||||
}
|
||||
174
public/csspageweaver/plugins/reloadInPlace/reloadInPlace.js
Normal file
174
public/csspageweaver/plugins/reloadInPlace/reloadInPlace.js
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* @name Reload-in-place v2.0
|
||||
* @desc A simple script to add to your pagedjs project. On reload, it will make the web browser scroll to the place it was before reload.
|
||||
* Useful when styling or proof correcting your book. Multi docs compatible and doesn't wait for complete compilation to go.
|
||||
* @author Nicolas Taffin
|
||||
* @author Sameh Chafik
|
||||
* @author (adapted by) Benjamin G. <ecrire@bnjm.eu>
|
||||
* @license MIT
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/reloadInPlace }
|
||||
*/
|
||||
|
||||
|
||||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
|
||||
export default class reloadInPlace extends Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.parameters = cssPageWeaver.features.reloadInPlace.parameters || {}
|
||||
this.isScrollBlured = this.parameters.blur || true;
|
||||
this.scrollBehavior = this.parameters.scrollBehavior || 'instant';
|
||||
|
||||
// set a "unique" filename based on title element, in case several books are opened
|
||||
this.fileTitle = document.getElementsByTagName("title")[0].text.replace(/ /g, "");
|
||||
}
|
||||
|
||||
beforeParsed() {
|
||||
// separate human / machine scroll
|
||||
this.parameters.machineScroll = false;
|
||||
|
||||
// check pagedJS ended compilation
|
||||
this.parameters.cssPageWeaverEnd = false;
|
||||
|
||||
// Make it blur if needed
|
||||
this.isBlur()
|
||||
}
|
||||
|
||||
afterParsed() {
|
||||
this.moveFast();
|
||||
}
|
||||
|
||||
afterRendered(pages) {
|
||||
|
||||
this.parameters.cssPageWeaverEnd = true;
|
||||
|
||||
|
||||
|
||||
// slow down a bit save position pace
|
||||
var slowSave = this.debounce(() => {
|
||||
if(!this.parameters.machineScroll) {
|
||||
this.saveAmountScrolled();
|
||||
}
|
||||
}, 100); // save frequency
|
||||
|
||||
setTimeout(function(){
|
||||
window.addEventListener('scroll', slowSave);
|
||||
}, 1000); // wait a bit before starting position save
|
||||
|
||||
}
|
||||
|
||||
getDocHeight() {
|
||||
var D = document;
|
||||
return Math.max(
|
||||
D.body.scrollHeight, D.documentElement.scrollHeight,
|
||||
D.body.offsetHeight, D.documentElement.offsetHeight,
|
||||
D.body.clientHeight, D.documentElement.clientHeight
|
||||
)
|
||||
}
|
||||
|
||||
saveAmountScrolled(){
|
||||
var scrollArray = [];
|
||||
var scrollTop = window.pageYOffset || (document.documentElement || document.body.parentNode || document.body).scrollTop
|
||||
if (!this.parameters.machineScroll) {
|
||||
var scrollLeft = window.pageXOffset || (document.documentElement || document.body.parentNode || document.body).scrollLeft
|
||||
scrollArray.push({ X: Math.round(scrollLeft), Y: Math.round(scrollTop) });
|
||||
//console.log("Saved ", scrollArray);
|
||||
localStorage['reloadInPlace-' + this.fileTitle] = JSON.stringify(scrollArray);
|
||||
}
|
||||
}
|
||||
|
||||
isBlur(){
|
||||
// Apply a blur effect if scroll blurring is enabled
|
||||
if (this.isScrollBlured) {
|
||||
var styleEl = document.createElement('style');
|
||||
styleEl.setAttribute("data-reload-in-place", true)
|
||||
document.head.appendChild(styleEl);
|
||||
this.styleSheet = styleEl.sheet;
|
||||
this.styleSheet.insertRule('.pagedjs_pages { filter: blur(3px); }', 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
retrievePosition(){
|
||||
// Retrieve saved scroll data from localStorage
|
||||
var savedData = localStorage.getItem('reloadInPlace-' + this.fileTitle);
|
||||
|
||||
if (savedData) {
|
||||
// Parse the saved data to get the scroll positions
|
||||
var scrollArray = JSON.parse(savedData);
|
||||
this.scrollTop = scrollArray[0].Y;
|
||||
this.scrollLeft = scrollArray[0].X;
|
||||
} else {
|
||||
// Default scroll positions if no saved data is found
|
||||
this.scrollTop = 0;
|
||||
this.scrollLeft = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adjusts the scroll position of the window based on saved data.
|
||||
* This function handles scrolling behavior when the document height changes,
|
||||
* ensuring the view returns to a previously saved scroll position or the bottom of the document.
|
||||
*
|
||||
* @param {Object} _ - ReloadInPlace scope
|
||||
*/
|
||||
moveFast() {
|
||||
// Set the machine scroll flag to true
|
||||
this.parameters.machineScroll = true;
|
||||
|
||||
this.retrievePosition()
|
||||
|
||||
// Get the window height
|
||||
var winheight = window.innerHeight || (document.documentElement || document.body).clientHeight;
|
||||
|
||||
let _ = this
|
||||
|
||||
// Set up an interval to adjust the scroll position
|
||||
_.currentInterval = setInterval(() => {
|
||||
// Get the current document height
|
||||
_.docheight = _.getDocHeight();
|
||||
|
||||
// Check if the saved scroll position is beyond the current document height
|
||||
if ( _.scrollTop > 0 && _.scrollTop > _.docheight - winheight && !_.parameters.cssPageWeaverEnd) {
|
||||
// Scroll to the bottom of the document
|
||||
window.scrollTo(_.scrollLeft, _.docheight, _.scrollBehavior);
|
||||
} else {
|
||||
// Scroll to the saved position
|
||||
window.scrollTo(_.scrollLeft, _.scrollTop, _.scrollBehavior);
|
||||
|
||||
// Clear interval
|
||||
clearInterval(_.currentInterval);
|
||||
|
||||
// set a timeout to finalize the scroll position
|
||||
setTimeout(function () {
|
||||
window.scrollTo(_.scrollLeft, _.scrollTop, _.scrollBehavior);
|
||||
|
||||
// Reset the machine scroll flag
|
||||
_.parameters.machineScroll = false;
|
||||
|
||||
// Remove the blur effect if it was applied
|
||||
if (_.isScrollBlured) {
|
||||
_.styleSheet.deleteRule(0);
|
||||
}
|
||||
}, 50); // Delay to start
|
||||
}
|
||||
}, 50); // Refresh frequency
|
||||
}
|
||||
|
||||
debounce(func, wait, immediate) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (!immediate) func.apply(context, args);
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) func.apply(context, args);
|
||||
};
|
||||
};
|
||||
}
|
||||
1
public/csspageweaver/plugins/spread/.gitignore
vendored
Normal file
1
public/csspageweaver/plugins/spread/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
15
public/csspageweaver/plugins/spread/config.json
Normal file
15
public/csspageweaver/plugins/spread/config.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "Spread",
|
||||
"description": "",
|
||||
"version": "1.0",
|
||||
"ui": {
|
||||
"title": "Screen view",
|
||||
"description": "This Toogle single page or board view",
|
||||
"toggle": false,
|
||||
"template": "spread.html"
|
||||
},
|
||||
"stylesheet": "spread.css",
|
||||
"hook": "spread-hook.js",
|
||||
"script": "spread-ui.js"
|
||||
|
||||
}
|
||||
25
public/csspageweaver/plugins/spread/spread-hook.js
Normal file
25
public/csspageweaver/plugins/spread/spread-hook.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class nrbPages extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
}
|
||||
|
||||
afterPageLayout(pageElement, page, breakToken) {
|
||||
|
||||
let nbrSpan = document.querySelector("#nrb-pages");
|
||||
let pagesDocument = document.querySelectorAll(".pagedjs_page");
|
||||
if (nbrSpan) {
|
||||
nbrSpan.innerHTML = pagesDocument.length;
|
||||
}
|
||||
}
|
||||
|
||||
afterRendered(pages){
|
||||
let nbrSpan = document.querySelector("#nrb-pages");
|
||||
if (nbrSpan) {
|
||||
nbrSpan.innerHTML = pages.length;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
38
public/csspageweaver/plugins/spread/spread-ui.js
Normal file
38
public/csspageweaver/plugins/spread/spread-ui.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* @name Spread
|
||||
* @author Julie Blanc <contact@julie-blanc.fr>
|
||||
* @see { @link https://gitlab.com/csspageweaver/plugins/ }
|
||||
*/
|
||||
|
||||
export default function spreadEvents(){
|
||||
|
||||
const body = cssPageWeaver.ui.body
|
||||
const fileTitle = cssPageWeaver.docTitle;
|
||||
const toggleInput = document.querySelector('#spread-toggle-button')
|
||||
|
||||
/* SPREAD ----------------------------------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------------------------------------------*/
|
||||
/* Toggle spread or recto-verso */
|
||||
let preference = localStorage.getItem('spreadToggle' + fileTitle);
|
||||
|
||||
|
||||
if(preference == "spread"){
|
||||
body.classList.remove('no-spread');
|
||||
toggleInput.checked = true
|
||||
}else if(preference == "no-spread"){
|
||||
body.classList.add('no-spread');
|
||||
toggleInput.checked = false
|
||||
}
|
||||
document.querySelector("#label-spread-toggle").addEventListener("click", (e) => {
|
||||
//e.preventDefault()
|
||||
|
||||
if(body.classList.contains("no-spread")){
|
||||
body.classList.remove('no-spread');
|
||||
localStorage.setItem('spreadToggle' + fileTitle, 'spread');
|
||||
}else{
|
||||
body.classList.add('no-spread');
|
||||
localStorage.setItem('spreadToggle' + fileTitle, 'no-spread');
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
29
public/csspageweaver/plugins/spread/spread.css
Normal file
29
public/csspageweaver/plugins/spread/spread.css
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
.no-spread .pagedjs_pages {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_first_page {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_page {
|
||||
margin: 0 auto;
|
||||
margin-top: 10mm;
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_left_page{
|
||||
width: calc(var(--pagedjs-bleed-left) + var(--pagedjs-pagebox-width) + var(--pagedjs-bleed-left))!important;
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-crop{
|
||||
border-color: var(--pagedjs-crop-color);
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_left_page .pagedjs_bleed-right .pagedjs_marks-middle{
|
||||
width: var(--pagedjs-cross-size)!important;
|
||||
}
|
||||
|
||||
.no-spread .pagedjs_right_page{
|
||||
left: 0;
|
||||
}
|
||||
61
public/csspageweaver/plugins/spread/spread.html
Normal file
61
public/csspageweaver/plugins/spread/spread.html
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<input type="checkbox" id="spread-toggle-button" name="spread-toggle">
|
||||
<div class="buttons-group">
|
||||
|
||||
<label for="spread-toggle-button" id="label-spread-toggle">
|
||||
<span id="button-spread" class="button">
|
||||
<svg width="100%" height="100%" viewBox="0 0 480 480" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-4,-1084)">
|
||||
<g id="spread-bis" serif:id="spread bis" transform="matrix(0.997921,0,0,1.00209,2.00416,1083)">
|
||||
<rect x="2" y="1" width="481" height="479" style="fill:none;" />
|
||||
<g transform="matrix(0.88709,0,0,0.842432,44.9417,123.556)">
|
||||
<path
|
||||
d="M249.88,336.193L249.88,282.887C249.88,280.925 251.397,279.334 253.269,279.334L275.731,279.334C277.603,279.334 279.12,280.925 279.12,282.887L279.12,336.193L463.88,336.193L463.88,20.807L396.102,20.807C394.23,20.807 392.713,19.216 392.713,17.253L392.713,-5.253C392.713,-7.216 394.23,-8.807 396.102,-8.807L478,-8.807C485.798,-8.807 492.12,-2.178 492.12,6L492.12,351C492.12,359.178 485.798,365.807 478,365.807L265,365.807C264.833,365.807 264.666,365.804 264.501,365.798L264.491,365.798C264.328,365.804 264.164,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,282.887C36.88,280.925 38.397,279.334 40.269,279.334L61.731,279.334C63.603,279.334 65.12,280.925 65.12,282.887L65.12,336.193L247.905,336.193L249.88,336.193Z" />
|
||||
</g>
|
||||
<g transform="matrix(1.00208,0,0,0.997917,8.0125,46.7815)">
|
||||
<g transform="matrix(0.885246,0,0,0.844191,-38.1475,9.93485)">
|
||||
<path
|
||||
d="M278.12,6L278.12,351C278.12,359.178 271.798,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,6C36.88,-2.178 43.202,-8.807 51,-8.807L264,-8.807C271.798,-8.807 278.12,-2.178 278.12,6ZM65.12,336.193L249.88,336.193L249.88,20.807L67.095,20.807L65.12,20.807L65.12,330.717L65.12,336.193Z" />
|
||||
</g>
|
||||
<g transform="matrix(0.885246,0,0,0.844191,151.295,9.93485)">
|
||||
<path
|
||||
d="M278.12,6L278.12,351C278.12,359.178 271.798,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,6C36.88,-2.178 43.202,-8.807 51,-8.807L264,-8.807C271.798,-8.807 278.12,-2.178 278.12,6ZM249.88,336.193L249.88,20.807L67.095,20.807L65.12,20.807L65.12,336.193L247.905,336.193L249.88,336.193Z" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</span>
|
||||
<span id="button-recto" class="button">
|
||||
<svg width="100%" height="100%" viewBox="0 0 480 480" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,-557,-1103)">
|
||||
<g id="recto-verso-bis" serif:id="recto-verso bis"
|
||||
transform="matrix(0.997921,0,0,1.00209,555.004,1102)">
|
||||
<rect x="2" y="1" width="481" height="479" style="fill:none;" />
|
||||
<g transform="matrix(0.88709,0,0,0.842432,184.453,157.485)">
|
||||
<path
|
||||
d="M249.88,336.193L249.88,20.807L183.231,20.807C181.36,20.807 179.843,19.216 179.843,17.253L179.843,-5.253C179.843,-7.216 181.36,-8.807 183.231,-8.807L264,-8.807C271.798,-8.807 278.12,-2.178 278.12,6L278.12,351C278.12,359.178 271.798,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,281.703C36.88,279.74 38.397,278.149 40.269,278.149L61.731,278.149C63.603,278.149 65.12,279.74 65.12,281.703L65.12,336.193L247.905,336.193L249.88,336.193Z" />
|
||||
</g>
|
||||
<g transform="matrix(0.88709,0,0,0.842432,103.284,89.6269)">
|
||||
<path
|
||||
d="M249.88,336.193L249.88,20.807L182.102,20.807C180.23,20.807 178.713,19.216 178.713,17.253L178.713,-5.253C178.713,-7.216 180.23,-8.807 182.102,-8.807L264,-8.807C271.798,-8.807 278.12,-2.178 278.12,6L278.12,351C278.12,359.178 271.798,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,282.887C36.88,280.925 38.397,279.334 40.269,279.334L61.731,279.334C63.603,279.334 65.12,280.925 65.12,282.887L65.12,336.193L247.905,336.193L249.88,336.193Z" />
|
||||
</g>
|
||||
<g transform="matrix(0.88709,0,0,0.842432,21.1135,22.7665)">
|
||||
<path
|
||||
d="M278.12,6L278.12,351C278.12,359.178 271.798,365.807 264,365.807L51,365.807C43.202,365.807 36.88,359.178 36.88,351L36.88,6C36.88,-2.178 43.202,-8.807 51,-8.807L264,-8.807C271.798,-8.807 278.12,-2.178 278.12,6ZM249.88,336.193L249.88,20.807C228.051,20.807 106.85,20.807 65.12,20.807L65.12,336.193L247.905,336.193L249.88,336.193Z" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
</span>
|
||||
|
||||
</label>
|
||||
|
||||
<p class="force-right">
|
||||
<span id="nrb-pages" >xx</span> pages
|
||||
</p>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue