@moRtenDk #dRupaLTWIg #srijAnwW
tHemIngSRIjAN wEDNeSDAy WEbINArS
DRUpAL
@moRtenDk #dRupaLTWIg #srijAnwW
DRUpAl 8 BEtA 14 (DRuPAL.ORG/DRUpAl-8.0.0-BEtA1)
WEBiNAR D8 THeMe GIThUB.cOM/mORTeNDK/WEBiNAR-SRIjANWw
dOwnLoad
@moRtenDk #dRupaLTWIg #srijAnwW
@MorTenDk
CLAsSy MAInTAInERGEEk
RÖYALe THE ANGrY THEmER
TaG1 CONsULTiNG
@moRtenDk #dRupaLTWIg #srijAnwW
sTocKhoLm sYndRome
@moRtenDk #dRupaLTWIg #srijAnwW
ACTuAL dRUPaL7 MARkUP
@moRtenDk #dRupaLTWIg #srijAnwW
“IT’S A FEAtUrE”
dIviTis<DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV><DIV>
</DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV></DIV>
@moRtenDk #dRupaLTWIg #srijAnwW
5000LINeS Of PHpTEMpLATe.PHp
TotAllY oK
@moRtenDk #dRupaLTWIg #srijAnwW
<div class=“foo bar baz foo-more-more bar-more-yet another one”>
fEatUreTHE CLAsS SoUP IS AnOTHeR
@moRtenDk #dRupaLTWIg #srijAnwW
nO mOre aAaaRgh!
@moRtenDk #dRupaLTWIg #srijAnwW
nEw
tHemE eNgiNe
GOOd-BYe PHPtEMPlAtEHELlO TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE fUncTioNs
dEad!
@moRtenDk #dRupaLTWIg #srijAnwW
tWig tEmpLatEs
EVErYTHiNG iS
BLOcK.HtML.tWiG
MARk.HTmL.TwIG
TABlE.HtML.tWiG
PAGe.HTmL.TwIGNODe.HTmL.TwIG
VIEw.HTmL.TwIG
FIElD.HtML.tWiG IMAgE-WiDGEt.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE iS iN cOntRolThE
OF mARKuP & CSs
@moRtenDk #dRupaLTWIg #srijAnwW
uNleArn pHptEmpLa
te<? pHP dIe(‘PHPtEMPlAtE’) ?>
@moRtenDk #dRupaLTWIg #srijAnwW
REAdY?
@moRtenDk #dRupaLTWIg #srijAnwW
tWigDRUpAl 8
@moRtenDk #dRupaLTWIg #srijAnwW
IS a “MODeRN” TEmPLAtE LaNGUaGe -> sYMPhONY
USEd BY OTHeR SySTEmS + ItS EaSY tO LeARN :)
tWig
@moRtenDk #dRupaLTWIg #srijAnwW
{{ var }}
{# comment #}
oUtpUt
@moRtenDk #dRupaLTWIg #srijAnwW
{{ data.is.here }}
{{ also.this[#hashtags] }}
vAr DriLliNg$yo[‘drupal_where ’]->is[‘und’][0]->my_data7
@moRtenDk #dRupaLTWIg #srijAnwW
{{ var|makemepretty(‘now’) }}
fUncTionPIBe
TWIg FUnCTIoNVaR
@moRtenDk #dRupaLTWIg #srijAnwW
{{ username|uppercase }}
MORTENDK
fUncTion(mortendk)
@moRtenDk #dRupaLTWIg #srijAnwW
{{ ‘Copenhagen’|t }} København
{% trans %} Copenhagen {{ var }} {% endtrans %}
tRanSlaTe
@moRtenDk #dRupaLTWIg #srijAnwW
{% if person=“mortendk” %} <h1>Loves Drupal8</h1> {% endif %}
cOntRol
@moRtenDk #dRupaLTWIg #srijAnwW
{{ sushi|raw}}
aUtoEscApe
SECuRITy IS SOMeTHInG DEVeLOPeRS LIKe
@moRtenDk #dRupaLTWIg #srijAnwW
{% set foo = “bar” %}
{{ foo }}
bar
cReaTe Var
@moRtenDk #dRupaLTWIg #srijAnwW
TWIg.SEnSIOlABS.ORG/DOCuMENtATIoN
tWig
@moRtenDk #dRupaLTWIg #srijAnwW
cLasSyTHE DRUpAl 8 BAsE ThEmE
@moRtenDk #dRupaLTWIg #srijAnwW
7corE
claSsy
<HTmL> .CSs CLAsS=“FoO”
<HTmL> .CSs CLAsS=“FoO”
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
corE claSsy
my ThemE
? barTik
sevEn$VArS
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
<div> {{ foo }} </div>
corE claSsy“MY tHEMe”
NOT DEFiNeD
@moRtenDk #dRupaLTWIg #srijAnwW
bAseTheMe
<div class=“node node—article”> {{ foo }} </div>
corE claSsy“MY tHEMe”
BASe THeME: CLAsSY
@moRtenDk #dRupaLTWIg #srijAnwW
gRouPing
@moRtenDk #dRupaLTWIg #srijAnwW
tEmpLatE gRouPsLAYoUT
FIElD
DATaSeT
VIEwS
BLOcK CONtENT-EDIt
CONtEnT
MISc
USEr
NAViGATiON
FORm
@moRtenDk #dRupaLTWIg #srijAnwW
dEfiNe BasEthEme
base theme: classy
THEmENAmE.InFO.yML
@moRtenDk #dRupaLTWIg #srijAnwW
sEtupSETtING UP a THeME
@moRtenDk #dRupaLTWIg #srijAnwW
[ROOt]/ThEMEs/[THEmENAmE]
I LiVE wHERe NOw ?
@moRtenDk #dRupaLTWIg #srijAnwW
tHemE cOnfIg FilEs
*.InFO.yMl *.LiBRArIES.YML *.BrEAKpOINtS.YmL *.ThEmE
@moRtenDk #dRupaLTWIg #srijAnwW
*.inFo.YmlTHEmE CoNFIgURAtION, CSs & jS
@moRtenDk #dRupaLTWIg #srijAnwW
BASiC INFo
REGiOnS
LIBrARIeS
REMoVE cSS
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
*.liBraRieS.yMlADD Js & CSs FIlES
@moRtenDk #dRupaLTWIg #srijAnwW
.INfO.YmL
.LIbRARiES.yML
@moRtenDk #dRupaLTWIg #srijAnwW
NAMe
DEPeNDEnCIEs
CSS FILeS
*.liBraRieS.yMl
JS fILEs
@moRtenDk #dRupaLTWIg #srijAnwW
global: version: VERSION css: component: css/user/user.theme.css: {} theme: css/layout.css: {}
cSs LibBASe LAYoUt COMpONEnT STAtE THEmE
@moRtenDk #dRupaLTWIg #srijAnwW
{{ attach_library('classy/book-navigation') }}
cSs FilEs In TemPlaTe
@moRtenDk #dRupaLTWIg #srijAnwW
[*].BreAkpOinTs.YmlRESpONSiVE iMAGeS
@moRtenDk #dRupaLTWIg #srijAnwW
*.BrEAKpOINtS.YmL
@moRtenDk #dRupaLTWIg #srijAnwW
*.BrEAKpOINtS.YmL
@moRtenDk #dRupaLTWIg #srijAnwW
[*].TheMe
WAS PHPtEMPlATE.PhP
@moRtenDk #dRupaLTWIg #srijAnwW
.TheMe
.LIbRARiES.yML
.THeME
@moRtenDk #dRupaLTWIg #srijAnwW
tOolsHOW TO fIND STUfF & DEbUg
@moRtenDk #dRupaLTWIg #srijAnwW
sEttIngS.pHp
if (file_exists(__DIR__ . '/settings.local.php')) { include __DIR__ . '/settings.local.php'; }
COPy: SiTES/EXAmPLE.SETtINGs.LOcAL.pHP
TO: SITeS/DeFAUlT/SeTTInGS.lOCAl.PHp
UNCoMMEnT In SEtTINgS.PhP
@moRtenDk #dRupaLTWIg #srijAnwW
DOWnLOAd DEvEL mODUlE INStALL DEVeL + KINt
INStALL DRUsH DRUsH En KInT
DOCs.DRuSH.oRG/eN/MaSTEr/INsTALl/
dEveL mOduLe
@moRtenDk #dRupaLTWIg #srijAnwW
dIsaBle csS cAche
@moRtenDk #dRupaLTWIg #srijAnwW
dEbuG fTw
LETs LOoK At THe THeME nOw (LIvE CoDE dEMO)
@moRtenDk #dRupaLTWIg #srijAnwW
FILe NAmE SuGGEsTIOnS
@moRtenDk #dRupaLTWIg #srijAnwW
kInt{{ kint( foo ) }}
KRUmO FoR DrUPAl 8
{{ content.field_image }}
@moRtenDk #dRupaLTWIg #srijAnwW
TWIg DEbUg: SITeS/AlL/DeFAUlT/SeRVIcES.yMl
DRUsH Cr {{ KInT(FoO) }}
dEbuG:
@moRtenDk #dRupaLTWIg #srijAnwW
tEmpLatE sTruCtuRe
HOW IS iT StRUCtUREd IN D8
@moRtenDk #dRupaLTWIg #srijAnwW
hTml
HTMl.HTmL.TwIG
CSS + Js
HEAdER
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIG
pAge
PAGe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIGREGiON.hTML.TWIg
REGiON.hTML.TWIg
REGiON.hTML.TWIg
rEgiOn's
PAGe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
HTMl.HTmL.TwIG
cOntEnt
BLOcK.HtML.tWiG NODe.HTmL.TwIG VIEw.HTmL.TwIG
REGiON.hTML.TWIg
@moRtenDk #dRupaLTWIg #srijAnwW
nOde
FIElD.HtML.tWiG
NODe.HTmL.TwIG
FIElD.HtML.tWiGFIElD.HtML.tWiG
FIElD-—IMAgE.HtML.tWiGFIElD.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
aLl The fiEldsFIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG FIElD.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
lAyoUtTHE MAGiC Of WItHOUt
@moRtenDk #dRupaLTWIg #srijAnwWNODe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
{{ content|without(‘field’) }}
wIthOut fuNctIonPIBe
NAMeTWIg FUnCTIoN
VaR
@moRtenDk #dRupaLTWIg #srijAnwW
conTeNt
imaGe
tagS
lAyoUt
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT }}
{{ imAge }}
{{ content }}
{{ teXt }} {{ taGs }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(*) }}
{{ imAge }}
{{ content|without(‘image’) }}
{{ content.image }}
{{ teXt }} {{ taGs }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(**) }}
{{ imAge }}
{{ content|without(‘image’,‘tags’) }}
{{ content.image }}
{{ teXt }} {{ taGs }}
{{ content.tags }}
@moRtenDk #dRupaLTWIg #srijAnwW
{{ coNtenT | WithOut(**) }}
{{ imAge }}
{{ content|without(‘image’,‘tags’) }}
{{ content.image }}
{{ teXt }} {{ taGs }}
{{ content.tags }}
{{ neW }}
NEW FIElD
@moRtenDk #dRupaLTWIg #srijAnwW
CONtEnTnOde.htMl.Twig
@moRtenDk #dRupaLTWIg #srijAnwW
CONtENT.FIElD_ImAgE
@moRtenDk #dRupaLTWIg #srijAnwW
CONtENT.FIElD_TaGS
@moRtenDk #dRupaLTWIg #srijAnwW
mArkUpOVErWRItE FiELDs
@moRtenDk #dRupaLTWIg #srijAnwW
nOde.htMl.Twig
@moRtenDk #dRupaLTWIg #srijAnwW
fIle naMe SugGesTioNs
@moRtenDk #dRupaLTWIg #srijAnwW
fIelD-[Foo].hTml.twIg
FIElD--nODE--FIeLD-tAGS--ARtICLe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
@moRtenDk #dRupaLTWIg #srijAnwW
<div {{ attributes }}> class=“foo” data-drupal-foo aria-hidden=“true”
aTtrIbuTes
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSY
<DIv CLaSs=“FOO FOO-BAR FOO-BAR-BaZ”>
*.TpL.PhP
THEmE FuNCTiOnS
PREpROCeSS
$VArS
DRUpAL7
7
@moRtenDk #dRupaLTWIg #srijAnwWNODe.HTmL.TwIG
@moRtenDk #dRupaLTWIg #srijAnwW
{% set classes = [ 'tags', 'field-' ~ field_name|clean_class ~ ' ] %}
<div {{ attributes.addClass(classes) }}>…</div>
<div class=“tags field-tags”>…
aDdcLass
@moRtenDk #dRupaLTWIg #srijAnwW
<i {{ attributes.removeClass(red) }}> … </i>
<i class=“blue”>…</i>
<div class=“red blue”> … </div>BAD MODuLE oUTPuT
rEmoVe ClaSs
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe”>
ESSeNTIaL ClASSeS Ex: “IS-vISIbLE”
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe MOdUlE”>
$vaR[‘attRibuTes’]->AddCLass(‘modUle’)
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe MOdULE THEmE”>
{{ ATtRIBuTES.ADDcLASs(‘THEmE’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“CORe THeME”>
{{ ATtRIBuTES.REMoVe(‘MODuLE’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
CLAsSYMODuLECORe
<DIv CLaSs=“THEmE”>
{{ ATtRIBuTES.REMoVe(‘MODuLE’,’CORe’) }}
@moRtenDk #dRupaLTWIg #srijAnwW
jS- PreFix
<DIv CLaSs=“JS-fOO fOO”>…
$(.jS-FoO) .FOo{…}
@moRtenDk #dRupaLTWIg #srijAnwW
<div class="blablabla"> {{ attributes .removeClass(‘blablabla’) .addClass(‘hero-main’) .setAttribute('id', 'top') }} <div id="top" class="hero-main">
aTtrIbuTes
@moRtenDk #dRupaLTWIg #srijAnwW
tWigBloCkMORe COoLNEsS FrOM tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
{% block foo %} {% endblock %}
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
datA (pAge.Html.twiG)
(paGe-—froNt.hTml.Twig)
{% extends "page.html.twig" %}
PAGe.HTmL.TwIGD8
datA (pAge.Html.twiG)
@moRtenDk #dRupaLTWIg #srijAnwW
PAGe.HTmL.TwIG
PAGe—FROnT.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
PAGe.HTmL.TwIG
PAGe—FROnT.HtML.tWiG
@moRtenDk #dRupaLTWIg #srijAnwW
CAUsE WhAT cOULd GO WROnG…
lIve deMo
@moRtenDk #dRupaLTWIg #srijAnwW
DRUpAL.oRG/tHEMe-GUiDe/8
DRUpAL.oRG/cODInG-StANDaRDS/CSS
SMAcSS.cOM
TWIg.SEnSIOlABS.ORG/DOCuMENtATIoN
lInks
@moRtenDk #dRupaLTWIg #srijAnwW
dOwnLoaD d8
BETa 14! - ONlY 11 BLoCKErS LeFT
DRUpAL.oRG/dRUPaL8
@moRtenDk #dRupaLTWIg #srijAnwW
WEEkLY mEETiNG’S THUrSDAy 1700 CEt
#DruPalTwig
@moRtenDk #dRupaLTWIg #srijAnwW
USE TWItTER #SRiJANwW
QUEsTIOnS, cOMMeNTS & FEeDBAcK @MOrTENdK
qUesTioNs