Skip to content

Design Architetturale

Architettura package

Papyrus è organizzato in un'architettura modulare, in cui ogni elemento principale è rappresentato da un package dedicato. La struttura dei package è la seguente:

diagramma dei package

Scelte di progettazione generali

Papyrus è stato progettato come una libreria modulare scritta in Scala, con un forte orientamento alla programmazione funzionale e alla gestione immutabile dei dati. L’approccio adottato si fonda su una costruzione del documento tramite funzioni pure e builder specializzati, che espongono un DSL leggibile, fortemente tipizzato e organizzato gerarchicamente.

L’utente interagisce con Papyrus invocando funzioni come papyrus, metadata, content, title, text, ecc., ognuna delle quali crea un contesto specifico utilizzando parametri impliciti (using) e builder composabili. Queste funzioni creano progressivamente la struttura interna del documento, fino al salvataggio finale del file HTML, CSS o PDF.

Ogni elemento del documento (es. titolo, paragrafo, lista, immagine) è rappresentato da un oggetto di dominio dotato di metodi render e renderStyle, che restituiscono rispettivamente la componente HTML e CSS, in formato stringa.


Papyrus struttura

Papyrus è l'elemento principale della libreria, che funge da punto d'ingresso per la creazione di documenti e permette una volta inseriti tutti i componenti di generare il documento richesto. La sua struttura è organizzata nella seguente gerarchia:

diagramma della struttura di Papyrus

Metadata struttura

Metadata rappresenta i metadati del documento, come titolo, autore, lingua, stile globale, ecc. È un componente essenziale che definisce le proprietà generali del documento e il suo aspetto visivo. La sua struttura è organizzata nella maniera seguente:

diagramma della struttura di Metadata

Content struttura

Content rappresenta il contenuto principale del documento, che può includere sezioni, sottosezioni, testo, immagini, tabelle e altri elementi. È responsabile della composizione e dell'organizzazione del contenuto in modo strutturato. La sua struttura è organizzata nella maniera seguente:

diagramma della struttura di Content

Entità principali

Le entità centrali all’interno di Papyrus si suddividono in due categorie:

  • Builder (entità attive):

    • PapyrusBuilder, MetadataBuilder, ContentBuilder, SectionBuilder, SubSectionBuilder, ListBuilder, TitleBuilder, ecc.
    • Ogni builder mantiene stato interno immutabile e contiene metodi with* per modificare configurazioni in maniera pura.
    • Al termine della configurazione, ciascun builder espone un metodo build() che restituisce l’oggetto finale (es. Title, Section, Text, ecc.).
  • Elementi (entità passive):

    • Title, Text, List, Table, Image, Paragraph, ecc.
    • Ogni elemento rappresenta una componente del documento e implementa due metodi:
      • render: restituisce il corrispondente HTML;
      • renderStyle: restituisce il CSS associato allo stile.

Ogni builder è progettato per operare su uno specifico livello del documento e può essere composto in modo ricorsivo, mantenendo sempre consapevolezza del contesto.


Modellazione del contesto

Papyrus impone vincoli gerarchici nella composizione del documento: ad esempio, una SubSection può essere dichiarata solo all’interno di una Section, così come un item può esistere solo all’interno di una list.

Questi vincoli sono codificati staticamente a livello di tipo tramite l’uso di parametri impliciti (using). Ad esempio, la funzione:

scala
def listing(init: ListBuilder ?=> Unit)(using ctx: PapyrusBuilder | ContentBuilder | SectionBuilder | SubSectionBuilder | ListBuilder): Unit = ...

I vincoli sono garantiti interamente a compile-time, riducendo la possibilità di errori strutturali.


Flusso di costruzione e rendering

  1. L’utente scrive il documento utilizzando le keyword offerte dal DSL Papyrus.
  2. Ogni chiamata attiva un builder, che elabora e memorizza le informazioni relative all’elemento.
  3. I builder vengono composti ricorsivamente, tenendo traccia del contesto e dello stile.
  4. Al termine del processo, ciascun elemento produce:
    • HTML tramite un metodo di rendering dedicato;
    • CSS tramite una funzione di serializzazione dello stile.
  5. Il documento completo viene assemblato da un componente finale che concatena tutti i contenuti e stili in un file HTML e un file CSS.

Output e generazione dei file

La generazione dell’output è centralizzata in un modulo che si occupa di:

  • Aggregare i contenuti HTML e lo stile CSS;
  • Salvare i file nella directory specificata, oppure, in mancanza, in una cartella temporanea eliminata successivamente;
  • Convertire il file HTML in PDF (se richiesto), utilizzando librerie esterne specifiche;
  • Aprire automaticamente il file generato con il programma predefinito dell’utente.

In ogni caso, il file HTML fa riferimento al foglio style.css, generato dinamicamente sulla base delle impostazioni raccolte nei builder.


Glossario tecnico

Keyword DSL

KeywordDescrizione
papyrusPunto d’ingresso del documento. Deve contenere esattamente un blocco metadata e uno content.
metadataBlocco che definisce i metadati e lo stile globale del documento (titolo, autore, font, colore, ecc.).
contentContenuto principale del documento: sezioni, testo, immagini, tabelle, liste, ecc.
sectionSezione del contenuto. Può contenere sottosezioni e altri elementi.
subsectionSottosezione nidificata all’interno di una section.
titleTitolo gerarchico. Il livello (H1/H2/H3) è determinato dal contesto (papyrus/content/section).
textBlocco testuale. Supporta stili inline mediante keyword come fontWeight, color, textDecoration.
boldInserisce un text marcato come grassetto. Shortcut di text + fontWeight("bold").
italicInserisce un text in corsivo. Shortcut di text + fontStyle("italic").
underlineInserisce un text sottolineato. Shortcut con textDecoration("underline").
listingCrea una lista ordinata o puntata. Può essere annidata, supporta ordinamenti.
itemElemento di una lista. Inseribile solo all’interno di un listing.
listTypeSpecifica il tipo di lista: "ul" (puntata) o "ol" (numerata).
orderedSpecifica il criterio di ordinamento: "alphabetical", "length", "reverse", "levenshtein".
referenceValore stringa usato per ordinamento Levenshtein in un listing.
table[T]Inserisce una tabella parametrica (T). Può contenere righe, caption, e configurazioni visive.
captionImposta la descrizione della tabella.
withListInserisce una lista di righe (List[RowBuilder[T]]) nella tabella.
backgroundColorTableImposta il colore di sfondo della tabella.
textAlignTableAllineamento del testo ("left", "center", "right", "justify").
marginTableMargine esterno della tabella.
widthTableLarghezza della tabella in pixel.
alignTableAllineamento orizzontale della tabella ("left", "right", "center").
renderTableFunzione di rendering delle celle: (T => String).
imageInserisce un’immagine con attributi opzionali (src, alt, caption, width).
nameFileImposta il nome del file finale da generare (document.pdf, ecc.).
extensionEstensione del file: "pdf" o "html".
pathPercorso per il salvataggio del file.
languageCodice ISO della lingua del documento ("it", "en", "de", ecc.).
metadataTitleTitolo del documento nel metadata.
authorNome dell’autore nel metadata.
charsetCharset del documento HTML ("utf-8", "iso-8859-1"...).
styleSheetPercorso del foglio di stile CSS utilizzato nel rendering HTML.
fontFont del corpo del documento. Valore applicato nel builder MainStyleBuilder.
fontSizeDimensione del font globale. Intero compreso tra 8 e 72.
lineHeightAltezza della riga, espressa come moltiplicatore (1.03.0).
textColorColore del testo globale ("#000000", rgb(...), ecc.).
backgroundColorColore di sfondo del documento.
textAlignAllineamento del paragrafo: "left", "center", "right", "justify".
marginMargine esterno del body. Intero tra 0 e 200 pixel.
Proprietà InlineTipoContestoDescrizione
colorColorStringtextImposta il colore del testo (#fff, rgb(...), "red", ecc.).
fontWeightFontWeighttextPeso del font: "normal" o "bold".
fontStyleFontStyletextStile del font: "normal" o "italic".
textDecorationTextDecorationtextDecorazione del testo: "none", "underline", "overline".
newLineStringtextAggiunge una nuova riga con testo opzionale.
levelLeveltitleLivello del titolo (1–3). Determinato anche automaticamente dal contesto.
fontFontFamilytitleFont da utilizzare per il titolo (es. "Helvetica").
fontSizeFontSizetitleDimensione del font del titolo (8–72).
textColorColorStringtitleColore del testo del titolo.
textAlignAlignmenttitleAllineamento: "left", "center", "right", "justify", ecc.