tests mise en page
|
|
@ -49,11 +49,11 @@ h3{
|
|||
font-size: 1em;
|
||||
}
|
||||
|
||||
h2 + h3{
|
||||
/*h2 + h3{
|
||||
margin-top: 0.5em;
|
||||
opacity: 0.8;
|
||||
font-weight: normal;
|
||||
}
|
||||
}*/
|
||||
|
||||
h5, h6{
|
||||
font-size: var(--textSize);
|
||||
|
|
@ -155,6 +155,7 @@ figure[data-crop="false"] img {
|
|||
}
|
||||
|
||||
.print-image .print-red{
|
||||
position: relative;
|
||||
background: var(--rouge);
|
||||
}
|
||||
|
||||
|
|
@ -331,3 +332,6 @@ header .mobile__menu_btn .rotate-bottom {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -436,13 +436,13 @@ figure img.cover{ object-fit: cover; max-width: none; width:100%; height:100%;}
|
|||
}
|
||||
|
||||
/* -------- FOOTNOTES ---------- */
|
||||
span.footnote {
|
||||
/*span.footnote {
|
||||
float: footnote;
|
||||
}
|
||||
|
||||
.footnote::footnote-call {
|
||||
content: counter(footnote, decimal) " ";
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,53 +2,346 @@
|
|||
|
||||
/* --------- Paramètres de base ---------- */
|
||||
@page{
|
||||
size: 165mm 240mm
|
||||
size: 165mm 240mm;
|
||||
/* bleed: 6mm;
|
||||
marks: crop;*/
|
||||
}
|
||||
|
||||
@page :left {
|
||||
margin: 16mm 25mm 10mm 10mm;
|
||||
@top-left-corner {
|
||||
margin: 20mm 36mm 18mm 12mm;
|
||||
/* @top-left-corner {
|
||||
content: counter(page);
|
||||
font-size: 7pt;
|
||||
font-size: 11pt;
|
||||
text-align: center;
|
||||
font-family: var(--fontFamily);
|
||||
}
|
||||
font-family: "Bilzig Trial";
|
||||
}*/
|
||||
@top-center{
|
||||
content: string(title);
|
||||
font-size: 7pt;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
width: 105%;
|
||||
margin-left: 0%;
|
||||
font-family: var(--fontFamily);
|
||||
content: "D6cor > essai";
|
||||
font-size: 8pt;
|
||||
color: var(--bleu);
|
||||
text-align: left;
|
||||
margin-top: 4mm;
|
||||
/*text-align: center;*/
|
||||
/*text-transform: uppercase;*/
|
||||
/*width: 105%;*/
|
||||
/*margin-left: 0%;*/
|
||||
}
|
||||
@bottom-left{
|
||||
font-family: var(--fontFamily);
|
||||
content: counter(page);
|
||||
font-size: 11pt;
|
||||
color: var(--vert);
|
||||
margin-top:-5mm;
|
||||
margin-left: 8mm;
|
||||
}
|
||||
}
|
||||
|
||||
@page :right {
|
||||
margin: 16mm 10mm 10mm 25mm;
|
||||
@top-right-corner {
|
||||
margin: 20mm 12mm 18mm 36mm;
|
||||
/*@top-right-corner {
|
||||
content: counter(page);
|
||||
font-size: 7pt;
|
||||
text-align: center;
|
||||
font-family: var(--fontFamily);
|
||||
}
|
||||
}*/
|
||||
@top-center{
|
||||
content: string(chapter);
|
||||
font-size: 7pt;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
width: 105%;
|
||||
margin-left: -9%;
|
||||
font-family: var(--fontFamily);
|
||||
font-size: 8pt;
|
||||
color: var(--bleu);
|
||||
text-align: right;
|
||||
margin-top: 4mm;
|
||||
}
|
||||
@bottom-right{
|
||||
font-family: var(--fontFamily);
|
||||
content: counter(page);
|
||||
font-size: 11pt;
|
||||
color: var(--vert);
|
||||
margin-top:-5mm;
|
||||
margin-right: 8mm;
|
||||
}
|
||||
}
|
||||
|
||||
.chapter{
|
||||
break-before: right;
|
||||
counter-reset: callNote_marginNote markerNote_marginNote;
|
||||
}
|
||||
|
||||
.chapter h2{
|
||||
page-break-after: always;
|
||||
/* borders */
|
||||
.pagedjs_margin-top-left-corner-holder:before{
|
||||
content: " ";
|
||||
background: var(--vert);
|
||||
width: 100%;
|
||||
height: var(--border);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.pagedjs_margin-left:before{
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top:0;
|
||||
background: var(--bleu);
|
||||
width: var(--border);
|
||||
height: var(--pagedjs-height);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.pagedjs_right_page .pagedjs_margin-left:before{
|
||||
content: none;
|
||||
}
|
||||
|
||||
.pagedjs_margin-right:after{
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top:0;
|
||||
right: 0;
|
||||
background: var(--bleu);
|
||||
width: var(--border);
|
||||
height: var(--pagedjs-height);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.pagedjs_left_page .pagedjs_margin-right:after{
|
||||
content: none;
|
||||
}
|
||||
|
||||
.pagedjs_margin-bottom:after{
|
||||
content: " ";
|
||||
background: var(--rouge);
|
||||
width: 100%;
|
||||
height: var(--border);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ---- INTERPAGES ------ */
|
||||
|
||||
.interpage figure{
|
||||
height: calc(var(--pagedjs-height) - (var(--border) * 2)) !important;
|
||||
margin-top: calc(var(--border) + 3mm);
|
||||
}
|
||||
|
||||
/* ---- PAGE DE TITRE ------ */
|
||||
|
||||
.chapter-title{
|
||||
page: chapterTitle;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@page chapterTitle{
|
||||
background: var(--bleu);
|
||||
margin: 12mm 0mm;
|
||||
@top-left-corner {content: none;}
|
||||
@top-left {content: none;}
|
||||
@top-center {content: none;}
|
||||
@top-right {content: none;}
|
||||
@top-right-corner {content: none;}
|
||||
@left-top {content: none;}
|
||||
@left-middle {content: none;}
|
||||
@left-bottom {content: none;}
|
||||
@right-top {content: none;}
|
||||
@right-middle {content: none;}
|
||||
@right-bottom {content: none;}
|
||||
@bottom-left-corner {content: none;}
|
||||
@bottom-left {content: none;}
|
||||
@bottom-center {content: none;}
|
||||
@bottom-right {content: none;}
|
||||
@bottom-right-corner {content: none;}
|
||||
}
|
||||
|
||||
.chapter-title h2,
|
||||
.chapter-title h3,
|
||||
.chapter-title p {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
color: #FFF;
|
||||
font-size: var(--textSize);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ascii-fill : pas de flex:1, hauteur fixée par JS */
|
||||
.ascii-fill {
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
line-height: 1.5;
|
||||
flex-shrink: 0;
|
||||
color: #FFF;
|
||||
font-size: var(--textSize);
|
||||
text-align: center;
|
||||
font-family: var(--fontFamily);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chapter-title,
|
||||
.biographie {
|
||||
font-family: var(--fontFamily);
|
||||
color: #FFF;
|
||||
text-align: center;
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
/*padding: 30px;*/
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: var(--fontFamily);
|
||||
font-size: var(--textSize);
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* ------- TITLES ------- */
|
||||
.chapter-content h3{
|
||||
/*width: calc(var(--pagedjs-width) - 12mm);*/
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.chapter-content h3:before{
|
||||
content: "+------------------------------------------------+";
|
||||
display: block;
|
||||
margin-bottom: 2mm;
|
||||
}
|
||||
|
||||
.chapter-content h3:after{
|
||||
content: "+------------------------------------------------+";
|
||||
display: block;
|
||||
margin-top: 1mm;
|
||||
margin-bottom: 1mm;
|
||||
}
|
||||
|
||||
.pagedjs_right_page .chapter-content h3{
|
||||
/*margin-left: calc((var(--pagedjs-margin-left) - 16mm) * -1);*/
|
||||
}
|
||||
|
||||
.chapter-content h4{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.chapter-content h4:before{
|
||||
content: "> > > > > > < < < < < < \a > > > > ";
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.chapter-content h4:after{
|
||||
content: " < < < < \a > > > > > > < < < < < <";
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* -------- IMAGES ------- */
|
||||
.float-image{
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
width: auto !important;
|
||||
float: right; /* ou left selon la position souhaitée */
|
||||
clear: right;
|
||||
width: 45% !important;
|
||||
|
||||
margin-top: 2mm;
|
||||
|
||||
}
|
||||
|
||||
.pagedjs_left_page .float-image{
|
||||
float: right;
|
||||
margin-right: calc(var(--pagedjs-margin-right) / 2 * -1);
|
||||
margin-left: 5mm;
|
||||
}
|
||||
|
||||
.pagedjs_right_page .float-image{
|
||||
float: left;
|
||||
margin-left: calc(var(--pagedjs-margin-left) / 2 * -1);
|
||||
margin-right: 5mm;
|
||||
}
|
||||
|
||||
.float-image figcaption{
|
||||
position: relative;
|
||||
color: var(--bleu);
|
||||
font-size: 8.5pt;
|
||||
font-family: "Bilzig Trial";
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.float-image figcaption p{
|
||||
color: var(--bleu);
|
||||
font-size: 8.5pt;
|
||||
font-family: "Bilzig Trial";
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* ------- NOTES ------- */
|
||||
|
||||
.margin-note{
|
||||
font-size: 8.5pt;
|
||||
line-height: 1.41;
|
||||
font-family: "Bilzig Trial";
|
||||
color: var(--bleu);
|
||||
text-align: left;
|
||||
position: relative !important;
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
width: auto !important;
|
||||
float: right; /* ou left selon la position souhaitée */
|
||||
clear: right;
|
||||
|
||||
/* Largeur de la note dans le corps du texte */
|
||||
width: 45% !important;
|
||||
|
||||
padding: 1mm 3mm 0mm;
|
||||
|
||||
}
|
||||
|
||||
.pagedjs_left_page .margin-note {
|
||||
float: right;
|
||||
margin-right: calc(var(--pagedjs-margin-right) / 2 * -1);
|
||||
padding: 1mm 0mm 0mm 3mm;
|
||||
}
|
||||
|
||||
.pagedjs_right_page .margin-note {
|
||||
float: left;
|
||||
margin-left: calc(var(--pagedjs-margin-left) / 2 * -1);
|
||||
text-align: right;
|
||||
padding: 1mm 3mm 0mm 0mm;
|
||||
}
|
||||
|
||||
.note-call_margin-note::before{
|
||||
content: "{";
|
||||
margin-right: 0.5mm;
|
||||
}
|
||||
|
||||
.note-call_margin-note::after{
|
||||
content: "}";
|
||||
margin-left: 0.5mm;
|
||||
}
|
||||
|
||||
.note-marker_margin-note{
|
||||
margin-right: 2mm;
|
||||
}
|
||||
|
||||
.note-marker_margin-note::before{
|
||||
content: "{";
|
||||
margin-right: 1mm;
|
||||
}
|
||||
|
||||
.note-marker_margin-note::after{
|
||||
content: "}";
|
||||
margin-left: 1mm;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
:root{
|
||||
--margin: 1em;
|
||||
|
||||
--fontFamily: sans-serif;
|
||||
--textSize: 17px;
|
||||
/*--fontFamily: "Routed Gothic";*/
|
||||
--fontFamily: "JetBrains Mono NL";
|
||||
/*--textSize: 11pt;*/
|
||||
--textSize: 9pt;
|
||||
--ratio : auto;
|
||||
|
||||
--rouge: #ff665e;
|
||||
--vert: #44d62c;
|
||||
--bleu: #0078bf;
|
||||
|
||||
--border: 4mm;
|
||||
|
||||
}
|
||||
109
assets/js/handlers-old.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
class asciiTextFill extends Paged.Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
}
|
||||
|
||||
afterRendered(pages) {
|
||||
const PAD = 4;
|
||||
|
||||
/* ── 1. Mesurer charW et lineH avec une pre cachée ── */
|
||||
const probe = document.createElement('pre');
|
||||
probe.style.cssText = [
|
||||
'position:absolute', 'visibility:hidden', 'top:0', 'left:0',
|
||||
'font-family:"Courier New",monospace', 'font-size:9pt',
|
||||
'line-height:1.5', 'white-space:pre'
|
||||
].join(';');
|
||||
// 10 lignes de 100 tirets → mesure fiable
|
||||
probe.textContent = Array(10).fill('-'.repeat(100)).join('\n');
|
||||
document.body.appendChild(probe);
|
||||
const pr = probe.getBoundingClientRect();
|
||||
const charW = pr.width / 200;
|
||||
const lineH = pr.height / 20;
|
||||
document.body.removeChild(probe);
|
||||
|
||||
/* ── 2. COLS = nb de caractères par ligne dans la zone imprimable ── */
|
||||
const COLS = Math.floor(pages[0].width / charW);
|
||||
// const COLS = pages[0].width;
|
||||
const DASH = '-'.repeat(COLS);
|
||||
|
||||
/* ── 3. makeBox centré dans COLS ── */
|
||||
function makeBox(lines) {
|
||||
const maxLen = Math.max(...lines.map(l => l.length));
|
||||
const innerW = maxLen + PAD * 2;
|
||||
const border = '|' + '-'.repeat(innerW) + '|';
|
||||
const empty = ' '.repeat(innerW + 2);
|
||||
const rows = lines.map(l =>
|
||||
' '.repeat(PAD) + l + ' '.repeat(innerW - PAD - l.length)
|
||||
);
|
||||
const offset = Math.max(0, Math.floor((COLS - (innerW + 2)) / 2));
|
||||
const sp = ' '.repeat(offset);
|
||||
return [sp + border, sp + empty, ...rows.map(r => sp + r), sp + empty, sp + border].join('\n');
|
||||
}
|
||||
|
||||
/* ── 4. Titre : vider SEULEMENT #chapter-title ── */
|
||||
const titleEl = document.getElementById('chapter-title');
|
||||
const titleLines = Array.from(titleEl.querySelectorAll('h2, h3'))
|
||||
.map(n => n.textContent.trim()).filter(Boolean);
|
||||
if (titleLines.length) {
|
||||
const pre = document.createElement('pre');
|
||||
pre.textContent = titleEl.innerHTML = ''; // vide le div
|
||||
pre.textContent = makeBox(titleLines);
|
||||
titleEl.appendChild(pre);
|
||||
}
|
||||
|
||||
/* ── 5. Bio : vider SEULEMENT #biographie ── */
|
||||
const bioEl = document.getElementById('biographie');
|
||||
const bioText = Array.from(bioEl.querySelectorAll('p'))
|
||||
.map(p => p.textContent.trim()).join(' ');
|
||||
const bioInnerW = COLS - 50; // place pour les | |
|
||||
|
||||
if (bioText) {
|
||||
// word-wrap manuel
|
||||
const wrapped = [];
|
||||
let cur = '';
|
||||
bioText.split(/\s+/).forEach(w => {
|
||||
const test = cur ? cur + ' ' + w : w;
|
||||
if (test.length <= bioInnerW) { cur = test; }
|
||||
else { if (cur) wrapped.push(cur); cur = w; }
|
||||
});
|
||||
if (cur) wrapped.push(cur);
|
||||
|
||||
const border = '|' + '-'.repeat(bioInnerW) + '|';
|
||||
// const bioRows = wrapped.map(l => '|' + l + ' '.repeat(bioInnerW - l.length) + '|');
|
||||
const pre = document.createElement('pre');
|
||||
// pre.textContent = [border, ...bioRows, border].join('\n');
|
||||
// const bioRows = wrapped.map(l => '|' + l + ' '.repeat(bioInnerW - l.length) + '|');
|
||||
pre.textContent = border + '\n\n' + wrapped + '\n\n' + border;
|
||||
bioEl.innerHTML = '';
|
||||
bioEl.appendChild(pre);
|
||||
}
|
||||
|
||||
/* ── 6. Calculer l'espace dispo et remplir les fills ── */
|
||||
// Hauteur intérieure de la page (après padding CSS)
|
||||
const totalH = pages[0].height;
|
||||
|
||||
// Hauteur réelle des blocs de contenu après génération
|
||||
const fixedH = titleEl.offsetHeight + bioEl.offsetHeight;
|
||||
|
||||
// Espace à distribuer entre les 3 fills
|
||||
const spare = Math.max(0, totalH - fixedH);
|
||||
|
||||
// Répartition : 1/3 haut, 1/3 milieu, 1/3 bas
|
||||
// (modifie ces ratios pour décaler le contenu verticalement)
|
||||
const ratios = [1/3, 1/3, 1/3];
|
||||
const ids = ['fill-top', 'fill-mid', 'fill-bottom'];
|
||||
|
||||
ids.forEach((id, i) => {
|
||||
const el = document.getElementById(id);
|
||||
const h = spare * ratios[i];
|
||||
const n = Math.max(0, Math.floor(h / lineH));
|
||||
el.textContent = Array(n).fill(DASH).join('\n');
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Paged.registerHandlers(asciiTextFill);
|
||||
|
||||
|
||||
|
||||
186
assets/js/handlers.js
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
class asciiTextFill extends Paged.Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
super(chunker, polisher, caller);
|
||||
}
|
||||
|
||||
afterRendered(pages) {
|
||||
const PAD = 5;
|
||||
const chars = ["-", "+", "{", "[", "}", "]", ";", "<", ">"];
|
||||
|
||||
/* ── 1. Mesurer charW et lineH avec une pre cachée ── */
|
||||
const probe = document.createElement('pre');
|
||||
probe.style.cssText = [
|
||||
'position:absolute', 'visibility:hidden', 'top:0', 'left:0',
|
||||
'font-family:"Courier New",monospace', 'font-size:9pt',
|
||||
'line-height:1.5', 'white-space:pre'
|
||||
].join(';');
|
||||
probe.textContent = Array(10).fill('-'.repeat(100)).join('\n');
|
||||
document.body.appendChild(probe);
|
||||
const pr = probe.getBoundingClientRect();
|
||||
const charW = pr.width / 200;
|
||||
const lineH = pr.height / 20;
|
||||
document.body.removeChild(probe);
|
||||
|
||||
/* ── 2. COLS = nb de caractères par ligne dans la zone imprimable ── */
|
||||
const COLS = Math.floor(pages[0].width / charW);
|
||||
const DASH = '-'.repeat(COLS);
|
||||
|
||||
/* ── 3. makeBox centré dans COLS ── */
|
||||
function makeBox(lines, char) {
|
||||
const maxLen = Math.max(...lines.map(l => l.length));
|
||||
const innerW = maxLen + PAD * 2;
|
||||
const border = '|' + char.repeat(innerW) + '|';
|
||||
const empty = ' '.repeat(innerW + 2);
|
||||
const rows = lines.map(l =>
|
||||
' '.repeat(PAD) + l + ' '.repeat(innerW - PAD - l.length)
|
||||
);
|
||||
const offset = Math.max(0, Math.floor((COLS - (innerW + 2)) / 10));
|
||||
const sp = ' '.repeat(offset);
|
||||
return [sp + border, sp + empty, ...rows.map(r => sp + r), sp + empty, sp + border].join('\n');
|
||||
}
|
||||
|
||||
/* ── 4. Itérer sur chaque .chapter ── */
|
||||
document.querySelectorAll('.chapter-title').forEach(titleEl => {
|
||||
let randomChar = chars[Math.floor(Math.random() * chars.length)];
|
||||
const DASH = randomChar.repeat(COLS);
|
||||
if(titleEl){
|
||||
const titleLinesH3 = Array.from(titleEl.querySelectorAll('h3'))
|
||||
.map(n => n.textContent.trim()).filter(Boolean);
|
||||
if (titleLinesH3.length) {
|
||||
// Supprimer les h2/h3 originaux
|
||||
titleEl.querySelectorAll('h3').forEach(el => el.remove());
|
||||
const preH3 = document.createElement('pre');
|
||||
preH3.textContent = makeBox(titleLinesH3, randomChar);
|
||||
// Insérer la boîte juste après fill-top
|
||||
const fillTop = titleEl.querySelector('.fill-top');
|
||||
fillTop.insertAdjacentElement('afterend', preH3);
|
||||
}
|
||||
const titleLinesH2 = Array.from(titleEl.querySelectorAll('h2'))
|
||||
.map(n => n.textContent.trim()).filter(Boolean);
|
||||
if (titleLinesH2.length) {
|
||||
// Supprimer les h2/h3 originaux
|
||||
titleEl.querySelectorAll('h2').forEach(el => el.remove());
|
||||
const pre = document.createElement('pre');
|
||||
pre.textContent = makeBox(titleLinesH2, randomChar);
|
||||
// Insérer la boîte juste après fill-top
|
||||
const fillTop = titleEl.querySelector('.fill-top');
|
||||
fillTop.insertAdjacentElement('afterend', pre);
|
||||
}
|
||||
const bioEl = titleEl.querySelector('.biographie');
|
||||
if(bioEl){
|
||||
const bioText = Array.from(bioEl.querySelectorAll('p'))
|
||||
.map(p => p.textContent.trim()).join(' ');
|
||||
const bioInnerW = COLS - 50;
|
||||
|
||||
if (bioText) {
|
||||
const wrapped = [];
|
||||
let cur = '';
|
||||
bioText.split(/\s+/).forEach(w => {
|
||||
const test = cur ? cur + ' ' + w : w;
|
||||
if (test.length <= bioInnerW) { cur = test; }
|
||||
else { if (cur) wrapped.push(cur); cur = w; }
|
||||
});
|
||||
if (cur) wrapped.push(cur);
|
||||
|
||||
const border = '|' + randomChar.repeat(bioInnerW) + '|';
|
||||
const pre = document.createElement('pre');
|
||||
pre.textContent = border + '\n\n' + wrapped.join('\n') + '\n\n' + border;
|
||||
bioEl.innerHTML = '';
|
||||
bioEl.appendChild(pre);
|
||||
}
|
||||
}
|
||||
const totalH = pages[0].height;
|
||||
const fixedH = titleEl.offsetHeight;
|
||||
// const fixedH = (titleEl ? titleEl.offsetHeight : 0) + (bioEl ? bioEl.offsetHeight : 0);
|
||||
const spare = Math.max(0, totalH - fixedH);
|
||||
|
||||
const ratios = [1/3, 1/3, 1/3];
|
||||
const fills = ['.fill-top', '.fill-mid', '.fill-bottom'];
|
||||
|
||||
fills.forEach((sel, i) => {
|
||||
const el = titleEl.querySelector(sel);
|
||||
if (!el) return;
|
||||
const n = Math.max(0, Math.floor((spare * ratios[i]) / lineH));
|
||||
el.textContent = Array(n).fill(DASH).join('\n');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
// document.querySelectorAll('.chapter').forEach(chapter => {
|
||||
// // /* ── Titre : h2 + h3 dans .chapter-title ── */
|
||||
// // const titleEl = chapter.querySelector('.chapter-title');
|
||||
// // if(titleEl){
|
||||
// // const titleLinesH3 = Array.from(titleEl.querySelectorAll('h3'))
|
||||
// // .map(n => n.textContent.trim()).filter(Boolean);
|
||||
// // if (titleLinesH3.length) {
|
||||
// // // Supprimer les h2/h3 originaux
|
||||
// // titleEl.querySelectorAll('h3').forEach(el => el.remove());
|
||||
// // const preH3 = document.createElement('pre');
|
||||
// // preH3.textContent = makeBox(titleLinesH3);
|
||||
// // // Insérer la boîte juste après fill-top
|
||||
// // const fillTop = titleEl.querySelector('.fill-top');
|
||||
// // fillTop.insertAdjacentElement('afterend', preH3);
|
||||
// // }
|
||||
// // const titleLinesH2 = Array.from(titleEl.querySelectorAll('h2'))
|
||||
// // .map(n => n.textContent.trim()).filter(Boolean);
|
||||
// // if (titleLinesH2.length) {
|
||||
// // // Supprimer les h2/h3 originaux
|
||||
// // titleEl.querySelectorAll('h2').forEach(el => el.remove());
|
||||
// // const pre = document.createElement('pre');
|
||||
// // pre.textContent = makeBox(titleLinesH2);
|
||||
// // // Insérer la boîte juste après fill-top
|
||||
// // const fillTop = titleEl.querySelector('.fill-top');
|
||||
// // fillTop.insertAdjacentElement('afterend', pre);
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// // /* ── Bio : .biographie dans ce chapter ── */
|
||||
// // const bioEl = chapter.querySelector('.biographie');
|
||||
// // if(bioEl){
|
||||
// // const bioText = Array.from(bioEl.querySelectorAll('p'))
|
||||
// // .map(p => p.textContent.trim()).join(' ');
|
||||
// // const bioInnerW = COLS - 50;
|
||||
|
||||
// // if (bioText) {
|
||||
// // const wrapped = [];
|
||||
// // let cur = '';
|
||||
// // bioText.split(/\s+/).forEach(w => {
|
||||
// // const test = cur ? cur + ' ' + w : w;
|
||||
// // if (test.length <= bioInnerW) { cur = test; }
|
||||
// // else { if (cur) wrapped.push(cur); cur = w; }
|
||||
// // });
|
||||
// // if (cur) wrapped.push(cur);
|
||||
|
||||
// // const border = '|' + '-'.repeat(bioInnerW) + '|';
|
||||
// // const pre = document.createElement('pre');
|
||||
// // pre.textContent = border + '\n\n' + wrapped.join('\n') + '\n\n' + border;
|
||||
// // bioEl.innerHTML = '';
|
||||
// // bioEl.appendChild(pre);
|
||||
// // }
|
||||
// // }
|
||||
|
||||
// const totalH = pages[0].height;
|
||||
// // const fixedH = titleEl.offsetHeight + bioEl.offsetHeight;
|
||||
// const fixedH = (titleEl ? titleEl.offsetHeight : 0) + (bioEl ? bioEl.offsetHeight : 0);
|
||||
// const spare = Math.max(0, totalH - fixedH);
|
||||
|
||||
// const ratios = [1/3, 1/3, 1/3];
|
||||
// const fills = ['.fill-top', '.fill-mid', '.fill-bottom'];
|
||||
|
||||
// fills.forEach((sel, i) => {
|
||||
// const spare = Math.max(0, totalH - fixedH);
|
||||
// const el = chapter.querySelector(sel);
|
||||
// if (!el) return;
|
||||
// const n = Math.max(0, Math.floor((spare * ratios[i]) / lineH));
|
||||
// el.textContent = Array(n).fill(DASH).join('\n');
|
||||
// });
|
||||
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
Paged.registerHandlers(asciiTextFill);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// -------------- M A R G I N N O T E S S C R I P T -----------------
|
||||
|
||||
let classNotes = "margin-note"; // ← Change the CLASS of the notes here
|
||||
let notesFloat = "left"; // ← Change the POSITION of the notes here
|
||||
let notesFloat = "inside"; // ← Change the POSITION of the notes here
|
||||
|
||||
class marginNotes extends Paged.Handler {
|
||||
constructor(chunker, polisher, caller) {
|
||||
|
|
@ -97,16 +97,9 @@ class marginNotes extends Paged.Handler {
|
|||
counter-increment: callNote_' + toCamelClassNote(classNotes) + ';\
|
||||
}\
|
||||
\
|
||||
.note-call_' + classNotes + '::after {\
|
||||
content: counter(callNote_' + toCamelClassNote(classNotes) + ');\
|
||||
}\
|
||||
\
|
||||
.note-marker_' + classNotes + ' {\
|
||||
counter-increment: markerNote_' + toCamelClassNote(classNotes) + ';\
|
||||
}\
|
||||
.note-marker_' + classNotes + '::before {\
|
||||
content: counter(markerNote_' + toCamelClassNote(classNotes) + ') "";\
|
||||
}\
|
||||
' + notePosition
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@
|
|||
<option value="black-layer">Noire</option>
|
||||
</select>
|
||||
</form>
|
||||
<form class="reset-this" id="black-form">
|
||||
<input class="reset-this" type="checkbox" id="black-toggle" name="black-toggle">
|
||||
<label class="reset-this"for="black-toggle" id="label-black-toggle">
|
||||
Noir et blanc
|
||||
</label>
|
||||
</form>
|
||||
<br>
|
||||
<form class="reset-this" id="preview-form">
|
||||
<input class="reset-this" type="checkbox" id="preview-toggle" name="preview-toggle">
|
||||
|
|
@ -45,12 +51,6 @@
|
|||
Preview
|
||||
</label>
|
||||
</form>
|
||||
<form class="reset-this" id="black-form">
|
||||
<input class="reset-this" type="checkbox" id="black-toggle" name="black-toggle">
|
||||
<label class="reset-this"for="black-toggle" id="label-black-toggle">
|
||||
Noir et blanc
|
||||
</label>
|
||||
</form>
|
||||
<button class="reset-this" id="button-print" onclick="window.print()" data-ready="false" data-text="Print">
|
||||
<!-- <img src="assets/pagedjs/icon-printer.svg">-->
|
||||
Exporter le PDF page à page
|
||||
|
|
|
|||
|
|
@ -2,6 +2,14 @@ Title: Un robot-poète ne nous fait toujours pas peur
|
|||
|
||||
----
|
||||
|
||||
Author: Olivain Porry
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://yb91zmu1609ukju5
|
||||
|
||||
----
|
||||
|
||||
Chapeau: <p>Entouré d’un cadre noir et brillant, posé sur une surface blanche et plastique, un texte s’affiche et décrit ce qui se trouve supposément devant lui : « Un homme se tient dans une salle baignée de lumière rouge ». Si un homme se tient en effet debout face à l’appareil, la salle d’exposition est pourtant blanche et aucune trace de rouge n’apparaît dans la scène. Ce dispositif, qui génère des descriptions textuelles manifestement erronées, est celui de « Lies Language Model » (O. Porry, 2026).</p><p>Si l’installation met en œuvre un algorithme d’intelligence artificielle (IA) capable de produire du texte à partir d’images, elle en révèle surtout les failles et les biais. Elle donne à voir la manière dont les systèmes d’IA peuvent produire de la désinformation de par leur fonctionnement intrinsèque. Car, chez les IA, les mots n’existent pas. Ces algorithmes ne manipulent en effet ni des symboles, ni des concepts, ni même des mots, mais seulement des probabilités statistiques portant sur des ensembles de caractères : des « jetons », fragments de mots dont l’agencement obéit à des logiques strictement calculatoires.</p><p>À l’heure de la généralisation des agents conversationnels et des grands modèles de langage (LLM), cette logique statistique semble s’imposer comme hégémonique sur de multiples plans : culturel, social, politique, mais aussi linguistique. Le langage, réduit à une suite de corrélations probabilistes, devient un matériau opératoire détaché de ses ancrages référentiels, historiques et sensibles. S’inquiéter face à des machines capables de produire du langage n’est pas nouveau. Dès 1954, le public s’effrayait de Calliope, invention du cybernéticien A. Ducrocq, tandis que Boris Vian, lui, s’en amusait. Dans une correspondance restée célèbre sous le titre « Un robot-poète ne nous fait pas peur »(note: Vian, B. (1953/2023).<em> Un robot poète ne nous fait pas peur</em> (J.-N. Lafargue, ill., notes) . Cormeilles-en-Parisis, France : Ateliers Geeks. ISBN 978-2-9589026-0-5), il écrivait : « Mirandolez, éclaboussez ce robot poète de vos connaissances en cybernétique, expliquez-lui comment il marche et vous l’aurez tout humble à votre merci. »</p><p>Aujourd’hui, notre rapport aux mots prend une forme nouvelle, incarnée par l’intégration de machines dans nos conversations et l’apparition de vocables qui circulent, se répètent et se diffusent dans nos imaginaires. Parmi eux, un mot en particulier cristallise ces tensions : le mot « arafed ».</p>
|
||||
|
||||
----
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 4.9 MiB |
|
|
@ -0,0 +1,9 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Uuid: b1ealx46ddf9ogl5
|
||||
|
After Width: | Height: | Size: 4.9 MiB |
|
|
@ -0,0 +1,9 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Uuid: yb91zmu1609ukju5
|
||||
21
content/3_index/chapitre.txt
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
|
|
@ -0,0 +1,9 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Uuid: wtrwmiveg0dntfu4
|
||||
BIN
content/3_index/push-1772898992.blue.preview.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
13
content/3_index/push-1772898992.blue.preview.png.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Sort: 2
|
||||
|
||||
----
|
||||
|
||||
Uuid: 49jw8ewxq9k43dbz
|
||||
BIN
content/3_index/push-1772898992.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
9
content/3_index/push-1772898992.png.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Uuid: fqvhtdtkrwkuqz1u
|
||||
21
content/4_code-creatif/chapitre.txt
Normal file
BIN
content/4_code-creatif/lafargue.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
9
content/4_code-creatif/lafargue.png.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Caption:
|
||||
|
||||
----
|
||||
|
||||
Alt:
|
||||
|
||||
----
|
||||
|
||||
Uuid: a8u2rj1e35diuqs4
|
||||
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
|
Before Width: | Height: | Size: 331 KiB After Width: | Height: | Size: 331 KiB |
|
Before Width: | Height: | Size: 446 KiB After Width: | Height: | Size: 446 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
|
Before Width: | Height: | Size: 427 KiB After Width: | Height: | Size: 427 KiB |
|
Before Width: | Height: | Size: 952 KiB After Width: | Height: | Size: 952 KiB |
|
Before Width: | Height: | Size: 586 KiB After Width: | Height: | Size: 586 KiB |
|
Before Width: | Height: | Size: 896 KiB After Width: | Height: | Size: 896 KiB |
49
site/blueprints/blocks/imagefloat.yml
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
name: Image flottante
|
||||
icon: image
|
||||
preview: image
|
||||
fields:
|
||||
image:
|
||||
label: field.blocks.image.name
|
||||
type: files
|
||||
query: model.images
|
||||
multiple: false
|
||||
image:
|
||||
back: black
|
||||
uploads:
|
||||
template: blocks/image
|
||||
imagered:
|
||||
label: Image (couche rouge)
|
||||
type: files
|
||||
query: model.images
|
||||
multiple: false
|
||||
image:
|
||||
back: black
|
||||
uploads:
|
||||
template: blocks/image
|
||||
imagegreen:
|
||||
label: Image (couche verte)
|
||||
type: files
|
||||
query: model.images
|
||||
multiple: false
|
||||
image:
|
||||
back: black
|
||||
uploads:
|
||||
template: blocks/image
|
||||
imageblue:
|
||||
label: Image (couche bleu)
|
||||
type: files
|
||||
query: model.images
|
||||
multiple: false
|
||||
image:
|
||||
back: black
|
||||
uploads:
|
||||
template: blocks/image
|
||||
alt:
|
||||
label: field.blocks.image.alt
|
||||
type: text
|
||||
icon: title
|
||||
caption:
|
||||
label: field.blocks.image.caption
|
||||
type: writer
|
||||
icon: text
|
||||
inline: true
|
||||
|
|
@ -7,6 +7,14 @@ columns:
|
|||
fields:
|
||||
type: fields
|
||||
fields:
|
||||
author:
|
||||
label: Auteur·ice
|
||||
type: text
|
||||
width: 1/2
|
||||
cover:
|
||||
label: Image de couverture
|
||||
type: files
|
||||
multiple: false
|
||||
chapeau:
|
||||
label: Chapeau
|
||||
type: writer
|
||||
|
|
@ -29,6 +37,7 @@ columns:
|
|||
fieldsets:
|
||||
- gallery
|
||||
- image
|
||||
- imagefloat
|
||||
- fullpageimage
|
||||
- spreadimage
|
||||
others:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Kirby::plugin('sarahgarcin/notes-tag', [
|
|||
'html' => function($tag) {
|
||||
$note = $tag->attr('note');
|
||||
|
||||
return '<span class="footnote">'.$note.'</span>';
|
||||
return '<span class="margin-note">'.$note.'</span>';
|
||||
|
||||
}
|
||||
]
|
||||
|
|
|
|||
46
site/snippets/blocks/imagefloat.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
/** @var \Kirby\Cms\Block $block */
|
||||
$alt = $block->alt();
|
||||
$caption = $block->caption();
|
||||
$src = $block->image()->toFile()->url();
|
||||
|
||||
?>
|
||||
|
||||
<?php if ($src): ?>
|
||||
<figure class="web-image">
|
||||
|
||||
<img src="<?= $src ?>" alt="<?= $alt->esc() ?>">
|
||||
|
||||
<?php if ($caption->isNotEmpty()): ?>
|
||||
<figcaption>
|
||||
<?= $caption->kt() ?>
|
||||
</figcaption>
|
||||
<?php endif ?>
|
||||
</figure>
|
||||
|
||||
<figure class="print-image float-image">
|
||||
<?php if($srcred = $block->imagered()->toFile()):?>
|
||||
<div class="print-red red-layer">
|
||||
<img src="<?= $srcred->url() ?>" alt="<?= $alt->esc() ?>">
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if($srcgreen = $block->imagegreen()->toFile()):?>
|
||||
<div class="print-green green-layer">
|
||||
<img src="<?= $srcgreen->url() ?>" alt="<?= $alt->esc() ?>">
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if($srcblue = $block->imageblue()->toFile()):?>
|
||||
<div class="print-blue blue-layer">
|
||||
<img src="<?= $srcblue->url() ?>" alt="<?= $alt->esc() ?>">
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
|
||||
<?php if ($caption->isNotEmpty()): ?>
|
||||
<figcaption>
|
||||
<?= $caption->kt() ?>
|
||||
</figcaption>
|
||||
<?php endif ?>
|
||||
</figure>
|
||||
<?php endif ?>
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
"assets/js/plugins/full-page.js",
|
||||
"assets/js/plugins/margin-notes.js",
|
||||
"assets/js/plugins/toc.js",
|
||||
"assets/js/handlers.js",
|
||||
'@auto'
|
||||
]) ?>
|
||||
|
||||
|
|
|
|||
49
site/templates/print-old.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php snippet('head') ?>
|
||||
|
||||
|
||||
<?php $sizes = "(min-width: 1200px) 25vw,
|
||||
(min-width: 900px) 33vw,
|
||||
(min-width: 600px) 50vw,
|
||||
100vw";
|
||||
?>
|
||||
|
||||
<header id="interface-header" w3-include-html="assets/pagedjs/interface.html"></header>
|
||||
|
||||
<div id="render-book"></div>
|
||||
|
||||
<template id="book-content">
|
||||
<section class="cover">
|
||||
<h1><?= $site->title()->html()?></h1>
|
||||
</section>
|
||||
<section class="toc">
|
||||
<h2>Sommaire</h2>
|
||||
<article id="table-of-contents"></article>
|
||||
</section>
|
||||
|
||||
<?php foreach($site->index()->filterBy('intendedTemplate', 'chapitre') as $chapitre):?>
|
||||
<section class="chapter">
|
||||
<div class="chapter-title">
|
||||
<!-- REMPLISSAGE HAUT -->
|
||||
<div class="ascii-fill fill-top"></div>
|
||||
<h2><?= $chapitre->title()->html()->smartypants() ?></h2>
|
||||
<h3><?= $chapitre->author()->html()->smartypants() ?></h3>
|
||||
<!-- REMPLISSAGE BAS -->
|
||||
<div class="ascii-fill fill-mid"></div>
|
||||
<div class="biographie" id="biographie">
|
||||
<p>Biographie Nus adit pressit et rem dolor ratibus. Ut atem et res ab id ut est lit, iscia cum que am verum sapici dolestorpora placeat laborit asinctate omnihilis aspelen dicatusam voluptae eum ipsandit undempos aut et laceptati omniminveris quam sim qui corem harum qui invenihita volorer sperumquas el mi, tectota tesequu ntioneserit, corem qui as earchit ipis di cum litios pro conse perspel ipsae eturi unt, sundae enimus aut ut endero cumquam faccatem duci quo quatqua meturion event fuga. Et volore videndia solorro runtis doluptas rem netum aborporaepro te quos raes at. Haritas sim quam, soluptate venem quam, earum vendunte omnisi ad endebisqui opta vel magnam conseditas eicia ditibearum rem explabo.</p>
|
||||
</div>
|
||||
<!-- REMPLISSAGE BAS FINAL -->
|
||||
<div class="ascii-fill fill-bottom"></div>
|
||||
</div>
|
||||
|
||||
<div class="chapeau"><?= $chapitre->chapeau()->kt()->smartypants() ?></div>
|
||||
<?php foreach ($chapitre->text()->toBlocks() as $block): ?>
|
||||
<div id="<?= $block->id() ?>" class="block block-type-<?= $block->type() ?>">
|
||||
<?= $block ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</section>
|
||||
<?php endforeach;?>
|
||||
</template>
|
||||
|
||||
<?php snippet('footer');?>
|
||||
|
|
@ -1,36 +1,58 @@
|
|||
<?php snippet('head') ?>
|
||||
|
||||
|
||||
<?php $sizes = "(min-width: 1200px) 25vw,
|
||||
(min-width: 900px) 33vw,
|
||||
(min-width: 600px) 50vw,
|
||||
100vw";
|
||||
?>
|
||||
|
||||
<header id="interface-header" w3-include-html="assets/pagedjs/interface.html"></header>
|
||||
|
||||
<div id="render-book"></div>
|
||||
|
||||
<template id="book-content">
|
||||
|
||||
<section class="cover">
|
||||
<h1><?= $site->title()->html()?></h1>
|
||||
</section>
|
||||
|
||||
<section class="toc">
|
||||
<h2>Sommaire</h2>
|
||||
<article id="table-of-contents"></article>
|
||||
</section>
|
||||
|
||||
<?php foreach($site->index()->filterBy('intendedTemplate', 'chapitre') as $chapitre):?>
|
||||
<section class="chapter">
|
||||
<?php foreach($site->index()->filterBy('intendedTemplate', 'chapitre')->listed() as $chapitre):?>
|
||||
<section class="chapter">
|
||||
<?php if($cover = $chapitre->cover()->toFile()):?>
|
||||
<div class="interpage full-bleed-image full-page">
|
||||
<figure>
|
||||
<img src="<?= $cover->url() ?>" alt="">
|
||||
</figure>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
<div class="chapter-title">
|
||||
<div class="ascii-fill fill-top"></div>
|
||||
|
||||
<h2><?= $chapitre->title()->html()->smartypants() ?></h2>
|
||||
<div class="chapeau"><?= $chapitre->chapeau()->kt()->smartypants() ?></div>
|
||||
<h3><?= $chapitre->author()->html()->smartypants() ?></h3>
|
||||
|
||||
<div class="ascii-fill fill-mid"></div>
|
||||
|
||||
<div class="biographie">
|
||||
<p>Biographie Nus adit pressit et rem dolor ratibus. Ut atem et res ab id ut est lit, iscia cum que am verum sapici dolestorpora placeat laborit asinctate omnihilis aspelen dicatusam voluptae eum ipsandit undempos aut et laceptati omniminveris quam sim qui corem harum qui invenihita volorer sperumquas el mi, tectota tesequu ntioneserit, corem qui as earchit ipis di cum litios pro conse perspel ipsae eturi unt, sundae enimus aut ut endero cumquam faccatem duci quo quatqua meturion event fuga. Et volore videndia solorro runtis doluptas rem netum aborporaepro te quos raes at. Haritas sim quam, soluptate venem quam, earum vendunte omnisi ad endebisqui opta vel magnam conseditas eicia ditibearum rem explabo.</p>
|
||||
</div>
|
||||
|
||||
<div class="ascii-fill fill-bottom"></div>
|
||||
</div>
|
||||
|
||||
<div class="chapeau"><?= $chapitre->chapeau()->kt()->smartypants() ?></div>
|
||||
|
||||
<div class="chapter-content">
|
||||
<?php foreach ($chapitre->text()->toBlocks() as $block): ?>
|
||||
<div id="<?= $block->id() ?>" class="block block-type-<?= $block->type() ?>">
|
||||
<?= $block ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</section>
|
||||
<?php endforeach;?>
|
||||
</template>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
<?php snippet('footer');?>
|
||||
</section>
|
||||
<?php endforeach;?>
|
||||
|
||||
</template>
|
||||
<?php snippet('footer');?>
|
||||