This commit is contained in:
Joshua Ramon Enslin 2018-06-01 22:35:44 +02:00 committed by Stefan Rohde-Enslin
commit 9430abd660
13 changed files with 1069 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.swp
/pdf
/tmp

185
brochure.tex Normal file
View File

@ -0,0 +1,185 @@
\documentclass[12pt,a4paper,twocolumn,landscape,openany]{memoir}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% Document-wide settings
\pagestyle{empty} % no page number
\parskip 7.2pt % space between paragraphs
\parindent 12pt % indent for new paragraph
\textwidth 6.5in % width of text
\columnsep 0.5in % separation between columns
% Load packages
\usepackage[utf8]{inputenc}
\input{pdfSettings.tex}
\usepackage{geometry}
\geometry{left=0.7in,top=0.7in,right=0.7in,bottom=0.7in} %margins
\usepackage{graphicx}
\usepackage{xcolor,framed}
\usepackage[colorlinks = true, % Set color of links to red
linkcolor = red,
urlcolor = red,
citecolor = red,
anchorcolor = red]{hyperref}
\usepackage{tikz} % for \gradientbox below.
\usepackage{eso-pic}
\usepackage{titlesec}
\pagenumbering{gobble} % Disable page numbers
% Set title formats using titlesec ----------------------------------
\titleformat{\chapter}
{\huge\bfseries\color{red}} % format
{} % label
{0pt} % sep
{\huge} % before-code
\titleformat{\section}
{\huge\bfseries} % format
{} % label
{0pt} % sep
{\huge} % before-code
\titleformat{\subsection}
{\Large\bfseries} % format
{} % label
{0pt} % sep
{\Large} % before-code
% Set font
\renewcommand{\familydefault}{cmss}
% Macro fot setting background on start page
\newcommand{\centerVertically}[1]{
\topskip0pt
\vspace*{\fill}
#1
\vspace*{\fill}
}
\newcommand\BackgroundPic{%
\put(0,0){%
\parbox[b][\paperheight]{\paperwidth}{%
\resizebox {\paperwidth} {!} {
\begin{tikzpicture}[
box/.style={draw,minimum width=2.5cm,align=left},
node distance=0.5cm and 3cm
]
\node[align=right,left color=orange,right color=orange] {};
\end{tikzpicture}%
}
}}}
\begin{document}%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% Title Page
%
\begin{titlingpage}%
%
% \AddToShipoutPicture*{\BackgroundPic}
\centering%
\color{black}%
\vspace{\paperheight}%
{\scshape // \par}%
\vspace{1cm}%
\vspace{.5cm}%
{\Huge\bfseries\color{red} Museum-Digital}%
%
\let\cleardoublepage\clearpage
\end{titlingpage}%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% Introduction
%
\chapter{Introduction}
\section{Entstehung...}
Grundsätzlich sind es die beteiligten Museen und ihre Verbände, die das Geschehen von museum-digital lenken. Jedes Museum ist für seine eigenen Beiträge verantwortlich. Diese Beiträge gestaltet das Museum mit den entsprechenden Werkzeugen von museum-digital in der regionalen (oder thematischen) Version der es zugeordnet ist. Jede regionale (oder thematische) Version von museum-digital hat andere Betreuer - zumeist die regionalen Museumsverbände oder Landesstellen für Museumsbetreuung. Die deutschlandweite Version von museum-digital entsteht aus den regionalen (und thematischen) Versionen (halb-) automatisch.
Weitere Entwicklungen bei museum-digital geschehen auf Anregung aus den Museen oder ihren Verbänden. Grundsätzliche Änderungen, d.h. Änderungen, die das Gesamtsystem betreffen, werden nur dann umgesetzt, wenn die AG Digitalisierung des Museumsverbandes Sachsen-Anhalt, die Keimzelle von museum-digital, zustimmt. Änderungen, die nur in einer einzelnen Version zum Tragen kommen und andere Versionen nicht tangieren, werden dann umgesetzt wenn die entsprechenden Versions-Betreuer es für nötig halten.
Alle konzeptuellen Änderungen (z.B. Aufnahme privater Sammlungen in das Verzeichnis) werden in der AG Digitalisierung des Museumsverbandes Sachsen-Anhalt diskutiert und entschieden.
\section{Wer steht dahinter}
Grundsätzlich sind es die beteiligten Museen und ihre Verbände, die das Geschehen von museum-digital lenken. Jedes Museum ist für seine eigenen Beiträge verantwortlich. Diese Beiträge gestaltet das Museum mit den entsprechenden Werkzeugen von museum-digital in der regionalen (oder thematischen) Version der es zugeordnet ist. Jede regionale (oder thematische) Version von museum-digital hat andere Betreuer - zumeist die regionalen Museumsverbände oder Landesstellen für Museumsbetreuung. Die deutschlandweite Version von museum-digital entsteht aus den regionalen (und thematischen) Versionen (halb-) automatisch.
Weitere Entwicklungen bei museum-digital geschehen auf Anregung aus den Museen oder ihren Verbänden. Grundsätzliche Änderungen, d.h. Änderungen, die das Gesamtsystem betreffen, werden nur dann umgesetzt, wenn die AG Digitalisierung des Museumsverbandes Sachsen-Anhalt, die Keimzelle von museum-digital, zustimmt. Änderungen, die nur in einer einzelnen Version zum Tragen kommen und andere Versionen nicht tangieren, werden dann umgesetzt wenn die entsprechenden Versions-Betreuer es für nötig halten.
Alle konzeptuellen Änderungen (z.B. Aufnahme privater Sammlungen in das Verzeichnis) werden in der AG Digitalisierung des Museumsverbandes Sachsen-Anhalt diskutiert und entschieden.
\section{Ziele und Grundsätze}
\subsection{Das Ziel in einem Satz}
Das eigentliche Ziel von museum-digital ist es allen Museen eine Möglichkeit zu bieten fundierte Informationen zu Ihren Objekten auf einfache Weise effektiv im Internet sichtbar zu machen. Hinter diesem Ziel steht die Absicht mit der Publikation der Objektinformation auf die Museen selbst und die in ihnen geleistete Erschließungsarbeit aufmerksam zu machen. Gleichzeitig sollen den Museen Möglichkeiten der Nachnutzung digitaler Information erschlossen werden, etwa durch Einbindung der Informationen in die eigene Internetpräsenz oder durch digitale Ausstellungen (Themenportale). museum-digital ist in jedem Fall nur ein Werkzeug. Für jene Museen, die über kein eigenes Programm zur Inventarisierung verfügen, stellt museum-digital die entsprechenden Funktionen in einem gesonderten Bereich zur Verfügung.
Aus dieser, schon 2009 von der AG Digitalisierung des Museumsverbandes Sachsen-Anhalt, formulierten Zielstellung und insbesondere aus den seit damals gewonnenen Erfahrungen leiten sich einige Grundsätze ab, die für alle Versionen von museum-digital gültig sind:
\subsection{Inventarisieren vs. Publizieren}
Inventarisieren ist eine Notwendigkeit. In den meisten Museen dient die Inventarisierung ausschließlich der Verwaltung der Objekte, dem Besitznachweis, dem Leihverkehr ... Die Einträge in den zur Inventarisierung genutzten Datenbanken sind entsprechend vor allem stichwortartig. Die Inventarisierungsdatenbanken sind in den meisten Fällen geschlossene Systeme, die nicht mit Systemen anderer Museen oder zentralen Datenbanken, wie etwa der Gemeinsamen Normdatei der Bibliotheken, kommunizieren können. Die Einträge in Inventarisierungsdatenbanken werden üblicherweise von Mitarbeitern des Museums ausschließlich für Mitarbeiter des gleichen Museums vorgenommen. Entsprechend sind Einträge wie "Stuhl, blau" als Objektbeschreibung häufig zu finden. Solche Einträge sind für die Publikation wenig geeignet.
Ganz ähnlich verhält es sich mit Abbildungen zu Objekten. Für die Inventarisierung werden häufig Fotos erstellt auf denen eine Inventarnummer zuerkennen ist und/oder ein genormter Farbbalken mit dem Objekt abgelichtet wurde. Dies soll die Zuordnung von Abbildungen zu Objekten erleichtern und die Rekonstruktion der Farbigkeit eines Objektes ermöglichen. Bildästhetische Maßstäbe werden nicht berücksichtigt. Solche Abbildungen (bei denen mitunter die Darstellung der Inventarnummer das Objekt bedeckt) sind für die Publikation wenig geeignet.
Für die Internet-Publikation sind ansprechende und aussagekräftige Objektabbildungen sowie ausführliche und geprüfte Objektinformationen nötig. Jenen Museen, die mit museum-digital nicht nur publizieren, sondern auch inventarisieren, wird empfohlen schon die Inventarisierung publikationsfähig zu gestalten. Das ist der einfachste Weg.
\subsection{Nicht in erster Linie ein Portal}
Objekte und Museen im Internet sichtbar machen heißt bei museum-digital die Objekte und Museen vor allem dort zu platzieren, wo die Internet-Nutzer sind. Der Aufbau eines "Portals für Museumsobjekte" ist nicht das Ziel von museum-digital. Die Mehrzahl der Internet-Nutzer kennen ihre Suchmaschine und sie sind es gewohnt diese Suchmaschine für allgemeine Fragen zu benutzen. Entsprechend ist es Absicht von museum-digital mit möglichst vielen Objekten möglichst weit vorn auf den Trefferlisten der Suchmaschinen zu sein. Dort suchen die Nutzer und von dort sollen sie den Weg zu den Objekten finden. Sind sie dann auf den Seiten von museum-digital angekommen, dann ist es das Ziel durch Verknüpfungen von Objektinformationen Anreize zu geben, weitere Seiten bei museum-digital zu lesen. Natürlich wird mit der Zeit bei immer mehr Nutzern bekannt, dass manche ihrer Fragen bei museum-digital eine Antwort finden. Diese Nutzer gehen dann, bei passenden Fragen, direkt zu museum-digital - das, auf diese Weise, ungewollt Portal-Funktionen wahrnimmt. Die Konsequenz aus diesem Grundsatz ist, dass der Quellcode von museum-digital in regelmäßigen Abständen für Suchmaschinen optimiert wird, dass viele Verlinkungsmöglichkeiten zwischen Objekten eingerichet wurden und dass dennoch die Suchfunktionen bei museum-digital selbst sehr ausgefeilt sind.
Es bedingt sich gegenseitig: Je mehr Museen mitmachen, desto größer werden Spektrum und Anzahl von Querverweisen. Mit mehr Querverweisen und (automatisch entstehenden) Übersichtsseiten steigt das Potential für die Suchmaschinenoptimierung. Im Streit um Aufmerksamkeit im Internet ist es für Museen hilfreich Objektinformationen gemeinsam zu publizieren.
\subsection{Offen für alle Museen}
Museum-digital steht allen Museen zur Verfügung. Dieser Anspruch hat Konsequenzen:
\begin{itemize}
\item{Die verwendete Software muss sehr einfach zu bedienen sein. Mitarbeiter müssen sie ohne teure IT-Schulung benutzen können.}
\item{Die verwendete Software muss weitestgehend kostenfrei sein. Längst nicht jedes Museum kann sich die oft sehr teueren Lizenzen von Museums-Softwareproduktion gewinnorientierter Firmen leisten. Museum-digital basiert auf frei verfügbarer Software (mysql, php).}
\item{Das System muss sehr flexibel sein. Es gibt in den verschiedenen Museen verschiedene Traditionen des Formulierens von Objektinformationen. Als Beispiel sei auf Zeitangaben verwiesen, wo "1600/1650" häufig das gleiche meint wie "1600-1650" oder wie "Erste Hälfte des 17. Jahrhunderts", was auch oft als "1. H. 17. Jh." notiert wird und sich wenig von "Anfang bis Mitte 17. Jahrhundert" unterscheidet. In einem Museum werden die Informationen auf die eine Art und in einem anderen auf eine andere Art notiert. Häufig gibt es keine Regeln (oder niemanden, der auf eine Einhaltung achtet) und es bleibt dem - möglicherweise täglich wechselnden - Geschmack der Bearbeiter überlassen, wie sie die Informationen notieren. Verschiedenartige Einträge erschweren die Suche - nicht nur in der museumseigenen Objektdatenbank sondern besonders bei kooperativen Systemen wie museum-digital, in denen die Kreativität vieler Museen aufeinandertrifft. Eine Redaktion bestimmter zentraler Angaben (Ortsnamen, Personen- und Institutionenbezeichnungen, Zeitangaben und Schlagworte) wird durch museum-digital vorgenommen. Einträge werden hierbei gleichgesetzt oder zu Synonymen erklärt. Ein Teil der Qualitätssicherung ist damit sozusagen von den Museen zu museum-digital verlagert.}
\item{Weil Museen aller Arten und Sparten mitwirken, kann und will museum-digital fachspezifische Internetportale nicht ersetzen. Wer beispielsweise sehr tiefgehende Hintergrund- und Grundlageninformationen über Mineralien (einschließlich modellhafter Abbildungen von Kristallstrukturen, Verbreitungskarten, etc.) sucht, der ist bei mindat.org besser aufgehoben. Wo möglich verlinkt museum-digital aber zu solchen Fachdatenbank-Systemen.}
\item{Offen für alle Museen bedeutet auch, dass die beteiligten Museen auf die Entwicklung des Software-Systems Einfluß nehmen können. Nur so kann sichergestellt werden, dass die Software für alle Museen gut zu verwenden ist und dass sie den Ansprüchen der Museen genügt.}
\end{itemize}
\subsection{Mehrsprachigkeit}
Das Internet ist global. museum-digital ist daher auf Mehrsprachigkeit eingerichtet - in Eingabe, Ausgabe und Verwaltung von Objektinformationen. Die Navigation der Seiten, wie auch die Informationen zu Museen, zu Sammlungen oder zu Objekten lassen sich in beliebig vielen Sprachen ein- und ausgeben. Dies ermöglicht Kooperationsprojekte über Sprachgrenzen hinweg. Im Augenblick stehen im Eingabe- und Bearbeitungwerkzeug folgende Sprachen zur Verfügung: Deutsch, Englisch, Indonesisch, Polnisch, Portugiesisch, Ungarisch. Auf der Internetseite können die Nutzer zwischen Deutsch, Englisch, Indonesisch, Italienisch, Polnisch, Portugiesisch und Ungarisch wählen. Ein eigenes Werkzeug erleichtert das Einrichten weiterer Sprachversionen.
\subsection{Mehrfachnutzung}
museum-digital ist keine Einbahnstraße und kein Selbstzweck! Museen, die Informationen zu ihren Objekten bei museum-digital publizieren haben von hier aus zahlreiche einfach nutzbare Möglichkeiten:
Museum-digital verfügt einen leicht zu bedienenden Exportmechanismus mit dem sich jedes Museum eine Exportdatei für ausgewählte Objekte erstellen kann. Diese Exportdatei ist im LIDO-Datenaustauschformat gehalten und kann einfach an Portale weitergegeben werden. Etliche Museen haben auf diese Weise bereits ihre Informationen an die "europeana" oder die "ddb" (Deutsche Digitale Bibliothek) weitergereicht. Mehr zu den Exportmöglichkeiten finden Sie unter Ausgabe/Export.
Jedes Museum kann seine eigenen Objektinformationen auch in die eigene Internetseite einbinden. Dafür gibt es den einfachen Weg über einen iframe (mehr dazu unter Ausgabe/Einbinden) oder über eine API (mehr dazu unter Ausgabe/APIs).
Eine weitere Möglichkeit, die eigenen Daten selbst zu nutzen, bietet das einfache Themen-Erstellungsprogramm von museum-digital. Hiermit können die Objekte in Form einer kleinen digitalen Ausstellung gruppiert, annotiert und (als Gruppe) beschrieben, vor allem aber präsentiert werden (Mehr dazu unter Ausgabe/Themen).
\newpage%
%
\input{contentsFrontend.tex}%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% Vorletztes: Links
%
\input{contentsTail.tex}%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% Vorletztes: Links
%
\input{contentsContact.tex}%
%
%
%
\end{document}

BIN
contents/.de.htm.swo Normal file

Binary file not shown.

195
contents/de.htm Normal file
View File

@ -0,0 +1,195 @@
<main>
<h1>Museum-Digital</h1>
<section id="introduction">
<h2>Introduction</h2>
<div>
<!--
<div>
</div>
<div>
</div>
-->
</div>
</section>
<section id="frontend">
<h2>Ausgabe</h2>
<div>
<div>
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
</div>
<div>
//
</div>
</div>
<div>
<h3>Accessibility</h3>
<div class="centerVertically">
<img src="media/Screenshot-Accessibility.png" />
</div>
<div class="centerVertically">
<ul>
<li>Klares, kontrastreiches Design</li>
<li>Semantisches Markup und alternative <a href="https://handbook.museum-digital.info/?lan=de&amp;q=Ausgabe/APIs">Ausgabeformate</a></li>
<li>Eine breite Auswahl von Eingabe- und Navigationsoptionen
<ul>
<li>Klassisches Navigieren mit der Maus</li>
<li>Kontextmenü</li>
<li>Tastatursteuerung</li>
<li>Sprachsteuerung</li>
</ul>
</li>
</ul>
</div>
</div>
</section>
<section id="musdb">
<h2>musdb: Die Eingabeoberfläche von museum-digital</h2>
<div>
<div>
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
</div>
<div>
</div>
</div>
</section>
<section id="musdb">
<h2>musdb: Die Eingabeoberfläche von museum-digital</h2>
<div>
<div>
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
</div>
<div>
</div>
</div>
</section>
<section id="themator">
<h2>Der Themator: Narrative und digitale Ausstellungen</h2>
<div>
<div>
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
Die Ausgabe von museum-digital ist ................. Einleitungstext.
</div>
<div>
</div>
</div>
</section>
<section id="learnMore">
<h2>Mehr Erfahren ...</h2>
<div>
<h3>Links</h3>
<div class="centerVertically">
<div>
<h4>Hauptseiten</h4>
<ul class="dl">
<li data-title="Startseite von Museum-Digital Deutschland"><a class="url" href="https://www.museum-digital.de">https://www.museum-digital.de</a></li>
</ul>
</div>
<div>
<h4>Nebenprojekte</h4>
<ul class="dl">
<li data-title="md:term"><a class="url" href="https://term.museum-digital.de">https://term.museum-digital.de</a></li>
<li data-title="themator"><a class="url" href="https://www..museum-digital.de/themator">https://www..museum-digital.de/themator</a></li>
</ul>
</div>
<div>
<h4>Über Museum-Digital</h4>
<ul class="dl">
<li data-title="Projektblog"><a class="url" href="https://museum-digital.de/blog">https://museum-digital.de/blog</a></li>
<li data-title="Handbuch"><a class="url" href="https://handbook.museum-digital.info">https://handbook.museum-digital.info</a></li>
</ul>
</div>
</div>
<div class="centerVertically">
<img src="media/Screenshot-Accessibility.png" />
</div>
</div>
</section>
<section id="contact">
<h2>Kontakt</h2>
<div>
<div>
<div>
<h4>Verantwortlichkeit</h4>
<ul class="dl">
<li data-title="V.i.S.d.P.">Jemand</li>
<li data-title="Dokument zuletzt generiert">\today</li>
</ul>
</div>
</div>
</div>
</section>
</main>

BIN
css/Quicksand-Medium.ttf Normal file

Binary file not shown.

BIN
css/Quicksand-Regular.ttf Normal file

Binary file not shown.

78
css/main.css Normal file
View File

@ -0,0 +1,78 @@
/* =============
| Loading fonts
|============ */
@font-face {
font-family: quicksand;
src: local('Quicksand-Regular'), local('Quicksand Regular'),
url(./Quicksand-Regular.ttf) format('truetype');
}
/* =============
| General
|============ */
* { z-index: 1; }
html { margin 0; padding: 0; }
body { margin: 0; background: #FFF; font-size: 1.2em; font-family: quicksand; line-height: 1.5em; }
a { text-decoration: inherit; color: inherit; }
h1, h2, h3, h4 { padding: .5em 0; color: #646464; }
h2 { color: #F00; }
body > * { padding: 2em 5vw; }
a.buttonLike { padding: .8em 1.0em; background: #F00; color: #FFF;
border: #D6D6D6; border-radius: .3em;
box-shadow: 2px 2px 4px #D6D6D6, -2px -2px 4px #D6D6D6;
transition: background .4s, color .4s; }
a.buttonLike:hover { background: #C11; color: #FFF; }
.centerVertically { vertical-align: middle !important; }
/* =============
| Structure elements
|============ */
/* =======
| Navigation
|====== */
body > nav { position: sticky; top: 0; left: 0;
display: flex; padding-top: 0; padding-bottom: 0;
background: #333; color: #EEE; border-bottom: #D6D6D6; box-shadow: 2px 2px 4px #333; }
body > nav > * { display: inline-block; flex: 1; padding: .6em .5em; vertical-align: middle; }
nav > a[href="#bottom"] { text-align: right; padding: .4em .5em; }
nav > a[href="#bottom"]:before { content: " \002193 "; display: inline-block; padding: .2em .5em;
background: #EEE; color: #333; border-radius: 100%;
transition: background .4s, color .4s; }
nav > a[href="#bottom"]:hover:before { background: #F00; color: #FFF; }
/* =======
| Sections
|====== */
section > div > div { display: inline-block; width: 45%; vertical-align: top; }
section > div > div img { display: block; width: 100%; }
section > div > div:first-of-type { padding-right: 5%; }
/* =======
| Defined lists (as <ul>)
|====== */
ul.dl { margin: 0; padding: 0; }
ul.dl > li { margin: 0; padding: 0; list-style: none; }
ul.dl > li:before { content: attr(data-title); }
/* =============
| Animations
|============ */
@keyframes fade-in {
from { opacity: .4; }
to { opacity: 1; }
}

356
functions.php Normal file
View File

@ -0,0 +1,356 @@
<?PHP
/**
* Main functions file.
*
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
*/
/**
* Browsersprache ermitteln
*
* @param array $allowed_languages Array of allowed languages
* @param string $default_language Language code of the default language
* @param string $lang_variable Already set language variable
* @param bool $strict_mode Whether to demand de (false) or de-de
*
* @return string
*/
function lang_getfrombrowser($allowed_languages, $default_language, $lang_variable = null, $strict_mode = true) {
// $_SERVER['HTTP_ACCEPT_LANGUAGE'] verwenden, wenn keine Sprachvariable mitgegeben wurde
if ($lang_variable === null) {
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $lang_variable = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
}
// wurde irgendwelche Information mitgeschickt?
if (empty($lang_variable)) {
// Nein? => Standardsprache zurückgeben
return $default_language;
}
// Den Header auftrennen
$accepted_languages = preg_split('/,\s*/', $lang_variable);
// Die Standardwerte einstellen
$current_lang = $default_language;
$current_q = 0;
// Nun alle mitgegebenen Sprachen abarbeiten
foreach ($accepted_languages as $accepted_language) {
// Alle Infos über diese Sprache rausholen
$res = preg_match('/^([a-z]{1,8}(?:-[a-z]{1,8})*)'.
'(?:;\s*q=(0(?:\.[0-9]{1,3})?|1(?:\.0{1,3})?))?$/i', $accepted_language, $matches
);
// war die Syntax gültig?
if (!$res) {
// Nein? Dann ignorieren
continue;
}
// Sprachcode holen und dann sofort in die Einzelteile trennen
$lang_code = explode('-', $matches[1]);
// Wurde eine Qualität mitgegeben?
if (isset($matches[2])) {
// die Qualität benutzen
$lang_quality = (float)$matches[2];
} else {
// Kompabilitätsmodus: Qualität 1 annehmen
$lang_quality = 1.0;
}
// Bis der Sprachcode leer ist...
while (count($lang_code)) {
// mal sehen, ob der Sprachcode angeboten wird
if (in_array(strtolower(join('-', $lang_code)), $allowed_languages)) {
// Qualität anschauen
if ($lang_quality > $current_q) {
// diese Sprache verwenden
$current_lang = strtolower(join ('-', $lang_code));
$current_q = $lang_quality;
// Hier die innere while-Schleife verlassen
break;
}
}
// Wenn wir im strengen Modus sind, die Sprache nicht versuchen zu minimalisieren
if ($strict_mode) {
// innere While-Schleife aufbrechen
break;
}
// den rechtesten Teil des Sprachcodes abschneiden
array_pop($lang_code);
}
}
// die gefundene Sprache zurückgeben
return $current_lang;
}
/**
* Function ensureDir checks if a directory exists, and creates it if it does not yet.
*
* @param string $filepath File path.
*
* @return void
*/
function ensureDir($filepath) {
if (!is_dir($filepath)) mkdir($filepath);
}
/**
* Function ensureJson checks that a JSON file exists. If not, it creates an empty one at the specified location.
*
* @param string $filepath File path to the JSON file.
*
* @return void
*/
function ensureJson($filepath) {
if (!file_exists($filepath) or filesize($filepath) < 2) {
file_put_contents($filepath, "[]");
}
}
/**
* Function ensuring the existence of all required files and folders.
*
* @return void
*/
function ensureEnvironment() {
$dirs = [
"contents",
"pdf",
"tex"
];
foreach ($dirs as $dir) {
ensureDir(__DIR__ . "/$dir");
}
}
/**
* Function transform escapes a string for printing in TeX
*
* @param string $transform String to transform
*
* @return string
*/
function transform($transform) {
$transform = preg_replace('#<br>#', ' ', $transform);
$transform = preg_replace('#</br>#', ' ', $transform);
$transform = preg_replace('#<br />#', ' ', $transform);
$transform = preg_replace('#&rsquo;#', '\'', $transform);
$transform = preg_replace('#'.chr(11).'#', ' ', $transform);
$transform = preg_replace('#&quot;#', '"', $transform);
$transform = preg_replace('#&amp;#', '&', $transform);
$transform = preg_replace('#•#', '&#8226;', $transform);
$transform = preg_replace('#'.chr(9).'#', '', $transform);
$transform = str_replace('&', '\\&', $transform);
$transform = str_replace('{', '\\{', $transform);
$transform = str_replace('}', '\\}', $transform);
$transform = str_replace('_', '\\_', $transform);
$transform = preg_replace('#Ä#', '&#196;', $transform);
$transform = preg_replace('#À#', '&#192;', $transform);
$transform = preg_replace('#Á#', '&#193;', $transform);
$transform = preg_replace('#à#', '&#224;', $transform);
$transform = preg_replace('#á#', '&#225;', $transform);
$transform = preg_replace('#ä#', '&#228;', $transform);
$transform = preg_replace('#Ö#', '&#214;', $transform);
$transform = preg_replace('#Ò#', '&#210;', $transform);
$transform = preg_replace('#Ó#', '&#211;', $transform);
$transform = preg_replace('#ò#', '&#242;', $transform);
$transform = preg_replace('#ó#', '&#243;', $transform);
$transform = preg_replace('#ö#', '&#246;', $transform);
$transform = preg_replace('#Ü#', '&#220;', $transform);
$transform = preg_replace('#Ù#', '&#217;', $transform);
$transform = preg_replace('#Ú#', '&#218;', $transform);
$transform = preg_replace('#ù#', '&#249;', $transform);
$transform = preg_replace('#ú#', '&#250;', $transform);
$transform = preg_replace('#ü#', '&#252;', $transform);
$transform = preg_replace('#ß#', '&#223;', $transform);
$transform = preg_replace('#Ç#', '&#199;', $transform);
$transform = preg_replace('#ç#', '&#231;', $transform);
$transform = preg_replace('##', '&#180;', $transform);
$transform = preg_replace('#é#', '&#233;', $transform);
$transform = preg_replace('#è#', '&#232;', $transform);
foreach (array("[", "]") as $toescape)
$transform = str_replace ($toescape, "$".$toescape."$", $transform);
$transform = html_entity_decode($transform, ENT_QUOTES, "utf-8" );
return $transform;
}
/**
* Function scanDirConts is a wrapper around scandir(), which removes [".", ".."].
*
* @param string $folder Folder to scan.
*
* @return string[]
*/
function scanDirConts($folder) {
return array_values(array_diff(scandir($folder), [".", "..", ".git"]));
}
// Generating PDFs
/**
* Function copyFolder copies a folder including all its contents.
*
* @param string $from Source location.
* @param string $to Target location.
*
* @return void
*/
function copyFolder($from, $to) {
mkdir ($to);
foreach (array_diff(scandir("$from"), [".", ".."]) as $file) {
copy("$from/$file", "$to/$file");
}
}
/**
* Function removeFolder deletes a folder including all its contents.
*
* @param string $folder Folder location.
*
* @return void
*/
function removeFolder($folder) {
foreach (array_diff(scandir("$folder"), [".", ".."]) as $file) {
if (is_dir("$folder/$file")) removeFolder("$folder/$file");
else unlink("$folder/$file");
}
rmdir($folder);
}
/**
* Function removeFolder deletes a folder including all its contents.
* It stops if a subfolder is younger than 60 seconds
*
* @param string $folder Folder location.
* @param string $exclude Folder for which time should not be checked.
*
* @return boolean
*/
function removeFolderGently($folder, $exclude) {
foreach (array_diff(scandir("$folder"), [".", ".."]) as $file) {
if (time() - filemtime("$folder/$file") < 10 and $file != $exclude) continue;
if (is_dir("$folder/$file")) $output = removeFolder("$folder/$file");
else if (!is_dir("$folder/$file")) unlink("$folder/$file");
}
if (count(array_diff(scandir("$folder"), [".", ".."])) == 0) rmdir($folder);
return $output;
}
/**
* Function runPDF runs LaTeX to generate a PDF file and then serves said file.
* It also does the subsequent cleanup by deleting the folder the PDF was generated in afterwards.
*
* @param string $folder Determines the folder (say, template) to use for PDF generation.
* @param string $texFilename Name of the TeX file. Used without its ending.
* @param string $filename Filename as it should be shown to the user.
* @param boolean $title Title of the overall output.
* @param boolean $lang Language. Optional.
* @param boolean $debug Enables/disables debug mode. Optional.
*
* @return void
*/
function runPDF($folder, $texFilename, $filename, $title, $lang = "de", $debug = false) {
if (!is_dir("./tmp")) mkdir("./tmp");
/* Eine eindeutige ID, beispielsweise: 4b3403665fea6 */
$uniqid = uniqid("PDF_");
copyFolder("$folder", "./tmp/$uniqid");
copy("brochure.tex", "./tmp/$uniqid/brochure.tex");
$generateUserSettings = function($lang, $title) {
$babelPackages = [
"en" => "english",
"de" => "german",
"es" => "spanish",
"hu" => "hungarian"
];
if (in_array($lang, $babelPackages)) $lan = $lang;
else $lan = "en";
return '\\usepackage[' . $babelPackages[$lan] . ']{babel}
\\def \\pageTitle {' . transform($title) . '}' . PHP_EOL;
};
$userSettings = $generateUserSettings($lang, $title);
file_put_contents("./tmp/$uniqid/pdfSettings.tex", $userSettings);
chdir("./tmp/$uniqid");
// Right now, pdflatex needs to be used. Once new packages are available, xelatex is to be preferred.
exec("pdflatex -interaction nonstopmode $texFilename.tex");
ensureDir(__DIR__ . "/pdf/$lang");
// Move output file to PDF directory.
if (file_exists(__DIR__ . "/pdf/$lang/brochure.pdf")) unlink(__DIR__ . "/pdf/$lang/brochure.pdf");
rename("brochure.pdf", __DIR__ . "/pdf/$lang/brochure.pdf");
# header("Content-type:application/pdf");
# header("Content-Disposition:inline;filename=$filename");
# readfile ("$texFilename.pdf");
chdir(__DIR__);
if (!$debug) removeFolderGently("./tmp", $uniqid);
}
// HTML Stuff
/**
* Function getHTMLHead returns the HTML for the top of the page.
*
* @param string $title Title of the page.
* @param string $contents Page contents.
* @param string $lang Language. Optional
* @param string $descriptions Page description. Optional.
*
* @return string
*/
function printHTMLPage(string $title, string $contents, string $lang = "en", string $descriptions = "") {
$output = '<!DOCTYPE html>
<html lang="' . $lang . '">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/main.css">
<title>' . $title . '</title>
<meta>' . $descriptions . '</meta>
</head>
<body id="start">
<nav id="mainNav">
<a href="#start">Top</a>
<a href="#bottom"></a>
</nav>
';
$output .= $contents . '
<footer id="bottom">
<a href="pdf/' . $lang . '/brochure.pdf" class="buttonLike">PDF</a>
</footer>
</html>';
return $output;
}
?>

197
htmlToTeX.php Normal file
View File

@ -0,0 +1,197 @@
<?PHP
/**
* File containing functions for generating PDFs from HTML contents.
*
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
*/
/**
* Converts a DOM div element to TeX.
*
* @param DOMElement|DOMText $node Element to convert.
*
* @return string
*/
function divToTeX($node):string {
$type = get_class($node);
$output = "";
if ($type === "DOMText") return $node->textContent;
else {
if ($node->tagName == "img") {
$output = "
\\begin{figure}[h]
\\begin{center}
\\includegraphics[width=\columnwidth]{../../" . transform($node->getAttribute("src")) . "}
\\end{center}
\\end{figure}
";
}
else if ($node->tagName == "ul") {
if ($node->getAttribute("class") == "dl") {
$output .= "
\\begin{description}
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "
\\end{description}
%";
}
else {
$output .= "
\\itemize{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "
}%
%";
}
}
else if ($node->tagName == "li") {
$output .= "\\item";
if ($node->getAttribute("data-title") != "") $output .= "[" . transform($node->getAttribute("data-title")) . "]{ \\hfill \\\\";
else $output .= "{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "%
}%
";
}
else if ($node->tagName == "h4") {
$output .= "\\subsection{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "%
}%
";
}
else if ($node->tagName == "h5") {
$output .= "\\subsubsection{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "%
}%
";
}
else if ($node->tagName == "div") {
$output .= "{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "%
}%
";
}
else if ($node->tagName == "a") {
if ($node->getAttribute("class") == "url") {
$output .= "\\url{" . transform($node->textContent) . "}";
}
else {
$output .= "\\href{" . $node->getAttribute("href") . "}{%
";
foreach ($node->childNodes as $childNode) {
$output .= divToTeX($childNode);
}
$output .= "
}%
";
}
}
else
print_r($node);
}
return $output;
}
/**
* Function DOMtoTeX transforms a DOM element into its proper TeX output.
*
* @param DOMElement $inputs A section element.
* @param string $folder Folder to store in.
*
* @return void
*/
function DOMtoTeX(DOMElement $inputs, string $folder) {
$centerTextTeX = function($content, $centered = false) {
if ($centered) $output = "
\centerVertically{
$content
}
";
else $output = $content;
return $output;
};
$concordanceIDFile = [
"introduction" => "contentsIntroduction.tex",
"frontend" => "contentsFrontend.tex",
"learnMore" => "contentsTail.tex",
"contact" => "contentsContact.tex",
];
$chapterID = $inputs->getAttribute("id");
$chapterTitle = $inputs->getElementsByTagName("h2")[0]->nodeValue;
$output = "%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%% Chapter: $chapterID
%
\\chapter{" . transform($chapterTitle) . "}%
";
foreach ($inputs->childNodes as $section) {
if (!isset($section->tagName) or $section->tagName != "div") continue;
foreach ($section->childNodes as $sectionElem) {
if (!isset($sectionElem->tagName)) continue;
if ($sectionElem->tagName == "h3") {
$output .= "
\\section{" . transform($sectionElem->textContent) . "}%";
}
else if ($sectionElem->tagName == "div") {
if ($sectionElem->getAttribute("class") == "centerVertically") $centered = true;
else $centered = false;
$sectionOutput = "";
foreach ($sectionElem->childNodes as $node) {
$sectionOutput .= divToTeX($node);
}
$output .= $centerTextTeX($sectionOutput, $centered);
$output .= "%
\\newpage%
%";
}
}
}
if (isset($concordanceIDFile[$chapterID])) {
if (!file_exists(__DIR__ . "/$folder")) mkdir(__DIR__ . "/$folder");
file_put_contents(__DIR__ . "/" . $folder . "/" . $concordanceIDFile[$chapterID], $output);
}
}
?>

53
index.php Normal file
View File

@ -0,0 +1,53 @@
<?PHP
/**
* This file serves the HTML output of the main about page.
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Load required files and ensure environment.
require_once __DIR__ . "/functions.php";
require_once __DIR__ . "/htmlToTeX.php";
ensureEnvironment();
// Find out current language
$availableLangs = scanDirConts(__DIR__ . "/contents"); // Those languages are available, for which there are files
foreach ($availableLangs as $key => $value) {
$availableLangs[$key] = str_replace(".htm", "", $value);
}
if (isset($_GET['lang'])) $lang = $_GET['lang'];
else $lang = lang_getfrombrowser($availableLangs, 'de', null, false);
// Load HTML document to PHP DOMDocument
$content = new DOMDocument();
$content->load(__DIR__ . "/contents/$lang.htm");
// Find out title
$title = $content->getElementsByTagName("h1")[0]->nodeValue;
// Generate PDF if need be.
// if (filemtime(__DIR__ . "/tex/$lang/contentsFrontend.tex") < filemtime(__DIR__ . "/contents/$lang.htm")) {
foreach ($content->getElementsByTagName("section") as $c) {
DOMtoTeX($c, "tex/$lang");
}
runPDF("tex/$lang", "brochure", "brochure.pdf", $title, $lang, true);
# }
// Print HTML page.
$content = file_get_contents(__DIR__ . "/contents/$lang.htm");
$content = str_replace("\\today", date("Y-m-d", filemtime("contents/$lang.htm")), $content);
echo printHTMLPage("about:" . $title, $content, $lang, true);
?>

BIN
media/06073815564.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB