Innholdsblokker
Disse kommer i to versjoner:
Innholdsblokker som de ulike sidetypene kan bruke direkte. Disse har først og fremst en semantisk funksjon; de markerer hvilken funksjon innholdet i blokken har på siden.
Innholdsblokker som kun er støtteblokker for blokkene i forrige punkt, og som de ulike sidetypene ikke skal referere til direkte. Disse implementerer støtte for den ekstra funksjonaliteten vi ønsker at ArtikkelBlock skal ha, f.eks SVG-figurer, TeX-uttrykk og så videre. Alle andre blokktyper enn de nevnt i forrige punkt er av denne typen.
Blokktypene som er ment å kunne brukes utenfra ligger i modulen artikkel.blocks
,
og kan importeres rett fra den modulen. Se src/artikkel/blocks/__init__.py
.
Støtteblokkene er ikke tilgjengelig via artikkel.blocks
,
men er tilgjengelig via relative importer.
Se f.eks i src/artikkel/blocks/artikkel.py
hvordan ArtikkelBlock
importerer støtteblokkene via:
from .callout import CalloutBlock
from .comment import CommentBlock
from .index import IndexBlock
from .tex import TexBlock
from .tikz import TikzBlock
from .subpages import SubpagesBlock
from .svg import SvgBlock
from .shiny import ShinyBlock
ArtikkelBlock
- Funksjon:
Brødtekst
- Kode:
src/artikkel/blocks/artikkel.py
- Template:
Ingen egen template (inkluderes i Artikkel via
include_block
)
Denne innholdsblokken brukes i hoveddelen (brødteksten) av en Artikkel.
Består av kun én blokktype, som gjentas en gang for hvert avsnitt på siden:
ArtikkelSectionBlock (ArtikkelSectionBlock)
Dette er gjort for å kunne rendre hvert enkelt avsnitt inne i sitt eget
<section>
-element slik at vi
har muligheten til å lage kollapsbare avsnitt i mobilversjonen,
slik som f.eks Wikipedia har («trykk på h2-overskriften, så skjules avsnittet»).
For å kunne få til dette må vi både ha et wrapper-element rundt alle blokkene
som hører til samme avsnitt, og vi må ha kontroll på hvordan både <h2>
-elementet og
wrapper-elementet rendres.
En annen årsak er at vi ikke har kontroll over hvordan overskrifter inne i en
RichTextBlock
rendres, og at de pr. Wagtail 2.4 rendres uten id-attributt.
Dette gjør det vanskelig å på et senere tidspunkt lage en blokktype som genererer
innholdsfortegnelse på siden (liste over <a href="#id">...</a>
uten å innføre
en egen innholdsblokk da. Hvis publiseringssystemet da er fylt med mye innhold, vil
det være veldig mye arbeid forbundet med å flytte overskriftene fra RichTextBlock
til egne innholdsblokker. Denne innholdsblokken er altså opprettet for å være føre var,
og ikke fordi vi på nåværende tidspunkt trenger å spesialbehandle overskrifter.
ArtikkelSectionBlock
- Funksjon:
Avsnitt
- Kode:
src/artikkel/blocks/artikkel.py
- Template:
src/artikkel/templates/artikkel/artikkel_section_block.html
Denne innholdsblokken representerer et avsnitt, og består av en overskrift og en eller flere andre innholdsblokker av disse to hovedtypene:
Wagtails innebygde blokker:
Rik tekst (RichTextBlock)
Vedlegg (DocumentBlock)
Våre egendefinerte blokker (unntatt LeadBlock):
Infoboks (CalloutBlock)
Embedding av interaktive R-applikasjoner (ShinyBlock)
Kommentar (CommentBlock)
Innholdsfortegnelser (liste over eksempler, videoer, etc.) (IndexBlock)
Liste over undersider (SubpagesBlock)
PNG-figur/JPEG-bilder (PictureBlock)
Forhåndsdefinert tekst (PredefinedTextBlock)
SVG-figur (SvgBlock)
TeX-uttrykk (TexBlock)
Tikz-figur (TikzBlock)
CalloutBlock
- Funksjon:
Infoboks
- Kode:
src/artikkel/blocks/callout.py
- Template:
src/artikkel/templates/artikkel/callout_block.html
Infoboksen består av en overskrift + brødtekst, og kan styles i flere varianter:
Definition
Theorem
Proof
Information
Question
Warning
Forskjellen mellom de ulike bokstypene er fargen, om boksen i utgangspunktet er kollapset (brødteksten vises først når man klikker på overskriften), og om det legges til tekst foran tittelen.
For å oppfordre til riktig bruk av denne blokktypen, kan brødteksten kun inneholde:
En begrenset variant av
RichTextBlock
(vanlig tekst, uthevet tekst, nummererte og unummererte lister og lenker til interne/eksterne sider eller dokumenter).TeX-kode (TexBlock).
Tikz-figurer (TikzBlock).
Forhåndsdefinert tekst (PredefinedTextBlock).
Mulighet for H2/H3/H4-overskrifter, video, bilder og kursiv tekst er altså fjernet,
se bruken av RichTextBlock(features=[...])
i callout.py
.
CodeBlock
- Funksjon:
Listing av programkode
- Kode:
src/artikkel/blocks/code.py
- Template:
src/artikkel/templates/artikkel/code_block.html
Blokk for kodelistinger, med syntax highlighting og knapp for å kopiere kodeblokken til utklippstavlen.
Følgende språk støttes:
Julia
MATLAB
Octave
Python
R
Wagtail-admingrensesnittet er modifisert for å gi monospaced font også i redigeringsgrensesnittet for denne blokken, se Ekstra CSS.
CommentBlock
- Funksjon:
Kommentar
- Kode:
src/artikkel/blocks/comment.py
- Template:
src/artikkel/templates/artikkel/comment_block.html
Gjør det mulig å legge inn en kommentar som kun vises i redigeringsmodus, og ikke rendres på siden.
IndexBlock
- Funksjon:
Vise innholdsfortegnelse
- Kode:
src/artikkel/blocks/index.py
- Template:
src/artikkel/templates/artikkel/index_block.html
src/artikkel/templates/artikkel/index_video_block.html
(videooversikten)src/artikkel/templates/artikkel/index_other_block.html
(beviser/eksempler/regneregler)
Denne innholdsblokken viser en innholdsfortegnelse over alle ressurser av en bestemt type som finnes i hierarkiet under den artikkelen man velger å vise innholdsfortegnelsen for.
Den kan brukes til å liste opp alle:
artikler
beviser
eksempler
regneregler
videoer
enten for hvert kapittel (for en valgt side på nivå 1) eller for nettstedet som helhet (hvis man velger startsiden).
Blokken prøver å være smart: En innholdsfortegnelse for et enkeltavsnitt skrives ut uten overskrift, mens en innholdsfortegnelse for hele nettstedet vises gruppert etter kapittel.
Formatteringen kan variere fra ressurstype til ressurstype, avhengig av om det kun listes opp lenker til andre artikler, eller om det også lenkes til videoer og nedlastbare PDF-filer:
Artiklene må være satt til riktig sidetype og sidetypen må være markert som eksempel/bevis/regneregel (se Page Type) for å bli listet opp på riktig sted.
Opplisting |
Innhold |
---|---|
Artikler (buggy!) |
|
Beviser |
|
Eksempler |
|
Regneregler |
|
Videoer |
|
Opplisting av hele eksamenssett støttes ikke av denne blokken.
JSXGraphBlock
- Funksjon:
Embedding av JSXGraph-applikasjoner.
- Kode:
src/artikkel/blocks/jsxgraph.py
- Template:
src/artikkel/templates/artikkel/jsxgraph_block.html
En JSXGraph-boks består av feltene:
Figurtekst (caption)
Javascript-kode (applikasjonen selv)
Bredde og høyde (minimum 200x200, maksimum 800x600)
For å unngå kollisjon mellom variabelnavn på tvers av grafer (hvis det finnes to eller flere grafer på en og samme side), inkluderes javascript-koden i en closure/anonym funksjon. Denne funksjonen kalles umiddelbart etter at den er definert, og får to parametre:
board_id: HTML element-ID til canvasen JSXGraph rendrer applikasjonen i.
html_id: HTML element-ID til et lite område utenfor canvasen der applikasjonen kan tegne opp inputfelter eller annen output. Feltet er plassert under canvasen, mellom canvas og figurtekst.
Disse er tilgjengelige som forhåndsdefinerte variabler i JSXGraph-koden.
board_id
brukes typisk som argument til initBoard()
ved initialisering av JSXGraph:
var board = JXG.JSXGraph.initBoard(board_id, { ... });
html_id
brukes kun hvis applikasjonen har behov for å tegne opp input/output-felter
utenfor selve JSXGraph-canvasen. Disse kan da tegnes opp ved å fylle elementet med
ID html_id
med ønsket HTML-kode.
document.getElementById(html_id).innerHTML += '...';
Eksempelet «Adding events»
viser hvordan applikasjonen kan generere output.
I dette eksempelet brukes hardkodet element-ID myOutput
,
her bør javascript-koden referere til variabelen html_id
i stedet for å bruke tekststrengen 'myOutput'
.
Eksempelet «Change Equation of a Graph»
viser interaksjon mellom inputfelter og JSXGraph-applikasjonen.
Siden Wagtail kjører JSXGraph-applikasjonen i sin egen closure,
vil i utgangspunktet ikke callback-funksjonen doIt()
som defineres i applikasjonen
være tilgjengelig fra andre steder på nettsiden, og det vil ikke fungere å referere til
den i <input>
-elementene.
For å gjøre callback-funksjonen tilgjengelig i globalt skop må den i stedet defineres som
en attributt på window
-objektet:
// Ikke slik:
function doIt() {
[...]
}
// Men slik:
window.doIt = function() {
[...]
}
Ideelt sett bør heller ikke inpufeltenes element-ID hardkodes, men genereres ut fra html_id
:
// Ikke slik:
document.getElementById(html_id).innerHTML += '<input type="text" id="eingabe" value="Math.sin(x)*Math.cos(x)">';
eval("function f(x){ return "+document.getElementById("eingabe").value+";}");
// Men slik:
input_id = html_id + '_input'
document.getElementById(html_id).innerHTML += '<input type="text" id="' + input_id + '" value="Math.sin(x)*Math.cos(x)">';
eval("function f(x){ return "+document.getElementById(input_id).value+";}");
og tilsvarende i callback-funksjonen og andre steder der getElementById()
brukes.
Da er man sikret mot navnekollisjoner hvis man har flere grafer på hver side.
I motsetning til andre figurtyper blir JSXGraph ikke vist i full bredde uten marg på små enheter. Hvis panorering er enablet i figuren, og figuren dekker hele den lille mobilskjermen, mister brukeren muligheten til å scrolle opp og ned på nettsiden, og blir stuck inne i figuren. Figuren må derfor ha en smal venstremarg slik at man kan nå tak i sidebakgrunnen for å scrolle forbi figuren. Av samme grunn er også høyden på figuren begrenset oppad til 600px, for å unngå at den dekker hele det synlige området på skjermen.
LeadBlock
- Funksjon:
Ingress
- Kode:
src/artikkel/blocks/artikkel.py
- Template:
Ingen egen template (inkluderes i Artikkel via
include_block
)
Egen innholdsblokk for ingressen i en Artikkel. Består av:
Rik tekst (
RichTextBlock
)
Innholdet er begrenset til kun uthevet tekst, punktlister og lenker. Det er kun mulig å ha én RichTextBlock inne i en LeadBlock.
PictureBlock
- Funksjon:
PNG-figurer og JPEG-bilder
- Kode:
src/artikkel/blocks/picture.py
- Template:
src/artikkel/templates/artikkel/picture_block.html
Blokk for bilde + påkrevd bildetekst.
PredefinedTextBlock
- Funksjon:
Sette inn en blokk med forhåndsdefinert tekst
- Kode:
src/artikkel/blocks/predefined_text.py
- Template:
src/artikkel/templates/artikkel/predefined_text_block.html
Setter inn en forhåndsdefinert tekstblokk.
Forhåndsdefinerte tekstblokker må legges inn som Predefined Text-snippets.
ShinyBlock
- Funksjon:
Embedding av Shiny-applikasjoner
- Kode:
src/artikkel/blocks/shiny.py
- Template:
src/artikkel/templates/artikkel/shiny_block.html
Applikasjonens URL + figurtekst må oppgis.
Applikasjonen blir embeddet i en <iframe>, og blokken forsøker å resize iframen automatisk slik at hele applikasjonen vises. For at dette skal fungere må Shiny-applikasjonen skrives på en bestemt måte. Se https://www.cultureofinsight.com/blog/2018/03/15/2018-03-15-responsive-iframes-for-shiny-apps/ for detaljert forklaring på hvordan resizingen fungerer. Kortversjonen er at ui-variabelen må inkludere et script helt først, og en HTML-tag til slutt:
ui <- fluidPage(
tags$head(
tags$script(src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/3.6.2/iframeResizer.contentWindow.min.js",
type="text/javascript")
),
# Resten av ui-elementene plasseres her ...
HTML('<div data-iframe-height></div>')
)
I tillegg må også siden som inneholder iframen inkludere et script. Dette gjøres via base.html. (Scriptet inkluderes på alle sider, ikke bare de som embedder Shiny-applikasjoner.)
SubpagesBlock
- Funksjon:
Vise artikkelens undersider
- Kode:
src/artikkel/blocks/subpages.py
- Template:
src/artikkel/templates/artikkel/subpages_block.html
Denne innholdsblokken lager en liste over artikkelens undersider. Kun de direkte undersidene vises, og ikke alle undersider rekursivt.
Det er også mulig å velge å vise undersidene til en annen artikkel.
Blokken skriver ut listen uten noen form for overskrift.
SvgBlock
- Funksjon:
SVG-figurer
- Kode:
src/artikkel/blocks/svg.py
- Template:
src/artikkel/templates/artikkel/svg_block.html
Denne innholdsblokken implementerer støtte for SVG-figurer.
Wagtails bildemodell støtter kun PNG/JPG, så vi henter figuren fra et opplastet dokument.
Støtte for å endre størrelsen på figuren mangler.
TexBlock
- Funksjon:
Støtte for «display mode» TeX
- Kode:
src/artikkel/blocks/tex.py
- Template:
src/artikkel/templates/artikkel/tex_block.html
Det er mulig å skrive matematikk inne i en RichTextBlock
(både inline ved å bruke \( ... \)
, og i display mode ved å bruke \[ ... ])
),
men diplay mode-matematikk som skrives inn over flere linjer fungerer
ikke så godt, siden RichTextBlock
tolker hardt linjeskift som nytt avsnitt,
og rendrer:
\[
...
\]
som:
<p>\[</p>
<p>...</p>
<p>\]</p>
som gjør at uttrykket ignoreres av Mathjax, siden det ikke forekommer i en og samme <p>.
En TexBlock er bare et flerlinjes inputfelt som rendres inne i et og samme avsnitt.
Blokken lar deg velge mellom vanlig display mode eller et align-environment.
Bruk da &
som kolonneseparator, som ellers i TeX. Eksempel:
a =& ~ \sin^2(x) + \cos^2(x) \\
=& ~ 1
TikzBlock
- Funksjon:
Inline Tikz-figurer
- Kode:
src/artikkel/blocks/tikz.py
- Template:
src/artikkel/templates/artikkel/tikz_block.html
Denne innholdsblokken lar deg skrive inn Tikz-kode direkte og få generert en SVG- eller PNG-figur on-the-fly.
Det er mulig å velge hvilken LaTeX-kompilator som skal brukes
(pdflatex
eller lualatex
).
For lualatex
finnes det også en variant som kompilerer til PNG.
Det er anbefalt å bruke SVG slik at figuren blir skalerbar og ser bra ut på høyoppløste skjermer, men hvis figuren er veldig komplisert kan den resultere i en veldig stor SVG-fil som medfører at siden lastes tregt. I så fall kan PNG-kompilatoren brukes for å redusere figurstørrelsen. Dette er mest aktuelt når tikz-figuren inneholder veldig mange objekter (ekstremt finmasket grid, etc.).
PNG-figurene er ikke skalerbare, men PNG-kompilatoren forsøker å bøte på dette ved å kompilere figurene i dobbel oppløsning (@2x) og skalere dem ned til 50% ved visning, slik at figurene ikke ser altfor ille ut på høyoppløste skjermer.
Bildefilen caches via Djangos cache framework.
For å legge til nye kompilatorer må det defineres en ny subklasse av
TikzCompiler
, og klassen må dekoreres med @TikzCompiler.register()
.
For et hypotetisk eksempel acmetex
:
@TikzCompiler.register('acmetex')
class TikzCompilerAcmetex(TikzCompiler):
def compile(self, preamble, code):
...
I tillegg må kompilatoren gjøres tilgjengelig i nedtrekksmenyen i
redigeringsgrensesnittet. Dette gjøres ved å utvide TikzBlock.compiler
.
class TikzBlock(StructBlock):
[...]
compiler = ChoiceBlock(default='lualatex', choices=[
('lualatex', 'lualatex to SVG'),
('pdflatex', 'pdflatex to SVG'),
('acmetex', 'acmetex to SVG'),
])