initial commit

This commit is contained in:
Julie Blanc 2026-01-10 18:33:22 +01:00
commit 21711bd5dd
253 changed files with 78415 additions and 0 deletions

View file

@ -0,0 +1 @@
.DS_Store

View 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 PageWeaver 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 PageWeaver**
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>
```
Dont 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

View file

@ -0,0 +1,8 @@
{
"name": "Float PAge",
"description": "",
"author": ["Julie Blanc"],
"license": "MIT License",
"version": "1.0",
"hook": "floatPage.js"
}

View 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();
}
// NEXTPAGE (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;
}

View 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>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>

View 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>

View 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>

View 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>