Initial commit
This commit is contained in:
commit
388079e6bb
1108 changed files with 330121 additions and 0 deletions
1
assets/csspageweaver/plugins/marginNotes/.gitignore
vendored
Normal file
1
assets/csspageweaver/plugins/marginNotes/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.DS_Store
|
||||
114
assets/csspageweaver/plugins/marginNotes/README.md
Normal file
114
assets/csspageweaver/plugins/marginNotes/README.md
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# Plugin for sidenotes
|
||||
|
||||
This plugin proposes a script for sidenotes in Paged.js.
|
||||
|
||||
The plugin creates sidenotes from `span` elements in the text flow. It can be combined with 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.
|
||||
|
||||
Note: The plugin moves notes if they overlap or if the last note overflows at the end of the page.
|
||||
|
||||
## How to use the plugin
|
||||
|
||||
|
||||
Add this folder to `csspageweaver/plugins/`.
|
||||
|
||||
Call the plugin in `csspageweaver/manifest.json`:
|
||||
|
||||
```json
|
||||
"plugins": [
|
||||
"sidenotes",
|
||||
// other plugins ...
|
||||
],
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
In `manifest.json`, you can modify/add some parameters:
|
||||
|
||||
```json
|
||||
"plugins":{
|
||||
"sidenotes"
|
||||
},
|
||||
"pluginsParameters":{
|
||||
"sidenotes": {
|
||||
"selector": ".sidenote",
|
||||
"position": "outside",
|
||||
"reset": ".chapter",
|
||||
"align": ".chapter p:first-of-type"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
All the parameters are optional.
|
||||
|
||||
- `selector` → CSS selector for the note element (must be inline in the HTML), default is `.sidenote`
|
||||
- `position` → Specifies the position of sidenotes relative to the main text: options are "outside", "inside", "left", "right".
|
||||
- 'outside': the left pages notes positonned on the margin left and the right pages notes on the margin right. This is the default value.
|
||||
- 'inside': the left pages notes positonned on the margin right and the right pages notes on the margin left.
|
||||
- 'left': the notes of both pages are positinoned on the margin left.
|
||||
- 'right': the notes of both pages are positinoned on the margin left.
|
||||
- `reset` → CSS selector where you want reset note counter
|
||||
- `align` → Element to align the first note of the page to, if present on the 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="sidenote">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 sidenotes plugin in the `manifest.json`:
|
||||
|
||||
|
||||
```json
|
||||
"plugins": [
|
||||
"inline_notes",
|
||||
"sidenotes",
|
||||
// other plugins ...
|
||||
],
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Styling notes
|
||||
|
||||
By default, the width of the notes is set on the corresponding margin where the notes are positioned. You can change this width by adjusting the `padding-left` and `padding-right` of your note elements.
|
||||
|
||||
To apply specific style depending on the left or right pages, uses the following CSS (where `sidenote` is the class of your notes):
|
||||
|
||||
```CSS
|
||||
.pagedjs_left_page .sidenote {
|
||||
padding-left: 40px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.pagedjs_right_page .sidenote {
|
||||
padding-left: 20px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
```
|
||||
|
||||
It's possible to change the styles of call notes and marker notes directly in your stylesheet like in the following code:
|
||||
|
||||
```CSS
|
||||
.pagedjs_sidenote_call{
|
||||
color: blue;
|
||||
}
|
||||
.pagedjs_sidenote_marker{
|
||||
color: violet;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Possible improvement
|
||||
|
||||
|
||||
Currently, there is no way to break a note element across two pages in Paged.js. If all the sidenotes on a page don't fit, the overflowing sidenotes are pushed to the next page. Implementing a feature to split notes across pages would enhance the layout flexibility.
|
||||
8
assets/csspageweaver/plugins/marginNotes/config.json
Normal file
8
assets/csspageweaver/plugins/marginNotes/config.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "Margin Notes",
|
||||
"description": "Create margin notes with call & markers",
|
||||
"author": ["Julie Blanc et Sarah Garcin"],
|
||||
"licence": "MIT",
|
||||
"version": "1.0",
|
||||
"hook": "marginNotes.js"
|
||||
}
|
||||
260
assets/csspageweaver/plugins/marginNotes/marginNotes.js
Normal file
260
assets/csspageweaver/plugins/marginNotes/marginNotes.js
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
import { Handler } from '/csspageweaver/lib/paged.esm.js';
|
||||
|
||||
export default class marginNotes extends Handler {
|
||||
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
this.parameters = cssPageWeaver.features.marginNotes.parameters;
|
||||
this.notesClass = this.parameters?.selector || ".sidenote";
|
||||
this.position = this.parameters?.position || "outside";
|
||||
this.reset = this.parameters?.reset;
|
||||
this.marker = this.parameters?.marker || ". ";
|
||||
}
|
||||
|
||||
beforeParsed(content) {
|
||||
let classNotes = this.notesClass;
|
||||
let marker = this.marker;
|
||||
if (typeof this.reset === "string" && this.reset.trim() !== "") {
|
||||
let sections = content.querySelectorAll(this.reset);
|
||||
sections.forEach(function (section) {
|
||||
addCallAndMarker(section, classNotes, marker);
|
||||
});
|
||||
} else {
|
||||
addCallAndMarker(content, classNotes, marker);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* NOTE FLOAT ---------------------------------------------------------------------------------- */
|
||||
|
||||
let positionRight = 'left: calc(var(--pagedjs-pagebox-width) - var(--pagedjs-margin-left) - var(--pagedjs-margin-right) - 1px); width: var(--pagedjs-margin-right);';
|
||||
let positionLeft = 'left: calc(var(--pagedjs-margin-left)*-1 - 1px); width: var(--pagedjs-margin-left);'
|
||||
|
||||
let notePosition;
|
||||
|
||||
switch (this.position) {
|
||||
case 'inside':
|
||||
notePosition = '.pagedjs_left_page ' + classNotes + '{' + positionRight + '} \
|
||||
.pagedjs_right_page ' + classNotes + '{' + positionLeft + '}';
|
||||
break;
|
||||
case 'left':
|
||||
notePosition = '.pagedjs_left_page ' + classNotes + '{' + positionLeft + '} \
|
||||
.pagedjs_right_page ' + classNotes + '{' + positionLeft + '}';
|
||||
break;
|
||||
case 'right':
|
||||
notePosition = '.pagedjs_left_page ' + classNotes + '{' + positionRight + '} \
|
||||
.pagedjs_right_page ' + classNotes + '{' + positionRight + '}';
|
||||
break;
|
||||
default:
|
||||
notePosition = '.pagedjs_left_page ' + classNotes + '{' + positionLeft + '} \
|
||||
.pagedjs_right_page ' + classNotes + '{' + positionRight + '}';
|
||||
}
|
||||
|
||||
|
||||
/* SPECIFIC CSS ---------------------------------------------------------------------------------- */
|
||||
|
||||
addcss('\
|
||||
' + classNotes + '{\
|
||||
position: absolute;\
|
||||
text-align-last: initial;\
|
||||
box-sizing: border-box;\
|
||||
}' + notePosition);
|
||||
|
||||
|
||||
} /* end beforeParsed*/
|
||||
|
||||
|
||||
afterPageLayout(pageElement, page, breakToken) {
|
||||
let classNotes = this.notesClass;
|
||||
let marker = this.marker;
|
||||
let notes = pageElement.querySelectorAll(classNotes);
|
||||
let noteOverflow = false;
|
||||
|
||||
let notesHeightAll = [];
|
||||
|
||||
if (typeof (notes) != 'undefined' && notes != null && notes.length != 0) {
|
||||
|
||||
for (let n = 0; n < notes.length; ++n) {
|
||||
// Display notes of the page
|
||||
notes[n].style.display = "inline-block";
|
||||
// Add height of the notes to array notesHeightAll
|
||||
let noteHeight = notes[n].offsetHeight;
|
||||
notesHeightAll.push(noteHeight);
|
||||
// Add margins of the notes to array notesHeightAll
|
||||
if (n >= 1) {
|
||||
let margins = biggestMargin(notes[n - 1], notes[n]);
|
||||
notesHeightAll.push(margins);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* FIT PAGE ------------------------------------------------------------------------------------- */
|
||||
|
||||
// Calculate if all notes fit on the page;
|
||||
let reducer = (accumulator, currentValue) => accumulator + currentValue;
|
||||
let allHeight = notesHeightAll.reduce(reducer);
|
||||
let maxHeight = pageElement.querySelectorAll(".pagedjs_page_content")[0].offsetHeight;
|
||||
|
||||
if (allHeight > maxHeight) {
|
||||
|
||||
/* IF DOESN'T FIT ----------------------------------------------------------------------------- */
|
||||
|
||||
// positions all the notes one after the other starting from the top
|
||||
notes[0].style.top = parseInt(window.getComputedStyle(notes[0]).marginBottom, 10) * -1 + "px";
|
||||
for (let a = 1; a < notes.length; ++a) {
|
||||
let notePrev = notes[a - 1];
|
||||
let newMargin = biggestMargin(notePrev, notes[a]);
|
||||
let newTop = notePrev.offsetTop + notePrev.offsetHeight - marginNoteTop(notes[a]) + newMargin;
|
||||
notes[a].style.top = newTop + "px";
|
||||
}
|
||||
// alert
|
||||
let pageNumber = pageElement.dataset.pageNumber;
|
||||
alert("Rendering issue \n ☞ A marginal note overflow on page " + pageNumber + " (this is because there is too many on this page and paged.js can't breaks notes between pages for now.)");
|
||||
noteOverflow = true;
|
||||
|
||||
} else {
|
||||
|
||||
/* PUSH DOWN ---------------------------------------------------- */
|
||||
for (let i = 0; i < notes.length; ++i) {
|
||||
if (i >= 1) {
|
||||
let noteTop = notes[i].offsetTop;
|
||||
let notePrev = notes[i - 1];
|
||||
let newMargin = biggestMargin(notes[i], notePrev);
|
||||
let notePrevBottom = notePrev.offsetTop - marginNoteTop(notePrev) + notePrev.offsetHeight + newMargin;
|
||||
// Push down the note to bottom if it's over the previous one
|
||||
if (notePrevBottom > noteTop) {
|
||||
notes[i].style.top = notePrevBottom + "px";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PUSH UP ---------------------------------------------- */
|
||||
|
||||
// Height of the page content
|
||||
let contentHeight = pageElement.querySelectorAll(".pagedjs_page_content")[0].querySelectorAll("div")[0].offsetHeight;
|
||||
|
||||
// Check if last note overflow
|
||||
let nbrLength = notes.length - 1;
|
||||
let lastNote = notes[nbrLength];
|
||||
let lastNoteHeight = lastNote.offsetHeight + marginNoteTop(lastNote);
|
||||
let noteBottom = lastNote.offsetTop + lastNoteHeight;
|
||||
|
||||
if (noteBottom > contentHeight) {
|
||||
|
||||
// Push up the last note
|
||||
lastNote.style.top = contentHeight - lastNoteHeight + "px";
|
||||
|
||||
// Push up previous note(s) if if it's over the note
|
||||
for (let i = nbrLength; i >= 1; --i) {
|
||||
let noteLastTop = notes[i].offsetTop;
|
||||
let notePrev = notes[i - 1];
|
||||
let notePrevHeight = notePrev.offsetHeight;
|
||||
let newMargin = biggestMargin(notePrev, notes[i]);
|
||||
let notePrevBottom = notePrev.offsetTop + notePrev.offsetHeight + newMargin;
|
||||
if (notePrevBottom > noteLastTop) {
|
||||
notePrev.style.top = notes[i].offsetTop - marginNoteTop(notePrev) - notePrevHeight - newMargin + "px";
|
||||
}
|
||||
}
|
||||
|
||||
} /* end push up */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}/* end afterPageLayout*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FUNCTIONS --------------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
|
||||
function addCallAndMarker(section, classNotes, marker){
|
||||
let notes = section.querySelectorAll(classNotes);
|
||||
for (let i = 0; i < notes.length; ++i) {
|
||||
|
||||
let num = i + 1;
|
||||
|
||||
// Add call notes
|
||||
var spanCall = document.createElement("span");
|
||||
spanCall.classList.add("note-call");
|
||||
spanCall.classList.add("note-call_" + classNotes);
|
||||
spanCall.dataset.noteCall = classNotes + '-' + num;
|
||||
spanCall.innerHTML = num;
|
||||
notes[i].parentNode.insertBefore(spanCall, notes[i]);
|
||||
|
||||
|
||||
// Add marker notes
|
||||
var spanMarker = document.createElement("span");
|
||||
spanMarker.classList.add("note-marker");
|
||||
spanMarker.classList.add("note-marker_" + classNotes);
|
||||
spanMarker.dataset.noteMarker = classNotes + '-' + num;
|
||||
spanMarker.innerHTML = num + marker;
|
||||
notes[i].prepend(spanMarker);
|
||||
|
||||
|
||||
// Hide notes to avoid rendering problems
|
||||
notes[i].style.display = "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARGINS
|
||||
|
||||
function marginNoteTop(elem) {
|
||||
let marginTop = parseInt(window.getComputedStyle(elem).marginTop, 10)
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
function marginNoteBottom(elem) {
|
||||
let marginBottom = parseInt(window.getComputedStyle(elem).marginBottom, 10)
|
||||
return marginBottom;
|
||||
}
|
||||
|
||||
function biggestMargin(a, b) {
|
||||
let margin;
|
||||
let marginBottom = marginNoteBottom(a);
|
||||
let marginTop = marginNoteTop(b);
|
||||
if (marginBottom > marginTop) {
|
||||
margin = marginBottom;
|
||||
} else {
|
||||
margin = marginTop;
|
||||
}
|
||||
return margin;
|
||||
}
|
||||
|
||||
|
||||
// ADD CSS
|
||||
|
||||
function addcss(css) {
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
var s = document.createElement('style');
|
||||
s.setAttribute('type', 'text/css');
|
||||
if (s.styleSheet) { // IE
|
||||
s.styleSheet.cssText = css;
|
||||
} else {// the world
|
||||
s.appendChild(document.createTextNode(css));
|
||||
}
|
||||
head.appendChild(s);
|
||||
}
|
||||
|
||||
|
||||
// CAMEL CLASS NOTE
|
||||
|
||||
function toCamelClassNote(elem) {
|
||||
let splitClass = elem.split("-");
|
||||
if (splitClass.length > 1) {
|
||||
for (let s = 1; s < splitClass.length; ++s) {
|
||||
let strCapilize = splitClass[s].charAt(0).toUpperCase() + splitClass[s].slice(1)
|
||||
splitClass[s] = strCapilize;
|
||||
}
|
||||
}
|
||||
let reducer = (accumulator, currentValue) => accumulator + currentValue;
|
||||
let classCamel = splitClass.reduce(reducer);
|
||||
return classCamel;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue