Content Management System.

Contenuti resistenti nel tempo e nello spazio (cyber).

Il nostro sistema di gestione dei contenuti e i documenti che genera devono essere resistenti nel tempo e nello spazio, gli strumenti che adottiamo per questo scopo sono: Guix, Emacs Org-mode e Git.

Introduzione

Speriamo sempre di riuscire a scrivere qualcosa di intelligente e utile non solo per noi e non solo per avere i nostri 15 minuti di gloria, per questo vorremmo che i nostri contenuti siano disponibili fra trent'anni o più nel caso a qualcuno sarà ancora interessato, per questo ce ne curiamo fin dalle fasi di progettazione.

Nel Dicembre 2019 Jeff Huang ha scritto un interessante articolo intitolato ˝designed to last˝ (in inglese) nel quale osserva come troppo spesso accade che le nostre pagine, i nostri media preferiti - audio, video, PDF - o addirittura interi siti scompaiano dal web o vengano spostati ad altri indirizzi (URL) rendendo inutilizzabili tutti i precedenti link: si tratta del cosiddetto problema del link rot; questo succede non solo quando sono passati decenni dalla loro prima pubblicazione, ma anche a distanza di pochi mesi se non addirittura giorni.

I motivi che stanno alla base di questo fenomeno - al netto delle cause storiche che determinano il modo di produzione dei nostri beni digitali - li possiamo ricondurre sostanzialmente alla difficoltà di gestire la complessità del sistema gestione dei contenuti.

Utilizzare una "piattaforma" basata su applicazioni web fornite da altri - come ad esempio WordPress.com o Facebook, ma ce ne sono moltissime altre - nella speranza che qualcun altro gestisca quella complessità per sempre al posto nostro è illusorio, perché prima o poi le "piattaforme" vengono dismesse e i contenuti che veicolano semplicemente scompaiono; che sia fornita gratuitamente o abbia un costo, che si tratti una piccola azienda o di un colosso multinazionale le cose con cambiano, a meno che qualcuno si occupi di migrare ad altra piattaforma i contenuti, coi relativi costi. Sono disponibili molti sistemi di pubblicazione basati su applicazioni web, da WordPress a Wikimedia, ma installare e soprattutto manutenere nel tempo tali servizi non è da tutti e… comunque non è per sempre.

Per affrontare questi problemi Huang propone di applicare alcuni principi di progettazione e implementazione che noi condividiamo: dalla redazione dei contenuti fino alla loro presentazione sul supporto finale, per esempio attraverso gli stili CSS per i documenti in HTML, passando per la scelta del software utilizzato nella catena di build.

Sistema di pubblicazione

Per redigere e pubblicare i documenti utilizziamo Emacs Org-mode, che include un sistema di pubblicazione che consente di gestire diversi progetti editoriali - per esempio siti web ma anche produzione di PDF o di ebook - utilizzando contenuti scritti nel linguaggio markup Org-mode; per chi volesse approfondire la documentazione di Emacs fornisce alcuni esempi.

La configurazione del sistema di pubblicazione ox-publish è scritta in questo documento, suddivisa in sezioni per ciascun sito di destinazione, a loro volta suddivise in una sezione per ciascun formato di output (allo stato attuale solo HTML); tutte queste sezioni sono estrapolate (tangling in terminologia literate programming) tramite il sistema noweb e salvate nel file publish.pl.

Principi generali di design

Questi sono i principi di design che valgono per l'intero sistema di pubblicazione:

  • riproducibilità del software: tutte le nostre dipendenze software sono gestite attraverso Guix, affinché il CMS generi i documenti in modo riproducibile e duraturo, per i dettagli si veda la sezione Software utilizzato;
  • minimalismo: in questo contesto si intende l'applicazione dei concetti di minimalismo alle dipendenze del software (evitare di introdurre dipendenze inutili1) e nella progettazione delle interfacce utente.

Questi principi di design valgono per ogni formato di esportazione utilizzato (per ora solo HTML):

  • le pubblicazioni devono essere progettate come fossero una rivista, una scheda prodotto o un manuale d'uso, considerato che per alcuni formati (es. HTML, Texinfo) ciascuna pagina può scorrere a piacere e adattarsi alle dimensioni del dispositivo (responsive design) mentre per altri (es. PDF, EPUB) il formato della pagina ha dimensioni fisse (es. A4, A5) indipendenti dal dispositivo;
  • le dimensioni dei media (immagini, audio, video) utilizzati devono essere minimizzate per ottenere il massimo risultato per ciascun formato di esportazione con il minimo incremento delle dimensioni.

Principi di designi HTML

L'HTML generato dal nostro sistema di pubblicazione deve aderire a questi principi:

Principi di design CSS

Il CSS usato per la presentazione dei contenuti HTML deve aderire a questi principi:

  • semantico: il CSS dipende dalla struttura semantica del HTML, deve essere lo specchio del markup HTML e deve rifletterne la struttura con selettori CSS annidati; per approfondimenti si veda l'articolo Semantics, (in inglese).
  • evitare framework CSS non semantici: Bootstrap e Tailwind sono due esempi di framework CSS non semantici, per approfondimenti si veda Why I Don't Like Tailwind CSS (in inglese);
  • evitare i device breakpoints: non c'è nessun motivo di calcolare le dimensioni di un particolare dispositivo per poi definire una griglia responsive codificata, per approfondimenti si veda l'articolo Stop using device breakpoints (in inglese);
  • evitare metodologie "BEM-like": BEM (Block, Element, Modifier) è una metodologia di naming dei selettori CSS: nonostante le intenzioni rende il codice meno leggibile e poco semantico, per approfondimenti si veda l'articolo BEM Is Terrible (in inglese);
  • limitare l'uso di preprocessori: usare sempre codice CSS nativo ove possibile (es. per variabili e nesting), solo se strettamente necessario è possibile usare il preprocessore SASS implementato in libsass, disponibile in Guix anche se è deprecata; non usare l'implementazione dart-sass perché non è disponibile come pacchetto Guix;

Software utilizzato

Usiamo GNU/Guix per gestire tutte le dipendenze software del sistema di pubblicazione perché ci consente di ottenere un sistema riproducibile nel tempo, potenzialmente per svariate decine di anni4, senza il rischio di incappare nel dependency hell, costantemente in agguato in ogni progetto software e mai davvero risolto da altri sistemi di pacchettizzazione o configuration management.

Il manifest.scm che definisce tutto il software necessario è pubblicato tramite il sistema noweb che lo estrae automaticamente (tangle) da questo file.

Pubblichiamo i nostri feed attraverso Emacs webfeeder, che genera uno o più feed RSS o ATOM a partire da un insieme configurabile di pagine HTML.

"emacs-webfeeder"

Per generare comodamente codice HTML utilizziamo xmlgen

"emacs-xmlgen"

Per il syntax highlighting del codice nelle pagine HTML usiamo htmlize:

"emacs-htmlize"

Usiamo git per la gestione delle revisioni e qui ci serve per ottenere da quale versione (commit e branch) stiamo generando i documenti

"git"

Parametri comuni a tutti i siti

HTML

Utilizziamo queste funzioni:

(defun xmlgen-from-list (the-list)
  "Apply xmlgen to each element of the-list and return a single string, the-list elements must be a valid xmlgen s-expr."
  (mapconcat
   (lambda (arg)
     (xmlgen arg))
   the-list "\n"))

(defun header1 ()
  "Return the SWWS logo container as SHTML."
  `(div :class "header1"
        (p :class "logo"
           (a :href "https://softwareworkers.it/"
              ":~ software|workers"))))

Utilizziamo queste variabili:

(defvar common-copyright-years "2016-2023")
(defvar common-content-license '("CC-BY-SA" . "https://creativecommons.org/licenses/by-sa/4.0/"))
(defvar common-code-license '("GNU GPLv3" . "https://www.gnu.org/licenses/gpl-3.0.en.html"))
(defvar git-commit (substring (shell-command-to-string "git rev-parse --short HEAD") 0 -1))
(defvar git-branch (substring (shell-command-to-string "git rev-parse --abbrev-ref HEAD") 0 -1))

;; Common values for html-head-extra
(defvar common-html-extra-head
  (list
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/fonts.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/custom-properties.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/elements.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/common.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/navbar.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/org.css")
   `(link :rel "stylesheet" :type "text/css" :href "/themes/swws/css/gui-js.css")
   `(script :src "/themes/swws/js/gui.js" "")))

;; Header 0 content
(defvar common-html-preamble-en
  `(div :class "header0"
        (span :hidden "hidden" "")))

(defvar common-html-preamble-it
  `(div :class "header0"
        (span :hidden "hidden" "")))

;; Footer 0 content
(defvar common-html-postamble-en
  `(div :class "footer0"
        (p :class "copyright"
           ,(format "© %s Software Workers" common-copyright-years)
           " (Code license: " (a :href ,(cdr common-code-license) ,(car common-code-license))
           ", content license: " (a :href ,(cdr common-content-license) ,(car common-content-license)) ")" )
        (p :class "git-commit"
           ,(format "Commit %s/%s" git-branch git-commit))))

(defvar common-html-postamble-it
  `(div :class "footer0"
        (p :class "copyright"
           ,(format "© %s Software Workers" common-copyright-years)
           " (Licenza del codice: " (a :href ,(cdr common-code-license) ,(car common-code-license))
           ", licenza del contenuto: " (a :href ,(cdr common-content-license) ,(car common-content-license)) ")" )
        (p :class "git-commit"
           ,(format "Commit %s/%s" git-branch git-commit))))

Questi sono i parametri di configurazione dell'esportazione HTML comuni a tutti i siti:

:recursive yes
:base-extension "org"
:publishing-function org-html-publish-to-html
:with-archived-trees nil
:headline-levels 3
:section-numbers nil
:with-creator t
:with-toc t
:html-doctype "html5"
:html-html5-fancy t
:html-self-link-headlines t
:html-head-include-scripts nil
:html-head-include-default-style nil
:html-preamble t
:html-postamble t

doc.meup

HTML

Utilizziamo queste variabili:

;; Title
(defvar doc.meup-title "DocMeUp!")

;; Extra head
(defvar doc.meup-html-extra-head
  (append common-html-extra-head
          (list
           `(link :rel "icon" :type "image/x-icon" :href "../logo.png")
           `(link :href "../atom.xml" :type "application/atom+xml" :rel "alternate" :title "DocMeup! Feed"))))

;; Header 1 content
(defvar doc.meup-html-preamble-en
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "/" "Home"))
               (li (a :href "/guides/sitemap.html" "User Guides"))
               (li (a :href "/colophon/" "Colophon"))
               (li (a :class "lang" :href "/it/" "IT"))))))

(defvar doc.meup-html-preamble-it
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "/it/" "Home"))
               (li (a :href "/it/guides/sitemap.html" "Guide utente"))
               (li (a :href "/it/colophon/" "Colophon"))
               (li (a :class "lang" :href "/" "EN"))))))

;; Footer 1 content
(defvar doc.meup-html-postamble-en
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Site map"))))

(defvar doc.meup-html-postamble-it
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Mappa del sito"))))

Generiamo l'elenco dei documenti della sitemap (di ciascuna sezione) con questo codice5:

;;
;; code adapted from Pierre Neidhardt's blog
;; https://gitlab.com/ambrevar/ambrevar.gitlab.io/-/blob/master/publish.el
;;

(defun doc-meup/org-publish-sitemap (title list)
  "doc-meup sitemap, as a string 
See `org-publish-sitemap-default'. "
  ;; Remove index and non articles.
  (setcdr list (seq-filter
                (lambda (file)
                  (string-match "file:[^ ]*/index.org" (car file)))
                (cdr list)))
  (org-list-to-org list))

(defun doc-meup/org-publish-sitemap-entry (entry style project)
  "Custom format for site map ENTRY, as a string.
See `org-publish-sitemap-default-entry'."
  (cond ((not (directory-name-p entry))
         (format "[[file:%s][%s]]"
                 entry
                 (org-publish-find-title entry project)))))

;; (defun doc-meup/org-publish-sitemap-entry (entry style project)
;;   "Format for sitemap ENTRY, as a string.
;; ENTRY is a file name.  STYLE is the style of the sitemap.
;; PROJECT is the current project."
;;   (unless (equal entry "index.org")
;;     (format "[[file:%s][%s]] (%s)"
;;          entry
;;          (org-publish-find-title entry project)
;;          (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)))))

I testi e i media per il sito doc.meup.io devono essere salvati nella cartella ./source/doc.meup/ e vengono pubblicati nella cartella ./public/doc.meup/, questo è il codice per configurare il tutto, dovrebbe essere sufficientemente autoesplicativo:

("doc.meup - English root pages"
 :language en
 :base-directory "./source/doc.meup/en"
 :publishing-directory "./public/doc.meup/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Site map" doc.meup-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("doc.meup - English guides"
 :language en
 :base-directory "./source/doc.meup/en/guides"
 :publishing-directory "./public/doc.meup/guides/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - User guides" doc.meup-title)
 :sitemap-style list
 ;; :sitemap-date-format FIXME
 :sitemap-format-entry doc-meup/org-publish-sitemap-entry
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("doc.meup - Italian root pages"
 :language it
 :base-directory "./source/doc.meup/it"
 :publishing-directory "./public/doc.meup/it/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Mappa del sito" doc.meup-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("doc.meup - Italian guides"
 :language it
 :base-directory "./source/doc.meup/it/guides"
 :publishing-directory "./public/doc.meup/it/guides" 
 :auto-sitemap t
 :sitemap-title ,(format "%s - Guide utente" doc.meup-title)
 :sitemap-style list
 :sitemap-format-entry doc-meup/org-publish-sitemap-entry
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("doc.meup - Media"
 :recursive yes
 :base-directory "./source/doc.meup/media"
 :base-extension "jpg\\|gif\\|png\\|svg\\|webm\\|mp4\\|ogg\\|.htaccess"
 :publishing-directory "./public/doc.meup/media"
 :publishing-function org-publish-attachment)

("doc.meup - Themes"
 :recursive yes
 :base-directory "./source/themes/"
 :base-extension "jpg\\|gif\\|png\\|svg\\|css\\|ttf\\|woff\\|woff2\\|js"
 :publishing-directory "./public/doc.meup/themes"
 :publishing-function org-publish-attachment)

("doc.meup" :components ("doc.meup - English guides"
                         "doc.meup - Italian guides"
                         "doc.meup - Media"
                         "doc.meup - Themes"
                         "doc.meup - English root pages"
                         "doc.meup - Italian root pages"))

Questa è la configurazione dei parametri di pubblicazione HTML specifici per questo sito:

:keywords "MeUp SoftwareWorkers"
:html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
:html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
:html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))

beta.swws

HTML

Questo è il sito di beta testing beta.softwareworkers.it.

Utilizziamo queste variabili:

;; test.softwareworkers - website variables
(defvar beta.swws-title "SWWS")

;; Extra head
(defvar beta.swws-html-extra-head
  (append common-html-extra-head
          (list
           `(link :rel "icon" :type "image/x-icon" :href "../logo.png")
           `(link :href "../atom.xml" :type "application/atom+xml" :rel "alternate" :title "SWWS Feed"))))

;; Header 1 content
(defvar beta.swws-html-preamble-en
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "/en/" "Home"))
               (li (a :href "/en/private-cloud" "Private cloud"))
               (li (a :href "/en/application-hosting" "Application hosting"))
               (li (a :href "/en/about/" "About"))
               (li (a :href "/en/impressum" "Impressum"))
               (li (a :class "lang" :href "/" "IT"))))))

(defvar beta.swws-html-preamble-it
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "/" "Home"))
               (li (a :href "/private-cloud" "Cloud privati"))
               (li (a :href "/application-hosting" "Hosting applicativo"))
               (li (a :href "/about/" "Chi siamo"))
               (li (a :href "/impressum" "Impressum"))
               (li (a :class "lang" :href "/en/" "EN"))))))

;; Footer 1 content
(defvar beta.swws-html-postamble-en
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Site map"))))

(defvar beta.swws-html-postamble-it
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Mappa del sito"))))

Generiamo l'elenco dei documenti della sitemap (di ciascuna sezione) con questo codice5:

;;
;; code adapted from Pierre Neidhardt's blog
;; https://gitlab.com/ambrevar/ambrevar.gitlab.io/-/blob/master/publish.el
;;

(defun beta-swws/org-publish-sitemap (title list)
  "beta-swws sitemap, as a string 
See `org-publish-sitemap-default'. "
  ;; Remove index and non articles.
  (setcdr list (seq-filter
                (lambda (file)
                  (string-match "file:[^ ]*/index.org" (car file)))
                (cdr list)))
  (org-list-to-org list))

(defun beta-swws/org-publish-sitemap-entry (entry style project)
  "Custom format for site map ENTRY, as a string.
See `org-publish-sitemap-default-entry'."
  (cond ((not (directory-name-p entry))
         (format "[[file:%s][%s]]^{ (%s)}"
                 entry
                 (org-publish-find-title entry project)
                 (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))))))

I testi e i media per il sito beta.softwareworkers.it devono essere salvati nella cartella ./source/beta.swws/ e vengono pubblicati nella cartella ./public/beta.swws/, questo è il codice per configurare il tutto, dovrebbe essere sufficientemente autoesplicativo:

("beta.swws - English root pages"
 :language en
 :base-directory "./source/beta.swws/en"
 :publishing-directory "./public/beta.swws/en"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Site map" beta.swws-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "SWWS SoftwareWorkers Software Workers"
 :html-head-extra ,(xmlgen-from-list beta.swws-html-extra-head)
 :html-preamble-format (("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-it)))
                       ("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-en))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it)))))

("beta.swws - English jobs"
 :language en
 :base-directory "./source/beta.swws/en/jobs"
 :publishing-directory "./public/beta.swws/en/jobs/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Jobs" beta.swws-title)
 :sitemap-style list
 ;; :sitemap-date-format FIXME
 :sitemap-format-entry beta-swws/org-publish-sitemap-entry
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("beta.swws - Italian root pages"
 :language it
 :base-directory "./source/beta.swws/it"
 :publishing-directory "./public/beta.swws/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Mappa del sito" beta.swws-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "SWWS SoftwareWorkers Software Workers"
 :html-head-extra ,(xmlgen-from-list beta.swws-html-extra-head)
 :html-preamble-format (("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-it)))
                       ("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-en))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it)))))

("beta.swws - Italian jobs"
 :language it
 :base-directory "./source/beta.swws/it/jobs"
 :publishing-directory "./public/beta.swws/jobs/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Offerte di lavoro" beta.swws-title)
 :sitemap-style list
 ;; :sitemap-date-format FIXME
 :sitemap-format-entry beta-swws/org-publish-sitemap-entry
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MeUp SoftwareWorkers"
 :html-head-extra ,(xmlgen-from-list doc.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list doc.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen doc.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))
 )

("beta.swws - Media"
 :recursive yes
 :base-directory "./source/beta.swws/media"
 :base-extension "jpg\\|gif\\|png\\|svg\\|webm\\|mp4\\|ogg\\|.htaccess"
 :publishing-directory "./public/beta.swws/media"
 :publishing-function org-publish-attachment)

("beta.swws - Themes"
 :recursive yes
 :base-directory "./source/themes/"
 :base-extension "jpg\\|gif\\|png\\|svg\\|css\\|ttf\\|woff\\|woff2\\|js"
 :publishing-directory "./public/beta.swws/themes"
 :publishing-function org-publish-attachment)

("beta.swws" :components ("beta.swws - Media"
                          "beta.swws - Themes"
                          "beta.swws - English root pages"
                          "beta.swws - English jobs"
                          "beta.swws - Italian root pages"
                          "beta.swws - Italian jobs"))

Questa è la configurazione dei parametri di esportazione per HTML comune a tutto il sito:

:keywords "SWWS SoftwareWorkers Software Workers"
:html-head-extra ,(xmlgen-from-list beta.swws-html-extra-head)
:html-preamble-format (("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-it)))
                       ("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.swws-html-preamble-en))))
:html-postamble-format (("en"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.swws-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))

beta.meup

HTML

Questo è il sito di beta testing beta.meup.io.

Utilizziamo queste variabili:

;; beta.meup - website variables
(defvar beta.meup-title "MEUP")

;; Extra head
(defvar beta.meup-html-extra-head
  (append common-html-extra-head
          (list
           `(link :rel "icon" :type "image/x-icon" :href "../logo.png")
           `(link :href "../atom.xml" :type "application/atom+xml" :rel "alternate" :title "Meup! Feed"))))

;; Header 1 content
(defvar beta.meup-html-preamble-en
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "https://softwareworkers.it" "by SWWS"))
               (li (a :href "/pricing/" "Pricing"))
               (li (a :href "/community/" "Community"))
               (li (a :class "lang" :href "/it/" "IT"))))))

(defvar beta.meup-html-preamble-it
  (list (header1)
        `(nav :class "menu" :aria-labelledby "menu-title"
              (h2 :id "menu-title" :class "a11y-offset" "Main Menu")
              (ul
               (li (a :href "https://softwareworkers.it" "by SWWS"))
               (li (a :href "/pricing/it/" "Prezzi"))
               (li (a :href "/community/it/" "Community"))
               (li (a :class "lang" :href "/" "EN"))))))

;; Footer 1 content
(defvar beta.meup-html-postamble-en
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Site map"))))

(defvar beta.meup-html-postamble-it
  `(div :class "footer1"
        (p :class "sitemap"
           (a :href "/sitemap.html" "Mappa del sito"))))

Generiamo l'elenco dei documenti della sitemap (di ciascuna sezione) con questo codice5:

;;
;; code adapted from Pierre Neidhardt's blog
;; https://gitlab.com/ambrevar/ambrevar.gitlab.io/-/blob/master/publish.el
;;

(defun beta-meup/org-publish-sitemap (title list)
  "beta-meup sitemap, as a string 
See `org-publish-sitemap-default'. "
  ;; Remove index and non articles.
  (setcdr list (seq-filter
                (lambda (file)
                  (string-match "file:[^ ]*/index.org" (car file)))
                (cdr list)))
  (org-list-to-org list))

(defun beta-meup/org-publish-sitemap-entry (entry style project)
  "Custom format for site map ENTRY, as a string.
See `org-publish-sitemap-default-entry'."
  (cond ((not (directory-name-p entry))
         (format "[[file:%s][%s]]^{ (%s)}"
                 entry
                 (org-publish-find-title entry project)
                 (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))))))

I testi e i media per il sito beta.meup.io devono essere salvati nella cartella ./source/beta.meup/ e vengono pubblicati nella cartella ./public/beta.meup/, questo è il codice per configurare il tutto, dovrebbe essere sufficientemente autoesplicativo:

("beta.meup - English root pages"
 :language en
 :base-directory "./source/beta.meup/en"
 :publishing-directory "./public/beta.meup/"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Site map" beta.meup-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MEUP SoftwareWorkers Software Workers"
 :html-head-extra ,(xmlgen-from-list beta.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it)))))

("beta.meup - Italian root pages"
 :language en
 :base-directory "./source/beta.meup/it"
 :publishing-directory "./public/beta.meup/it"
 :auto-sitemap t
 :sitemap-title ,(format "%s - Site map" beta.meup-title)
 :sitemap-style list
 :recursive yes
 :base-extension "org"
 :publishing-function org-html-publish-to-html
 :with-archived-trees nil
 :headline-levels 3
 :section-numbers nil
 :with-creator t
 :with-toc t
 :html-doctype "html5"
 :html-html5-fancy t
 :html-self-link-headlines t
 :html-head-include-scripts nil
 :html-head-include-default-style nil
 :html-preamble t
 :html-postamble t
 :keywords "MEUP SoftwareWorkers Software Workers"
 :html-head-extra ,(xmlgen-from-list beta.meup-html-extra-head)
 :html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-it))))
 :html-postamble-format (("en"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it)))))

("beta.meup - Media"
 :recursive yes
 :base-directory "./source/beta.meup/media"
 :base-extension "jpg\\|gif\\|png\\|svg\\|webm\\|mp4\\|ogg\\|.htaccess"
 :publishing-directory "./public/beta.meup/media"
 :publishing-function org-publish-attachment)

("beta.meup - Themes"
 :recursive yes
 :base-directory "./source/themes/"
 :base-extension "jpg\\|gif\\|png\\|svg\\|css\\|ttf\\|woff\\|woff2\\|js"
 :publishing-directory "./public/beta.meup/themes"
 :publishing-function org-publish-attachment)

("beta.meup" :components ("beta.meup - Media"
                          "beta.meup - Themes"
                          "beta.meup - English root pages"
                          "beta.meup - Italian root pages"))

Questa è la configurazione dei parametri di esportazione per HTML comune a tutto il sito:

:keywords "MEUP SoftwareWorkers Software Workers"
:html-head-extra ,(xmlgen-from-list beta.meup-html-extra-head)
:html-preamble-format (("en"
                        ,(concat (xmlgen common-html-preamble-en) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-en)))
                       ("it"
                        ,(concat (xmlgen common-html-preamble-it) "\n"
                                 (xmlgen-from-list beta.meup-html-preamble-it))))
:html-postamble-format (("en"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-en)))
                        ("it"
                         ,(concat (xmlgen beta.meup-html-postamble-it) "\n"
                                  (xmlgen common-html-postamble-it))))

TODO Deployment

Tutti gli asset generati devono essere pubblicati su un web server per il quale si dispongono le credenziali.

Il web server fornisce solo pagine e asset statici quindi non ha bisogno di supporto a qualche linguaggio per applicazioni web, tipo PHP o Ruby, e nemmeno di accesso a RDMBS.

Redazione dei contenuti.

Riteniamo che sia fondamentale utilizzare formati accessibili e duraturi e per questo evitiamo formati binari per i testi e ove possibile utilizziamo linguaggi di markup specifici per ciascun dominio, come ad esempio ditaa per i diagrammi liberi, PlantUML per diagrammi strutturati o gnuplot per rappresentare graficamente i dati tabellari. Laddove è necessario includere media, utilizziamo solo formati binari liberi.

Org-mode

Per scrivere il contenuto abbiamo scelto il formato Org-mode perché tra i Light Markup Languages è quello che consente un elevato grado di espressività pur rimanendo sufficientemente intuitivo. Org-mode include anche il sistema Babel che consente di inserire nei documenti il codice sorgente e di pubblicare il risultato della sua esecuzione: questo sistema è perfetto per includere nel testo anche pezzi di codice che poi vengono compilati e inseriti nelle pagine pubblicate, per esempio immagini di diagrammi in formato ditaa.

Per inserire o correggere i testi ciascun autore può scegliere di utilizzare l'editor che preferisce; chi usa l'interprete Lisp Emacs, nel quale è programmato Org-mode, dovrebbe già conoscere il markup e il suo avanzato sistema di gestione.

Per vim sappiamo esiste il plugin Org.vim che fornisce il supporto alla sintassi Org-mode; se utilizzate altri editor di testo potete cercare se sono disponibili plugins analoghi. Ad ogni modo sconsigliamo vivamente di adottare sistemi alternativi e Emacs Org-mode che tentino di andare oltre il semplice supporto alla visualizzazione facilitata della sintassi Org-mode.

Detto questo, ciascun utente deve occuparsi di configurare il proprio ambiente di editing in modo tale da fornirgli uno strumento di lavoro che lo soddisfi e che gli permetta di essere produttivo.

File media

Questi sono i formati di file media ammessi:

  • PDF per documenti da stampare,
  • PNG per le immagini,
  • OGG o MP3 per l'audio,
  • WebM per il video.

Estensioni.

Se siete nel gruppo dei redattori di questo progetto ed avete necessità di utilizzare testo formattato in altri linguaggi di markup leggeri o di generare assets (es. immagini, audio, video) attraverso software che interpreta un domain specific language non incluso nell'attuale sistema di pubblicazione, potete contattare il supporto tecnico e descrivere i vostri requisiti e le vostre proposte in merito: se valuteremo che l'estensione richiesta è necessaria e il software è disponibile in Guix allora c'è la possibilità che la vostra proposta venga accettata.

TODO Come contribuire

Il progetto è pubblico, ogni persona può copiare e redistribuire i contenuti secondo quanto stabilito nella licenza.

Se sei interessato a contribuire con nuovi contenuti, integrare quelli già presenti, tradurli in altre lingue, commentare o segnalare possibili correzioni siete benvenuti; questo progetto:

  • usa git per la gestione delle revisioni e l'inclusione delle patch, il remote ufficiale è su GitLab;
  • usa una mailing list pubblica, moderata, per l'invio e la discussione di patch (FIXME)
  • usa una mailing list pubblica, moderata, per l'invio e la pubblicazione dei commenti sui contenuti. (FIXME)

TODO Invio patch tramite email

Prendere ispirazione da https://orgmode.org/contribute.html

Per invio patch fare riferimento a: https://git-send-email.io/

Note a piè di pagina:

1

si veda ad esempio l'articolo My Minimalist Approach to Software Engineering di Benjamin Tanone

2

detti anche slideshows o sliders, presentano una collezione di elementi, uno per volta, con la possibilità di sfogliarli; sono usati tipicamente per i titoli delle notizie, gli articoli in evidenza in home page e le gallerie di immagini.

3

laddove occorra inserire immagini di diverse varianti di uno stesso prodotto, meglio inserire ciascuna immagine (con eventuali didascalie) nel flusso stesso della pagina, intercalate al testo.

4

almeno sulle architettute hardware attualmente supportate da Guix, ammesso che tali architetture esisteranno ancora tra decine di anni.

5

grazie a Brett Gilio per aver condiviso il suo codice, che ho preso come esempio.

Mappa del sito

Commit CSS-devel/4a4c25c