Compare commits
6 commits
19ea597528
...
928e3afebd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
928e3afebd | ||
|
|
48932f2b80 | ||
|
|
45bcde6d70 | ||
|
|
6ec0d96d43 | ||
|
|
b0fffe4f0a | ||
|
|
981140da28 |
BIN
.DS_Store
vendored
Normal file
BIN
content/images/.DS_Store
vendored
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 14 KiB |
BIN
content/images/craftletter.zip
Normal file
BIN
content/images/craftletter/.DS_Store
vendored
Normal file
BIN
content/images/craftletter/favicon.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
85
content/images/craftletter/favicon.svg
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="29.989243mm"
|
||||
height="29.989243mm"
|
||||
viewBox="0 0 29.989243 29.989242"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="favicon.svg"
|
||||
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showguides="true"
|
||||
inkscape:zoom="2.0186728"
|
||||
inkscape:cx="14.365874"
|
||||
inkscape:cy="58.206559"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1351"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g19" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="g19"
|
||||
transform="translate(-6.494133,-6.033493)">
|
||||
<circle
|
||||
style="fill:#249bb3;fill-opacity:1;stroke-width:0.264583"
|
||||
id="path22"
|
||||
cx="21.488754"
|
||||
cy="21.028114"
|
||||
r="14.994621" />
|
||||
<g
|
||||
id="g18"
|
||||
transform="matrix(1.0220008,0,0,1.0220008,4.9074989,-32.198722)"
|
||||
style="fill:#ffffff">
|
||||
<path
|
||||
d="m 10.061962,40.811205 v 21.591448 h 13.81621 l -0.478,-3.432865 -9.06043,-0.03307 v -1.414384 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399459 0,-0.221405 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004012 h -1.91151 c -0.22141,0 -0.39946,-0.178569 -0.39946,-0.399975 0,-0.221405 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399975 0.39946,-0.399975 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399458 0,-0.221406 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399458 0.39946,-0.399458 h 1.91151 v -1.893426 z"
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:2.53699"
|
||||
id="path6" />
|
||||
<path
|
||||
d="m 14.339742,42.704631 h -1.91151 c -0.22141,0 -0.39946,0.178052 -0.39946,0.399458 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path8" />
|
||||
<path
|
||||
d="m 14.339742,45.508077 h -1.91151 c -0.22141,0 -0.39946,0.17857 -0.39946,0.399976 0,0.221405 0.17805,0.399458 0.39946,0.399458 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path10" />
|
||||
<path
|
||||
d="m 14.339742,48.31204 h -1.91151 c -0.22141,0 -0.39946,0.178053 -0.39946,0.399459 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 14.339742,51.115487 h -1.91151 c -0.22141,0 -0.39946,0.178569 -0.39946,0.399975 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path14" />
|
||||
<path
|
||||
d="m 14.339742,53.91945 h -1.91151 c -0.22141,0 -0.39946,0.178054 -0.39946,0.399459 0,0.221406 0.17805,0.399975 0.39946,0.399975 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path16" />
|
||||
<path
|
||||
d="m 14.339742,56.722896 h -1.91151 c -0.22141,0 -0.39946,0.178571 -0.39946,0.399976 0,0.221406 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:none;stroke-width:0.296737"
|
||||
id="path18" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
BIN
content/images/craftletter/horizontal.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
157
content/images/craftletter/horizontal.svg
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="191.23006mm"
|
||||
height="29.989243mm"
|
||||
viewBox="0 0 191.23006 29.989242"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="horizontal.svg"
|
||||
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showguides="true"
|
||||
inkscape:zoom="2.0186728"
|
||||
inkscape:cx="367.32054"
|
||||
inkscape:cy="111.70706"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1351"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g18">
|
||||
<sodipodi:guide
|
||||
position="60.83391,3.6250775"
|
||||
orientation="0,-1"
|
||||
id="guide22"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g19"
|
||||
transform="translate(-6.494133,-6.033493)">
|
||||
<rect
|
||||
style="fill:#249bb3;fill-opacity:1;stroke-width:0.23553"
|
||||
id="rect26-3-6"
|
||||
width="95.615021"
|
||||
height="29.989243"
|
||||
x="6.494133"
|
||||
y="6.033493"
|
||||
ry="0.008925369" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 96.399823,31.800868 c -0.61408,0.40592 -0.66317,0.4146 -1.53746,0.6748 -0.87429,0.26021 -1.82143,0.39031 -2.84143,0.39031 -2.01919,0 -3.53878,-0.52041 -4.55878,-1.56122 -1.02,-1.05123 -1.54047,-2.44595 -1.53,-4.18409 l 0.0463,-7.17819 -0.0463,-7.71591 4.12163,0.0101 0.0463,4.80364 -5e-5,2.9021 -0.0463,7.16259 c -0.005,0.85345 0.20817,1.47796 0.62449,1.87347 0.41633,0.3955 1.08766,0.59327 2.01399,0.59327 0.59326,0 1.13449,-0.0677 1.62367,-0.20297 0.49959,-0.14571 0.95235,-0.32786 1.35827,-0.54643 z"
|
||||
id="path12-9-4-7"
|
||||
sodipodi:nodetypes="csscscccccccsssc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 77.522843,8.8230973 c 1.10327,0 2.07643,0.0885 2.9195,0.26541 0.85347,0.17694 1.63408,0.41632 2.34183,0.71816 l -1.18653,2.7789807 c -0.55163,-0.22898 -1.12928,-0.39551 -1.73296,-0.49959 -0.60367,-0.10408 -1.20735,-0.15612 -1.81102,-0.15612 -1.03041,0 -1.785,0.19776 -2.26378,0.59326 -0.47877,0.38511 -0.71816,1.0044 -0.71816,1.85786 v 2.67561 l 19.601696,-0.0095 v 2.88231 l -19.601696,0.0096 v 12.45858 h -4.10603 v -12.45857 h -3.63765 v -2.88241 h 3.63765 v -2.76926 c 0,-1.59246 0.57766,-2.89868 1.73297,-3.918681 1.16571,-1.0304097 2.77377,-1.5456097 4.82418,-1.5456097 z"
|
||||
id="path11-8-9-3"
|
||||
sodipodi:nodetypes="ccccsscsccccccccccsccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 63.839893,28.041788 c 0,0.6349 0.0937,1.09807 0.28102,1.3895 0.18735,0.29143 0.48919,0.50479 0.90551,0.6401 l -0.0442,2.79812 c -1.56938,-0.001 -2.46937,-0.347 -3.09386,-0.69047 -0.62449,-0.35387 -1.10326,-0.87949 -1.43632,-1.57684 -0.6245,0.7598 -1.41552,1.32705 -2.37307,1.70174 -0.94714,0.37469 -1.94112,0.56204 -2.981938,0.56204 -1.686124,0 -3.023574,-0.47878 -4.01235,-1.43633 -0.988777,-0.95755 -1.483165,-2.20132 -1.483165,-3.73132 0,-1.75899 0.686939,-3.11205 2.060818,-4.05919 1.384287,-0.95755 3.341023,-1.43633 5.870205,-1.43633 h 2.31062 v -0.8899 c 0,-0.97837 -0.30704,-1.68612 -0.92113,-2.12327 -0.60367,-0.44755 -1.46755,-0.67132 -2.59163,-0.67132 -0.530817,0 -1.19694,0.0729 -1.998369,0.21857 -0.801429,0.13531 -1.618471,0.34867 -2.451124,0.6401 l -0.983572,-2.82583 c 1.051225,-0.3955 2.107655,-0.68693 3.169288,-0.87428 1.072041,-0.18734 2.045207,-0.28102 2.919487,-0.28102 2.32103,0 4.04358,0.49439 5.16766,1.48316 1.12408,0.97838 1.68612,2.36787 1.68612,4.16848 z"
|
||||
id="path10-6-6-7"
|
||||
sodipodi:nodetypes="sscccccssscscscsccccscss" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#249bb3;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 56.439683,29.884038 c 0.62449,0 1.25419,-0.17173 1.88909,-0.5152 0.6349,-0.35388 1.13969,-0.85347 1.51439,-1.49878 v -3.21613 h -1.62368 c -1.53,0 -2.638471,0.24459 -3.32541,0.73378 -0.676531,0.48919 -1.014796,1.18133 -1.014796,2.07643 0,1.61327 0.85347,2.4199 2.560406,2.4199 z"
|
||||
id="path9-5-3-2"
|
||||
sodipodi:nodetypes="scccscss" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 32.598108,32.397608 v -2.85704 h 2.326226 v -10.83491 h -2.326226 v -2.84144 l 5.974025,0.0232 0.255265,3.77062 c 0.603674,-1.39469 1.36347,-2.45112 2.279389,-3.1693 0.915919,-0.71816 2.066022,-1.07724 3.450309,-1.07724 0.530817,0 0.999184,0.0416 1.405103,0.1249 0.405919,0.0833 0.801429,0.19255 1.186531,0.32785 l -0.432569,4.826 h -3.025794 l -0.02317,-1.60986 c -1.072041,0.0937 -1.998368,0.58286 -2.778981,1.46755 -0.780613,0.87429 -1.476612,2.07874 -1.924163,3.51507 l 0.08192,5.47759 h 3.294186 v 2.85704 z"
|
||||
id="path8-0-7-6"
|
||||
sodipodi:nodetypes="ccccccccssscccccccccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 21.842901,10.337487 c 1.498777,0 2.768574,0.197761 3.809391,0.593261 1.040817,0.38511 2.003572,0.94195 2.888267,1.67051 l -2.170104,2.57603 c -0.62449,-0.51 -1.301021,-0.9003 -2.029593,-1.17092 -0.728572,-0.28102 -1.509185,-0.42154 -2.341838,-0.42154 -1.009593,0 -1.93592,0.26541 -2.778982,0.79623 -0.832653,0.53082 -1.498776,1.38429 -1.99837,2.56041 -0.499592,1.16572 -0.749388,2.70613 -0.749388,4.62124 0,1.88388 0.239388,3.40868 0.718164,4.57439 0.489185,1.15531 1.150104,2.00357 1.982757,2.5448 0.843062,0.54122 1.79541,0.81183 2.857043,0.81183 1.124083,0 2.055614,-0.19255 2.794594,-0.57765 0.749389,-0.39551 1.415512,-0.83266 1.998369,-1.31143 l 2.013981,2.5448 c -0.759797,0.74939 -1.712144,1.38949 -2.857043,1.92031 -1.134491,0.53081 -2.513573,0.79622 -4.137248,0.79622 -1.883879,0 -3.564798,-0.42673 -5.04276,-1.2802 -1.47796,-0.86388 -2.638471,-2.13368 -3.481533,-3.80939 -0.843061,-1.68613 -1.264592,-3.75735 -1.264592,-6.21368 0,-2.4147 0.431939,-4.4547 1.295817,-6.12002 0.874286,-1.67571 2.050409,-2.94551 3.528369,-3.80939 1.48837,-0.86387 3.143269,-1.295811 4.964699,-1.295811 z"
|
||||
id="text1-1-9-2-8-0"
|
||||
sodipodi:nodetypes="sccccsccsccsccccsccsccs" />
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-6.4941406,-6.0334926)">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.23553"
|
||||
id="rect26-3-6-5"
|
||||
width="95.615021"
|
||||
height="29.989243"
|
||||
x="102.10917"
|
||||
y="6.0334926"
|
||||
ry="0.008925369"
|
||||
inkscape:label="rect26-3-6-5" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 167.25894,25.406429 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
|
||||
id="path19-4-4-6-5" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 179.51963,32.453911 v -2.85704 h 2.32622 v -10.83491 h -2.32622 v -2.84144 l 5.97402,0.0232 0.25527,3.77062 c 0.60366,-1.39469 1.36347,-2.45112 2.27939,-3.1693 0.91591,-0.71816 2.06602,-1.07724 3.4503,-1.07724 0.53082,0 0.99919,0.0416 1.40511,0.1249 0.40592,0.0833 0.80143,0.19255 1.18653,0.32785 l -0.43257,4.826 h -3.02579 l -0.0232,-1.60986 c -1.07205,0.0937 -1.99837,0.58286 -2.77899,1.46755 -0.78061,0.87429 -1.47661,2.07874 -1.92416,3.51507 l 0.0819,5.47759 h 3.29418 v 2.85704 z"
|
||||
id="path20-7-4-3" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 124.31121,25.498691 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
|
||||
id="path19-4-4-6" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 127.85521,18.410731 c -0.99919,0 -1.82144,0.35908 -2.46675,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96307 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
|
||||
id="path18-2-6-1" />
|
||||
<path
|
||||
id="path17-7-0-5"
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 140.17463,12.245649 v 4.827095 h -3.59048 v 2.887163 h 3.59048 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.53971,1.561145 4.55889,1.561145 1.02001,0 1.96688,-0.129947 2.84117,-0.390157 0.87429,-0.2602 0.92381,-0.268974 1.53789,-0.674894 l -0.72605,-2.97863 c -0.40591,0.21857 -0.85847,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.03041,0.203088 -1.62367,0.203088 -0.92632,0 -1.59751,-0.197745 -2.01383,-0.593245 -0.41634,-0.39551 -0.62477,-1.020318 -0.62477,-1.873788 v -7.163903 h 7.73493 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.5392,1.561145 4.55838,1.561145 1.02,0 1.96739,-0.129947 2.84168,-0.390157 0.87429,-0.2602 0.9233,-0.268974 1.53738,-0.674894 l -0.72554,-2.97863 c -0.40591,0.21857 -0.85846,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.0304,0.203088 -1.62367,0.203088 -0.92632,0 -1.59802,-0.197745 -2.01435,-0.593245 -0.41633,-0.39551 -0.62425,-1.020318 -0.62425,-1.873788 v -7.163903 h 5.04259 v -2.887163 h -5.04259 v -4.817277 l -4.12171,-0.0098 v 4.827095 h -7.73493 v -4.817277 z"
|
||||
sodipodi:nodetypes="cccccscsscccsssccscsscccssscccccccccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 170.93889,18.844808 c -0.99919,0 -1.82143,0.35908 -2.46674,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96306 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
|
||||
id="path14-3-1-0" />
|
||||
<path
|
||||
d="M 105.67699,10.821962 V 32.41341 h 13.81621 l -0.478,-3.432865 -9.06043,-0.03307 v -1.414384 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399459 0,-0.221405 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004012 h -1.91151 c -0.22141,0 -0.39946,-0.178569 -0.39946,-0.399975 0,-0.221405 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399975 0.39946,-0.399975 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399458 0,-0.221406 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399458 0.39946,-0.399458 h 1.91151 v -1.893426 z"
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
id="path6" />
|
||||
<path
|
||||
d="m 109.95477,12.715388 h -1.91151 c -0.22141,0 -0.39946,0.178052 -0.39946,0.399458 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path8" />
|
||||
<path
|
||||
d="m 109.95477,15.518834 h -1.91151 c -0.22141,0 -0.39946,0.17857 -0.39946,0.399976 0,0.221405 0.17805,0.399458 0.39946,0.399458 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path10" />
|
||||
<path
|
||||
d="m 109.95477,18.322797 h -1.91151 c -0.22141,0 -0.39946,0.178053 -0.39946,0.399459 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 109.95477,21.126244 h -1.91151 c -0.22141,0 -0.39946,0.178569 -0.39946,0.399975 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path14" />
|
||||
<path
|
||||
d="m 109.95477,23.930207 h -1.91151 c -0.22141,0 -0.39946,0.178054 -0.39946,0.399459 0,0.221406 0.17805,0.399975 0.39946,0.399975 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path16" />
|
||||
<path
|
||||
d="m 109.95477,26.733653 h -1.91151 c -0.22141,0 -0.39946,0.178571 -0.39946,0.399976 0,0.221406 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path18" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
160
content/images/craftletter/vertical.svg
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="95.615028mm"
|
||||
height="59.978485mm"
|
||||
viewBox="0 0 95.61503 59.978484"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="vertical.svg"
|
||||
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
|
||||
inkscape:export-filename="vertical.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showguides="true"
|
||||
inkscape:zoom="1.0093364"
|
||||
inkscape:cx="64.398747"
|
||||
inkscape:cy="-93.625871"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1351"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g19">
|
||||
<sodipodi:guide
|
||||
position="60.83391,3.6250775"
|
||||
orientation="0,-1"
|
||||
id="guide22"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g19"
|
||||
transform="translate(-6.494133,-6.033493)">
|
||||
<rect
|
||||
style="fill:#249bb3;fill-opacity:1;stroke-width:0.23553"
|
||||
id="rect26-3-6"
|
||||
width="95.615021"
|
||||
height="29.989243"
|
||||
x="6.494133"
|
||||
y="6.033493"
|
||||
ry="0.008925369" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 96.399823,31.800868 c -0.61408,0.40592 -0.66317,0.4146 -1.53746,0.6748 -0.87429,0.26021 -1.82143,0.39031 -2.84143,0.39031 -2.01919,0 -3.53878,-0.52041 -4.55878,-1.56122 -1.02,-1.05123 -1.54047,-2.44595 -1.53,-4.18409 l 0.0463,-7.17819 -0.0463,-7.71591 4.12163,0.0101 0.0463,4.80364 -5e-5,2.9021 -0.0463,7.16259 c -0.005,0.85345 0.20817,1.47796 0.62449,1.87347 0.41633,0.3955 1.08766,0.59327 2.01399,0.59327 0.59326,0 1.13449,-0.0677 1.62367,-0.20297 0.49959,-0.14571 0.95235,-0.32786 1.35827,-0.54643 z"
|
||||
id="path12-9-4-7"
|
||||
sodipodi:nodetypes="csscscccccccsssc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 77.522843,8.8230973 c 1.10327,0 2.07643,0.0885 2.9195,0.26541 0.85347,0.17694 1.63408,0.41632 2.34183,0.71816 l -1.18653,2.7789807 c -0.55163,-0.22898 -1.12928,-0.39551 -1.73296,-0.49959 -0.60367,-0.10408 -1.20735,-0.15612 -1.81102,-0.15612 -1.03041,0 -1.785,0.19776 -2.26378,0.59326 -0.47877,0.38511 -0.71816,1.0044 -0.71816,1.85786 v 2.67561 l 19.601696,-0.0095 v 2.88231 l -19.601696,0.0096 v 12.45858 h -4.10603 v -12.45857 h -3.63765 v -2.88241 h 3.63765 v -2.76926 c 0,-1.59246 0.57766,-2.89868 1.73297,-3.918681 1.16571,-1.0304097 2.77377,-1.5456097 4.82418,-1.5456097 z"
|
||||
id="path11-8-9-3"
|
||||
sodipodi:nodetypes="ccccsscsccccccccccsccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 63.839893,28.041788 c 0,0.6349 0.0937,1.09807 0.28102,1.3895 0.18735,0.29143 0.48919,0.50479 0.90551,0.6401 l -0.0442,2.79812 c -1.56938,-0.001 -2.46937,-0.347 -3.09386,-0.69047 -0.62449,-0.35387 -1.10326,-0.87949 -1.43632,-1.57684 -0.6245,0.7598 -1.41552,1.32705 -2.37307,1.70174 -0.94714,0.37469 -1.94112,0.56204 -2.981938,0.56204 -1.686124,0 -3.023574,-0.47878 -4.01235,-1.43633 -0.988777,-0.95755 -1.483165,-2.20132 -1.483165,-3.73132 0,-1.75899 0.686939,-3.11205 2.060818,-4.05919 1.384287,-0.95755 3.341023,-1.43633 5.870205,-1.43633 h 2.31062 v -0.8899 c 0,-0.97837 -0.30704,-1.68612 -0.92113,-2.12327 -0.60367,-0.44755 -1.46755,-0.67132 -2.59163,-0.67132 -0.530817,0 -1.19694,0.0729 -1.998369,0.21857 -0.801429,0.13531 -1.618471,0.34867 -2.451124,0.6401 l -0.983572,-2.82583 c 1.051225,-0.3955 2.107655,-0.68693 3.169288,-0.87428 1.072041,-0.18734 2.045207,-0.28102 2.919487,-0.28102 2.32103,0 4.04358,0.49439 5.16766,1.48316 1.12408,0.97838 1.68612,2.36787 1.68612,4.16848 z"
|
||||
id="path10-6-6-7"
|
||||
sodipodi:nodetypes="sscccccssscscscsccccscss" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#249bb3;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 56.439683,29.884038 c 0.62449,0 1.25419,-0.17173 1.88909,-0.5152 0.6349,-0.35388 1.13969,-0.85347 1.51439,-1.49878 v -3.21613 h -1.62368 c -1.53,0 -2.638471,0.24459 -3.32541,0.73378 -0.676531,0.48919 -1.014796,1.18133 -1.014796,2.07643 0,1.61327 0.85347,2.4199 2.560406,2.4199 z"
|
||||
id="path9-5-3-2"
|
||||
sodipodi:nodetypes="scccscss" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 32.598108,32.397608 v -2.85704 h 2.326226 v -10.83491 h -2.326226 v -2.84144 l 5.974025,0.0232 0.255265,3.77062 c 0.603674,-1.39469 1.36347,-2.45112 2.279389,-3.1693 0.915919,-0.71816 2.066022,-1.07724 3.450309,-1.07724 0.530817,0 0.999184,0.0416 1.405103,0.1249 0.405919,0.0833 0.801429,0.19255 1.186531,0.32785 l -0.432569,4.826 h -3.025794 l -0.02317,-1.60986 c -1.072041,0.0937 -1.998368,0.58286 -2.778981,1.46755 -0.780613,0.87429 -1.476612,2.07874 -1.924163,3.51507 l 0.08192,5.47759 h 3.294186 v 2.85704 z"
|
||||
id="path8-0-7-6"
|
||||
sodipodi:nodetypes="ccccccccssscccccccccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 21.842901,10.337487 c 1.498777,0 2.768574,0.197761 3.809391,0.593261 1.040817,0.38511 2.003572,0.94195 2.888267,1.67051 l -2.170104,2.57603 c -0.62449,-0.51 -1.301021,-0.9003 -2.029593,-1.17092 -0.728572,-0.28102 -1.509185,-0.42154 -2.341838,-0.42154 -1.009593,0 -1.93592,0.26541 -2.778982,0.79623 -0.832653,0.53082 -1.498776,1.38429 -1.99837,2.56041 -0.499592,1.16572 -0.749388,2.70613 -0.749388,4.62124 0,1.88388 0.239388,3.40868 0.718164,4.57439 0.489185,1.15531 1.150104,2.00357 1.982757,2.5448 0.843062,0.54122 1.79541,0.81183 2.857043,0.81183 1.124083,0 2.055614,-0.19255 2.794594,-0.57765 0.749389,-0.39551 1.415512,-0.83266 1.998369,-1.31143 l 2.013981,2.5448 c -0.759797,0.74939 -1.712144,1.38949 -2.857043,1.92031 -1.134491,0.53081 -2.513573,0.79622 -4.137248,0.79622 -1.883879,0 -3.564798,-0.42673 -5.04276,-1.2802 -1.47796,-0.86388 -2.638471,-2.13368 -3.481533,-3.80939 -0.843061,-1.68613 -1.264592,-3.75735 -1.264592,-6.21368 0,-2.4147 0.431939,-4.4547 1.295817,-6.12002 0.874286,-1.67571 2.050409,-2.94551 3.528369,-3.80939 1.48837,-0.86387 3.143269,-1.295811 4.964699,-1.295811 z"
|
||||
id="text1-1-9-2-8-0"
|
||||
sodipodi:nodetypes="sccccsccsccsccccsccsccs" />
|
||||
</g>
|
||||
<g
|
||||
id="g18"
|
||||
transform="translate(-6.4941406,-6.0334926)">
|
||||
<rect
|
||||
style="fill:#ffffff;stroke-width:0.23553"
|
||||
id="rect26-3-6-5"
|
||||
width="95.615021"
|
||||
height="29.989243"
|
||||
x="6.4941444"
|
||||
y="36.022736"
|
||||
ry="0.008925369"
|
||||
inkscape:label="rect26-3-6-5" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 71.643915,55.395672 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
|
||||
id="path19-4-4-6-5" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 83.904605,62.443154 v -2.85704 h 2.32622 v -10.83491 h -2.32622 v -2.84144 l 5.97402,0.0232 0.25527,3.77062 c 0.60366,-1.39469 1.36347,-2.45112 2.27939,-3.1693 0.91591,-0.71816 2.06602,-1.07724 3.4503,-1.07724 0.53082,0 0.99919,0.0416 1.40511,0.1249 0.40592,0.0833 0.80143,0.19255 1.18653,0.32785 l -0.43257,4.826 h -3.02579 l -0.0232,-1.60986 c -1.07205,0.0937 -1.99837,0.58286 -2.77899,1.46755 -0.78061,0.87429 -1.47661,2.07874 -1.92416,3.51507 l 0.0819,5.47759 h 3.29418 v 2.85704 z"
|
||||
id="path20-7-4-3" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 28.696185,55.487934 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
|
||||
id="path19-4-4-6" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 32.240185,48.399974 c -0.99919,0 -1.82144,0.35908 -2.46675,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96307 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
|
||||
id="path18-2-6-1" />
|
||||
<path
|
||||
id="path17-7-0-5"
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
d="m 44.559605,42.234892 v 4.827095 h -3.59048 v 2.887163 h 3.59048 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.53971,1.561145 4.55889,1.561145 1.02001,0 1.96688,-0.129947 2.84117,-0.390157 0.87429,-0.2602 0.92381,-0.268974 1.53789,-0.674894 l -0.72605,-2.97863 c -0.40591,0.21857 -0.85847,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.03041,0.203088 -1.62367,0.203088 -0.92632,0 -1.59751,-0.197745 -2.01383,-0.593245 -0.41634,-0.39551 -0.62477,-1.020318 -0.62477,-1.873788 V 49.94915 h 7.73493 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.5392,1.561145 4.55838,1.561145 1.02,0 1.96739,-0.129947 2.84168,-0.390157 0.87429,-0.2602 0.9233,-0.268974 1.53738,-0.674894 l -0.72554,-2.97863 c -0.40591,0.21857 -0.85846,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.0304,0.203088 -1.62367,0.203088 -0.92632,0 -1.59802,-0.197745 -2.01435,-0.593245 -0.41633,-0.39551 -0.62425,-1.020318 -0.62425,-1.873788 V 49.94915 h 5.04259 v -2.887163 h -5.04259 V 42.24471 l -4.12171,-0.0098 v 4.827095 h -7.73493 v -4.817277 z"
|
||||
sodipodi:nodetypes="cccccscsscccsssccscsscccssscccccccccc" />
|
||||
<path
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
|
||||
d="m 75.323865,48.834051 c -0.99919,0 -1.82143,0.35908 -2.46674,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96306 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
|
||||
id="path14-3-1-0" />
|
||||
<path
|
||||
d="m 10.061965,40.811205 v 21.591448 h 13.81621 l -0.478,-3.432865 -9.06043,-0.03307 v -1.414384 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399459 0,-0.221405 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004012 h -1.91151 c -0.22141,0 -0.39946,-0.178569 -0.39946,-0.399975 0,-0.221405 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399975 0.39946,-0.399975 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399458 0,-0.221406 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399458 0.39946,-0.399458 h 1.91151 v -1.893426 z"
|
||||
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
|
||||
id="path6" />
|
||||
<path
|
||||
d="m 14.339745,42.704631 h -1.91151 c -0.22141,0 -0.39946,0.178052 -0.39946,0.399458 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path8" />
|
||||
<path
|
||||
d="m 14.339745,45.508077 h -1.91151 c -0.22141,0 -0.39946,0.17857 -0.39946,0.399976 0,0.221405 0.17805,0.399458 0.39946,0.399458 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path10" />
|
||||
<path
|
||||
d="m 14.339745,48.31204 h -1.91151 c -0.22141,0 -0.39946,0.178053 -0.39946,0.399459 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 14.339745,51.115487 h -1.91151 c -0.22141,0 -0.39946,0.178569 -0.39946,0.399975 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path14" />
|
||||
<path
|
||||
d="m 14.339745,53.91945 h -1.91151 c -0.22141,0 -0.39946,0.178054 -0.39946,0.399459 0,0.221406 0.17805,0.399975 0.39946,0.399975 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path16" />
|
||||
<path
|
||||
d="m 14.339745,56.722896 h -1.91151 c -0.22141,0 -0.39946,0.178571 -0.39946,0.399976 0,0.221406 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
|
||||
style="fill:#ffffff;stroke-width:0.296737"
|
||||
id="path18" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -27,7 +27,7 @@ vous pouvez consulter les résultats du sondage [State of JS 2025](https://2025.
|
|||
Quelques points qui m’ont interpelés :
|
||||
|
||||
* Angular est toujours aussi peu apprécié : plus d’une personne sur deux qui l’a essayé n’a pas aimé l’expérience.
|
||||
* Le taux de satisfaction des utilisateurs de HTMX est en baisse (de 84% en 2016 à 69% en 2025) ; je soupçonne que cela correspond à la découverte des limitations de ce framework quand les applications deviennent plus complexes. Datastar, dont je vous parlais dans [la lettre n°7](http://127.0.0.1:8000/lettre-ndeg7-19-janvier-2026.html), n’apparait pas dans ce sondage, c’est dommage, car j’aurais bien aimé découvrir les retours d’expérience à son sujet.
|
||||
* Le taux de satisfaction des utilisateurs de HTMX est en baisse (de 84% en 2016 à 69% en 2025) ; je soupçonne que cela correspond à la découverte des limitations de ce framework quand les applications deviennent plus complexes. Datastar, dont je vous parlais dans [la lettre n°7](https://www.craftletter.fr/lettre-ndeg7-19-janvier-2026.html), n’apparait pas dans ce sondage, c’est dommage, car j’aurais bien aimé découvrir les retours d’expérience à son sujet.
|
||||
* La satisfaction des utilisateurs de React est également en baisse régulière (de 92% en 2016 à 72% en 2025).
|
||||
* Cypress (Tests End-to-end), autrefois très populaire, a perdu de sa superbe, puisque à peine plus de la moitié des utilisateurs ont envie de le réutiliser.
|
||||
* À l’inverse, Playwright (tests End-to-end), Vitest (tests unitaires), Vite (build), Astro (framework pour créer des sites de contenu), Bun (alternative à NodeJs), Hono et Fastify (frameworks Web) sont appréciés par une large majorité de ceux qui les ont utilisés.
|
||||
|
|
|
|||
101
content/newsletter/craft-letter-11.md
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
Title: Lettre n°11 — 16 février 2026
|
||||
Date: 2026-02-16 09:00
|
||||
Category: Newsletter
|
||||
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°11", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 16 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
|
||||
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
|
||||
|
||||
## Édito
|
||||
|
||||
De temps en temps, une rencontre, une conférence, une méthode ou un article me marque particulièrement, et de façon durable. Parce qu’il est aligné avec mes valeurs, et qu’il m’apporte un éclairage nouveau. Je m’appuie dessus, le cite fréquemment et mets en œuvre tout ou partie de ce qu’il raconte pendant quelques années, jusqu’à ce que ce soit tellement intégré que je n’y pense même plus, et que cela devienne une évidence —ce qui est un problème, car ce qui est acquis pour moi ne l’est pas nécessairement pour les autres. Cela a été le cas, par exemple, il y a 25 ans lors de ma découverte de l’eXtreme Programming et de l’Agilité —l’état d’esprit original, pas la caricature qui s’est répandue depuis.
|
||||
|
||||
Le premier article mentionné dans cette newsletter fera probablement partie de ces rares élus. Les chiffres qu’il donne méritent d’être retenus, et ses conseils devraient être suivis, selon moi.
|
||||
|
||||
## La crise de qualité logicielle et de productivité que les exécutifs ne traiteront pas
|
||||
|
||||
Si vous ne deviez lire qu’un seul article cette semaine, c’est [celui-là](https://flowchainsensei.wordpress.com/2026/02/04/the-software-quality-and-productivity-crisis-executives-wont-address/) 🇬🇧.
|
||||
|
||||
Bob Marshall fait un constat assez accablant, en partant de plusieurs études : la qualité des logiciels s’est considérablement dégradée ces dernières années, et les trois quarts des projets de développement logiciel sont des échecs. Ces chiffres n’ont jamais été aussi hauts. La dette technique est la principale préoccupation de 9 CTO sur 10, et la solution pour la résorber est connue. Malgré ça, la direction des entreprises n’y accorde aucun intérêt, tant qu’une crise n’éclate pas. Pourquoi ? Parce que la majorité des dirigeants se focalisent sur leurs revenus personnels, et sur le court terme. De même, ils ne s’intéressent pas au bien être des développeurs, alors que 83% d’entre eux ont fait, ou feront, un burn-out.
|
||||
|
||||
Pourtant, l’histoire récente nous montre qu’un autre monde est possible. Un monde où la qualité est une préoccupation, et où la majorité des projets atteignent leurs objectifs —l’un découlant de l’autre. Un monde où les développeurs sont heureux de faire leur travail, et ne mettent pas en péril leur santé mentale. Pour revenir à ça, ce que préconise Bob Marshall, c’est de prendre en main vous-même la gestion de la dette technique, sans en attendre l’autorisation —qui ne viendra pas, ou trop tard. Et de rendre ce travail visible en définissant vos propres indicateurs, qui auront plus de valeur que ceux qu’on vous impose.
|
||||
|
||||
Bob Marshall évoque les risques de cette démarche, mais j’ajouterais qu’il ne faut pas en négliger les avantages : se montrer courageux et transparent est un moyen de gagner le respect de vos collègues. Et si vous êtes dans une entreprise qui punit ces qualités au lieu de les récompenser, il est temps d’en changer.
|
||||
|
||||
À lire d’urgence.
|
||||
|
||||
## Laravel vs Symfony
|
||||
RadWebHosting a établi [une comparaison détaillée des deux frameworks PHP les plus populaires](https://blog.radwebhosting.com/laravel-vs-symfony-a-comprehensive-comparison-of-php-frameworks/) 🇬🇧, Laravel et Symfony, avec des recommandations pour vous guider dans un choix entre les deux.
|
||||
## Event Storming
|
||||
|
||||
L'Event Storming est un type d'atelier inventé par Alberto Brandolini —oui, celui qui a énoncé la [loi de Brandolini](https://fr.wikipedia.org/wiki/Loi_de_Brandolini)🇫🇷, mais ça n'a aucun rapport.
|
||||
|
||||
L'Event Storming se décline en différentes variantes, selon l'objectif. Les plus courantes sont :
|
||||
|
||||
* **Big Picture Event Storming** : pour explorer collaborativement un domaine métier complexe ;
|
||||
* **Process Modeling Event Storming** : pour détailler un process métier, du début à la fin (par exemple : de la commande à la livraison d'un produit) ;
|
||||
* **Software Design Event Storming** : pour enrichir un Process Modeling Event Storming, en y ajoutant des éléments d'architecture logicielle (contextes bornés, agrégats, commandes...).
|
||||
|
||||
J'ai animé à plusieurs reprises des ateliers **Process Modeling Event Storming**, avec un public mixte, technique et métier. Mon retour d'expérience, c'est que, s'il est bien préparé, c'est un atelier qui apporte énormément de valeur par rapport au temps consacré —je vous recommande de prévoir deux heures, pas plus. Les participants, même s'ils travaillent sur le logiciel depuis plusieurs années, en apprendront des subtilités qu'ils ignoraient. C'est un outil idéal pour faire découvrir un logiciel existant à de nouveaux venus.
|
||||
|
||||
Staffan Palopää explique [comment animer ces ateliers](https://www.qlerify.com/post/event-storming-the-complete-guide) 🇬🇧.
|
||||
|
||||
## Moderniser un legacy conséquent sans y perdre ses plumes
|
||||
|
||||
Dans cette [première partie](https://blog.octo.com/apprivoiser-un-legacy-consequent-sans-y-perdre-les-plumes) 🇫🇷, Bruno Boucart décrit comment le code legacy s’installe inexorablement au fil des années, et devient un obstacle pour les développeurs, qui subissent les conséquences de choix organisationnels. La modernisation d’un code legacy est souvent perçue comme impossible. Mais la réécriture totale d’un logiciel, sans changement des pratiques et de l’organisation, produira une application avec les mêmes défauts que la précédente. En particulier, le management doit adopter la posture du *servant leadership*, c’est-à-dire créer les conditions qui permettront aux équipes de réussir, plutôt que de chercher à les contrôler.
|
||||
|
||||
L’organisation d’ateliers d’Event Storming Big Picture est un moyen d’assurer que le nouveau code correspondra aux besoins du métier. Mais cela implique de réorganiser les équipes en fonction des sous-domaines identifiés lors de ces ateliers. Après avoir identifié les sous-domaines, qui sont un découpage du problème, il devient possible de découper la solution technique en contextes bornés (*bounded contexts*). Cet alignement entre l’organisation du code, les responsabilités des équipes, et le métier, est une condition indispensable au succès de la refonte.
|
||||
|
||||
Une autre condition réside dans la compréhension du métier par les développeurs. Ce point peut être résolu par l’organisation d’ateliers. Tout d’abord, des ateliers de User Story Mapping, qui permettent d’identifier les parcours utilisateurs et prioriser les User Stories. Ensuite, des ateliers d’Example Mapping, pour préciser le contenu des User Stories.
|
||||
|
||||
La dernière partie de l’article évoque trop rapidement l’approche Team Topologies pour être utile.
|
||||
|
||||
Si la différence entre sous-domaines et contextes bornés n’est pas claire pour vous, je vous invite à lire [cette explication](https://blog.ancyracademy.fr/posts/bounded-contexts-vs-subdomains/) 🇫🇷.
|
||||
|
||||
Si vous souhaitez vous familiariser avec le Domain Driven Design, je vous recommande la lecture de [Learning Domain Driven Design](https://www.oreilly.com/library/view/learning-domain-driven-design/9781098100124/) 🇬🇧 de Vlad Khononov.
|
||||
|
||||
J’évoquerai dans la prochaine lettre la suite de l’article de Bruno.
|
||||
|
||||
## Découvrir ou approfondir JavaScript et/ou TypeScript
|
||||
|
||||
Axel Rauschmayer propose [une série de livres](https://exploringjs.com/) 🇬🇧, à propos de JavaScript et Typescript, dont la version en ligne est gratuite.
|
||||
|
||||
## Le but de l’intégration continue est d’échouer
|
||||
|
||||
Je ne suis pas du tout d’accord avec le point de vue défendu par l’auteur de ce billet de blog, selon lequel [le but de la CI serait d’échouer](https://blog.nix-ci.com/post/2026-02-05_the-purpose-of-ci-is-to-fail) 🇬🇧. Selon lui, la valeur ne serait produite que par les erreurs détectées, comme il l’explique après un rappel de ce qu’il entend par CI (*Continuous Integration*).
|
||||
|
||||
Sans surprise, mon point de vue est celui qui est plus communément admis : l’objectif de la CI est de nous assurer que le code que l’on s’apprête à déployer ne comporte pas de problème évident, et a de bonnes chances de fonctionner en production.
|
||||
|
||||
Au passage, j’ajouterai que si l’auteur décrit ce qui est appelé de façon un peu abusive "intégration continue" aujourd’hui (par moi aussi), ce n’est pas ce que désigne initialement cette expression. Le concept d’intégration continue consiste à fusionner tous les jours votre code avec celui de vos collègues, comme son nom l’indique. Pour cela, un système de gestion de version tel que Git suffit. Github Actions, Gitlab CI ou un équivalent ne sont pas nécessaires. Le build et les vérifications automatisés exécutés par ces derniers sont un complément très utile de l’intégration continue au sens premier. Faire une "vraie" intégration continue élimine la plupart des conflits, ce qui gagne du temps et évite des bugs. Cela nécessite de réaliser en plusieurs fois les changements, plutôt qu’attendre qu’une fonctionnalité soit complète avant de fusionner des centaines, voire des milliers de lignes de code. Ce qui peut amener à faire du Trunk Based Development, et améliorer nettement la productivité. Mais c’est une autre histoire, dont j’aurais certainement l’occasion de vous parler plus tard.
|
||||
|
||||
## Une conférence au soleil
|
||||
|
||||
[Sunnytech](https://sunny-tech.io/) 🇫🇷, la conférence Tech organisée à Montpellier, aura lieu les 2 et 3 juillet 2026. Le CFP est ouvert. La première vague de billets est déjà vendue, mais une nouvelle vague sera mise en vente mi-avril, avant une troisième et dernière vague fin avril.
|
||||
|
||||
## Une conférence peut-être un peu moins ensoleillée...
|
||||
... et encore, ça reste à démontrer ! 😉
|
||||
|
||||
Le 9 Juin aura lieu [C:\aen\Tech](https://caen.tech/) 🇫🇷, une conférence Normande qui privilégie les retours d’expérience locaux. Le CFP est ouvert.
|
||||
## Granian, un serveur HTTP performant pour Python
|
||||
|
||||
C’est un euphémisme de dire que les performances ne sont pas le point fort de Python.
|
||||
|
||||
[Granian](https://github.com/emmett-framework/granian) est un serveur HTTP écrit en Rust, qui vise à améliorer cet état de fait. Remplacer Guvicorn ou Uvicorn par Granian ne transformera pas votre application en bête de course, car de multiples autres facteurs entrent en jeu : le framework, les algorithmes implémentés, les accès disque et réseau, les requêtes à la base de données... Mais c’est une étape, qui peut apporter des changements significatifs par rapport à la simplicité de l’effort demandé. Il faudra bien entendu faire des benchmarks pour mesurer l’impact réel de ce changement dans votre cas de figure. En effet, dans le pire des cas, il peut s’avérer négatif. Cela peut arriver si votre code n’est pas asynchrone.
|
||||
|
||||
Merci à Mikaël qui m’a fait découvrir Granian et partagé son retour d’expérience !
|
||||
|
||||
## Crystal, un langage pour les humains et les ordinateurs
|
||||
|
||||
Lors du Fosdem, cette énorme conférence dédiée à l’open-source, [Johannes Müller a présenté Crystal](https://crystal-lang.org/2026/01/23/crystal-talk-fosdem/) 🇬🇧. Crystal est un langage généraliste, Orienté Objet, inspiré de Ruby. Il en corrige ce que je considère comme des points faibles. Il apporte un typage statique, de l’inférence de type, de meilleures performances, un déploiement plus facile et une meilleure gestion de la concurrence, tout en conservant la lisibilité et la facilité d’utilisation de Ruby. Ce langage sympathique est utilisé en production, comme le montre [cette liste](https://crystal-lang.org/used_in_prod/) qui est probablement incomplète.
|
||||
|
||||
Crystal, qui date de 2013, a eu pour slogan jusqu’à fin 2019 "Fast as C, slick as Ruby" ("*Rapide comme C, Ingénieux comme Ruby*"). L’affirmation selon laquelle Crystal aurait la rapidité du C était exagérée, et c’est probablement pourquoi ce slogan a été abandonné.
|
||||
|
||||
## Bienfaits du TDD et tests en production
|
||||
|
||||
Ola Hast et Asgaut Mjølne Söderbom [expliquent comment leurs équipes obtiennent d’excellents résultats](https://www.infoq.com/news/2026/02/feedback-TDD-production/) 🇬🇧 avec des tests unitaires et des tests d’intégration, sans tests end-to-end.
|
||||
|
||||
Le TDD et le Pair programming leur permettent d’écrire un code de qualité. Le Pair et le Mob Programming éliminent le besoin de faire des revues de code, diffusent la connaissance, et augmentent la résilience des équipes.
|
||||
|
||||
Puisque les environnements de test ne sont qu’une approximation de la production, ils les ont quasiment abandonnés au profit du test en production, et déploient de petits incréments, désactivables par des *feature flags* pour réduire les risques.
|
||||
|
||||
-----
|
||||
|
||||
Voilà, c’est tout pour cette semaine.
|
||||
104
content/newsletter/craft-letter-12.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
Title: Lettre n°12 — 23 février 2026
|
||||
Date: 2026-02-23 09:00
|
||||
Category: Newsletter
|
||||
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°12", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 23 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
|
||||
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
|
||||
|
||||
## Edito
|
||||
|
||||
La Craft Letter est récente, et je me pose encore des questions sur son format. Dois-je continuer à faire des résumés détaillés, comme ceux que contient ce numéro à propos de Zig vs C3, ou de la modernisation de code legacy ? Ou des textes d’introduction plus courts sont-ils préférables, comme celui sur AtomVM ? Je vous serais reconnaissant si vous preniez quelques secondes pour répondre à ce [sondage minimaliste](https://framaforms.org/sondage-craft-letter-1771415205)🇫🇷 (il n’y a qu’une question). Les réponses m’aideront à définir le format des prochaines Craft Letters.
|
||||
|
||||
## Limiter les contributions open-source avec Vouch
|
||||
|
||||
Mitchell Hashimoto est un développeur prolifique et talentueux. Fondateur de HashiCorp (la société derrière Terraform, Vagrant, Vault...), il est aussi le créateur de Ghostty, un émulateur de terminal que je vous recommande. Son nouveau projet, [Vouch](https://github.com/mitchellh/vouch)🇬🇧, est un outil pour la CI qui limite les contributions aux projets open source (Pull Requests et Issues) à certains comptes de confiance. Les contributeurs ne peuvent pas en certifier d’autres : seuls les mainteneurs le peuvent, ce qui garantit qu’ils conservent la main sur leur projet. Par contre, ils peuvent échanger leurs listes de contributeurs de confiance.
|
||||
Sans surprise, le but est de limiter les contributions de basse qualité générées par IA, comme celles qui ont amené le projet [Curl à fermer son programme de bug bounty](https://intelligence-artificielle.developpez.com/actu/365686/Les-mainteneurs-de-logiciels-libres-sont-noyes-dans-des-rapports-de-bogues-inutiles-rediges-par-l-IA-Ces-systemes-ne-sont-pas-encore-capable-de-comprendre-le-code-estime-un-developpeur/)🇫🇷, ou celles qui [submergent le projet Godot](https://www.pcgamer.com/software/platforms/open-source-game-engine-godot-is-drowning-in-ai-slop-code-contributions-i-dont-know-how-long-we-can-keep-it-up/)🇬🇧.
|
||||
|
||||
## Sérialisation rapide en Python
|
||||
|
||||
[MsgSpec](https://jcristharif.com/msgspec/)🇬🇧 est une librarie pour (dé)sérialisaliser et valider des données en Python, qu’elles soient au format JSON, YAML, TOML ou MessagePack. Elle utilise du C pour obtenir des performances élevées.
|
||||
|
||||
## Qui, de Zig ou de C3, résout les problèmes du C ?
|
||||
|
||||
Dans mes newsletters précédentes, je vous ai parlé de Zig et de C3, deux langages qui se veulent des successeurs du C. Les deux cherchent à en corriger des défauts, chacun à leur manière.
|
||||
|
||||
[Cette vidéo](https://www.youtube.com/watch?v=y3tDZACGRAY)🇬🇧 de la chaîne Youtube The Techy Shop explique que ces langages présentent de nombreuses similarités, mais aussi certaines différences, que je peux résumer ainsi :
|
||||
|
||||
* C3 est présenté comme une évolution incrémentale de C. Il y introduit de la simplicité, notamment dans la syntaxe et l’outillage. Il élimine une partie des pièges de son prédécesseur grâce à des fonctionnalités comme la gestion des erreurs à l’aide d’un type Option.
|
||||
* Zig se veut une révolution, et est plus ambitieux —au prix d’une complexité plus grande que que celle de C3. La preuve en est le système de build, qui nécessite l’écriture d’un script en Zig, là où C3 utilise un simple fichier JSON. Mais aussi le compilateur, qui, en plus de LLVM, utilise un backend spécifique à Zig, qui réduit significativement les temps de compilation pour le mode debug et les architectures x86_64.
|
||||
|
||||
Les deux sont compatibles avec C, mais C3 n’utilise pas les fichiers d’en-tête du C, ce qui implique de déclarer les fonctions C importées. Zig permet d’intégrer plus facilement du code C, tandis que C3 s’oriente plus vers la réécriture du C existant. Aucun des deux n’offre d’équivalent à l’instruction GOTO du C, ce qui implique un travail d’adaptation pour porter du code C, même s’il existe des moyens de simuler un GOTO.
|
||||
|
||||
C3 s’appuie sur l’écosystème C, là où Zig voudrait le remplacer entièrement.
|
||||
|
||||
Malgré leurs objectifs affichés, l’expérience de développement en Zig serait ironiquement plus proche de celle du C que celle de C3, car si elle offre plus de contrôle, elle requiert plus de rigueur en contrepartie. C3 minimise les surprises, au prix de fonctionnalités moins avancées.
|
||||
|
||||
Les deux langages évoluent rapidement, ont chacun une communauté passionnée. C3 est toutefois plus récent et moins visible. Zig est plus populaire, et a déjà de belle références, comme Bun ou Ghostty.
|
||||
|
||||
Au final Zig et C3 résolvent, de façon différente, les problèmes du C : la complexité de l’outillage, les multiples possibilités de se tirer une balle dans le pied. Les deux offrent des performances comparables à du C optimisé, et devraient jouer un rôle important dans la programmation système à l’avenir.
|
||||
|
||||
Pour en savoir plus sur C3, cette [courte vidéo](https://www.youtube.com/watch?v=yJClpzNxs3s)🇬🇧 explique les différences par rapport à C. Et pour essayer le langage simplement, il y a [un tutoriel](https://learn-c3.org/)🇬🇧 en ligne.
|
||||
## Adopter Kotlin dans un environnement dominé par Java
|
||||
|
||||
Kotlin possède de [nombreux avantages par rapport à Java](https://kotlinlang.org/docs/comparison-to-java.html)🇬🇧. Pour n’en citer que quelques-un,
|
||||
|
||||
* le code est beaucoup plus concis tout en étant expressif,
|
||||
* la sécurité est meilleure grâce au contrôle des valeurs nulles par le système de types,
|
||||
* il n’y a pas de conversions implicites,
|
||||
* les types primitifs de Java sont des objets en Kotlin,
|
||||
* la gestion de la concurrence utilise des coroutines (plus légères que les threads),
|
||||
|
||||
Le tout avec des performances équivalentes.
|
||||
|
||||
Quand je parle de concision de Kotlin, je repense toujours à des collègues qui ont réécrit une application mobile Java de 33 000 lignes. La version Kotlin en faisait seulement 17 000. C’est possible notamment parce que le code boilerplate inhérent à Java n’existe pas en Kotlin.
|
||||
|
||||
La migration de Java vers Kotlin peut être tout à fait progressive, puisqu’une application Kotlin peut contenir du code Java, et que l’interopérabilité entre les deux langages est excellente. Cette [démonstration](https://www.youtube.com/watch?v=WXVeHvOvSww)🇫🇷 de migration reste intéressante même si elle date un peu, car elle est basée sur un retour d’expérience. Elle montre la simplicité relative d’une migration, grâce à l’outillage fourni par JetBrains, qui n'est plus limité à leurs IDE, puisqu'il vient juste d'[arriver sous VSCode](https://blog.jetbrains.com/kotlin/2026/02/java-to-kotlin-conversion-comes-to-visual-studio-code/)🇬🇧.
|
||||
|
||||
Jetbrains propose [un guide de migration](https://blog.jetbrains.com/kotlin/2025/12/the-ultimate-guide-to-successfully-adopting-kotlin-in-a-java-dominated-environment/)🇬🇧, qui, outre des conseils techniques, fournit des recommandations sur la stratégie à adopter, notamment pour convaincre vos pairs et managers.
|
||||
## Java : le Valhalla est enfin là !
|
||||
|
||||
Près de douze ans après son lancement, [le projet Valhalla est arrivé dans Java 23](https://javaworldmag.com/project-valhalla-value-types-in-production/)🇬🇧, en preview pour l’instant.
|
||||
|
||||
En Java, tous les objets sont représentés par des zones mémoires allouées sur le tas (*heap*), avec un en-tête, et nécessitent qu’on y accède via un pointeur —c’est masqué, mais ce n’est pas sans impact sur les performances. Et ce, même si ces objets ne servent qu’à encapsuler une ou plusieurs valeurs, comme les coordonnées x et y d’un point. Le projet Valhalla résout ce problème.
|
||||
|
||||
Il change aussi la façon dont ces données sont stockées dans les collections génériques : au lieu de contenir des pointeurs, elles contiennent directement les valeurs, contiguës en mémoire.
|
||||
|
||||
Ces changements améliorent drastiquement les performances, réduisent la fragmentation et la consommation mémoire, ainsi que la fréquence des déclenchements du ramasse-miette. Toutefois, ils ne sont pas applicables à toutes les structures de données.
|
||||
|
||||
## Moderniser un legacy conséquent sans y perdre ses plumes - Partie II
|
||||
|
||||
Dans la première partie, que j’ai résumée dans la lettre précédente, Bruno Boucart expliquait la première phase pour réussir la modernisation d’une grosse application legacy. Elle consiste à en comprendre le métier, le cartographier, puis aligner l’organisation des équipes et l’architecture sur ce découpage. Dans cette [seconde partie](https://blog.octo.com/apprivoiser-un-legacy-consequent-sans-y-perdre-ses-plumes-partie-ii)🇫🇷, il évoque la transformation du code qui doit suivre.
|
||||
|
||||
Après l’identification de contextes bornés (*bounded contexts*) au cours d’ateliers d’Event Storming, il explique comment remplir pour chacun un [Bounded Context Canvas](https://github.com/ddd-crew/bounded-context-canvas)🇬🇧. Il s’agit d’un outil de modélisation qui va permettre d’affiner la définition du contexte, et de faire émerger le langage ubiquitaire —le vocabulaire partagé entre les équipes métier et techniques, qui est l’un des concepts les plus importants du Domain Driven Design (DDD).
|
||||
|
||||
Rappel : un contexte borné est une notion du DDD, qui désigne un sous-ensemble de la solution technique.
|
||||
|
||||
Bruno rappelle ensuite une série de *design patterns* que l’on peut utiliser pour casser les dépendances entre des parties du code. C’est en effet une étape préliminaire indispensable à l’écriture des tests qui vont permettre d’envisager sereinement des modifications plus importantes.
|
||||
|
||||
La réorganisation du code, selon les contextes bornés identifiés précédemment, n’est pas suffisante : elle doit s’accompagner d’une réorganisation de la base de données, de façon à casser là aussi les dépendances entre les parties du système.
|
||||
|
||||
Le code refactoré doit refléter fortement le métier : c’est ce qu’on appelle le *deep modeling.* Cela facilite la collaboration entre experts métiers et techniques, mais assure aussi la durabilité du nouveau code, qui tolérera mieux les évolutions futures du métier. L’une des clés pour cela est l’utilisation du langage ubiquitaire pour nommer les fonctions, les classes, les variables, etc.
|
||||
Le contour des classes doit correspondre à celui des concepts métier qu’elles représente.
|
||||
|
||||
L’activité qui mène à cette modélisation proche du métier porte le nom de Conception Souple (Supple Design) en DDD, et possède ses propres *design patterns*.
|
||||
|
||||
Pour améliorer la lisibilité, la testabilité et l’évolutivité, le code métier doit être isolé du code technique (accès à la base de données, appels à des APIs…) et de celui des interfaces utilisateurs. C’est le principe de l’architecture hexagonale (également appelée Ports et adaptateurs).
|
||||
|
||||
|
||||
## AtomVM : Erlang, Elixir ou Gleam sur un microcontrôleur
|
||||
|
||||
[Davide Bettio présente AtomVM](https://fosdem.org/2026/schedule/event/YP97YR-atomvm_elixir_erlang_and_gleam_on_microcontrollers/)🇬🇧, une machine virtuelle capable d’exécuter des projets écrits en Erlang, Elixir ou Gleam sur un microcontrôleur comme un ESP32, un Raspberry PI Pico ou un ESP32. Il en explique aussi l’intérêt : tolérance aux erreurs, gestion de la mémoire, de l’asynchronisme, des valeurs binaires...
|
||||
|
||||
## Principe de responsabilité unique en programmation fonctionnelle
|
||||
|
||||
Christian Ekrem montre comment le Principe de Responsabilité Unique (le S de SOLID, *Single Responsibility Principle*) s’applique de façon naturelle dans certains langages fonctionnels. En n’autorisant que l’écriture de fonctions pures, [Elm interdit des antipatterns](https://cekrem.github.io/posts/solid-in-fp-single-responsibility/)🇬🇧 que l’on peut implémenter en TypeScript.
|
||||
|
||||
|
||||
## Another World, une belle leçon d'architecture logicielle
|
||||
|
||||
Olivier Poncet raconte dans une conférence passionnante [comment un jeu culte des années 90 a été conçu](https://www.youtube.com/watch?v=OyJScQqUAsA)🇫🇷. Il explique clairement des détails de conception d'une grande ingéniosité, utilisés pour compenser les faibles ressources du matériel de l'époque.
|
||||
|
||||
-----
|
||||
|
||||
Voilà, c’est tout pour cette semaine.
|
||||
|
||||
Avant de vaquer à d’autres activités, pensez à remplir le [sondage](https://framaforms.org/sondage-craft-letter-1771415205)🇫🇷 si ce n’est pas encore fait !
|
||||
|
|
@ -1,12 +1,15 @@
|
|||
Title: Accueil
|
||||
Date: 2026-02-09 09:00
|
||||
Date: 2026-02-23 09:00
|
||||
URL:
|
||||
save_as: index.html
|
||||
Category: Home
|
||||
JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
|
||||
JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 23 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
|
||||
|
||||
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
|
||||
|
||||
|
||||
# La [lettre n°12]({filename}/newsletter/craft-letter-12.md) est parue !
|
||||
|
||||
La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles
|
||||
issues de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences...
|
||||
|
||||
|
|
@ -34,6 +37,8 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo
|
|||
|
||||
# Archives
|
||||
|
||||
* [Lettre n°12]({filename}/newsletter/craft-letter-12.md)
|
||||
* [Lettre n°11]({filename}/newsletter/craft-letter-11.md)
|
||||
* [Lettre n°10]({filename}/newsletter/craft-letter-10.md)
|
||||
* [Lettre n°9]({filename}/newsletter/craft-letter-9.md)
|
||||
* [Lettre n°8]({filename}/newsletter/craft-letter-8.md)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"python313Packages.pip@latest",
|
||||
"ruby@latest",
|
||||
"hunspellDicts.fr-moderne@latest",
|
||||
"hunspell@latest"
|
||||
"hunspell@latest",
|
||||
"stork@latest"
|
||||
],
|
||||
"shell": {
|
||||
"init_hook": [
|
||||
|
|
|
|||
48
devbox.lock
|
|
@ -301,6 +301,54 @@
|
|||
"store_path": "/nix/store/gphbrsb5wd49qwg9bxby194wwm47awks-ruby-3.4.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stork@latest": {
|
||||
"last_modified": "2026-01-23T17:20:52Z",
|
||||
"resolved": "github:NixOS/nixpkgs/a1bab9e494f5f4939442a57a58d0449a109593fe#stork",
|
||||
"source": "devbox-search",
|
||||
"version": "1.6.0",
|
||||
"systems": {
|
||||
"aarch64-darwin": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/ck1rmp4lh2xis1sadlsbg7aq0105wl3b-stork-1.6.0",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/ck1rmp4lh2xis1sadlsbg7aq0105wl3b-stork-1.6.0"
|
||||
},
|
||||
"aarch64-linux": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/84q9aw2y7fz9ssg391ijspwpa833h2yn-stork-1.6.0",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/84q9aw2y7fz9ssg391ijspwpa833h2yn-stork-1.6.0"
|
||||
},
|
||||
"x86_64-darwin": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/0pdqh1jl67qyqyhh51iszvp1g51i5vy1-stork-1.6.0",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/0pdqh1jl67qyqyhh51iszvp1g51i5vy1-stork-1.6.0"
|
||||
},
|
||||
"x86_64-linux": {
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"path": "/nix/store/0kvfmzsm9fsnv128lwlyc08ak8amrgm8-stork-1.6.0",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"store_path": "/nix/store/0kvfmzsm9fsnv128lwlyc08ak8amrgm8-stork-1.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@ new_content = set_publication_date_for_pelican(content, next_monday)
|
|||
|
||||
new_content = set_publication_date_for_seo(new_content, next_monday)
|
||||
|
||||
link = (
|
||||
f"[lettre n°{args.number}]({{filename}}/newsletter/craft-letter-{args.number}.md)"
|
||||
)
|
||||
new_content = new_content.replace("{LINK}", link)
|
||||
|
||||
for i in reversed(range(args.number)):
|
||||
link = f"* [Lettre n°{i + 1}]({{filename}}/newsletter/craft-letter-{i + 1}.md)\n"
|
||||
new_content += link
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@ JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil
|
|||
|
||||
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
|
||||
|
||||
|
||||
# La {LINK} est parue !
|
||||
|
||||
La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles
|
||||
issues de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences...
|
||||
issus de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences...
|
||||
|
||||
Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vous lire l'édito du [premier numéro]({filename}/newsletter/craft-letter-1.md).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Title: Lettre n°{LETTER_NUMBER} - {DATE}
|
||||
Title: Lettre n°{LETTER_NUMBER} — {DATE}
|
||||
Date: {DATE_DIGITS} 09:00
|
||||
Category: Newsletter
|
||||
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°{LETTER_NUMBER}", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "{DATE_UTC} 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
|
||||
|
|
|
|||
17
themes/blue-penguin/CONTRIBUTORS.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Contributors
|
||||
|
||||
* [Nevan Scott](https://github.com/nevanscott/Mockingbird) (original author)
|
||||
* [wrl](http://ghttps://github.com/guikcdithub.com/wrl) (port to pelican, pelican-mockingbird)
|
||||
* [Jody Frankowski](http://github.com/jody-frankowski) (Blue Penguin)
|
||||
* [Grimbox](https://github.com/Grimbox)
|
||||
* [ix5](https://github.com/ix5)
|
||||
* [dn0](https://github.com/dn0)
|
||||
* [anhtuann](https://github.com/anhtuann)
|
||||
* [aperep](https://github.com/aperep)
|
||||
* [iranzo](https://github.com/iranzo)
|
||||
* [thetlk](https://github.com/thetlk)
|
||||
* [SnorlaxYum](https://github.com/SnorlaxYum)
|
||||
* [guikcd](https://github.com/guikcd)
|
||||
* [jorgesumle](https://github.com/jorgesumle)
|
||||
* [crxxn](https://github.com/crxxn)
|
||||
* [Pascal Le Merrer](https://www.craftletter.fr)
|
||||
53
themes/blue-penguin/README.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||

|
||||
|
||||
# Blue Penguin for pelican
|
||||
A simple theme for pelican. Solarized pygments. Feeds support.
|
||||
|
||||
## Settings
|
||||
```python
|
||||
# all the following settings are *optional*
|
||||
|
||||
# HTML metadata
|
||||
SITEDESCRIPTION = ''
|
||||
|
||||
# all defaults to True.
|
||||
DISPLAY_HEADER = True
|
||||
DISPLAY_FOOTER = True
|
||||
DISPLAY_HOME = True
|
||||
DISPLAY_MENU = True
|
||||
|
||||
# provided as examples, they make ‘clean’ urls. used by MENU_INTERNAL_PAGES.
|
||||
TAGS_URL = 'tags'
|
||||
TAGS_SAVE_AS = 'tags/index.html'
|
||||
AUTHORS_URL = 'authors'
|
||||
AUTHORS_SAVE_AS = 'authors/index.html'
|
||||
CATEGORIES_URL = 'categories'
|
||||
CATEGORIES_SAVE_AS = 'categories/index.html'
|
||||
ARCHIVES_URL = 'archives'
|
||||
ARCHIVES_SAVE_AS = 'archives/index.html'
|
||||
|
||||
# use those if you want pelican standard pages to appear in your menu
|
||||
MENU_INTERNAL_PAGES = (
|
||||
('Tags', TAGS_URL, TAGS_SAVE_AS),
|
||||
('Authors', AUTHORS_URL, AUTHORS_SAVE_AS),
|
||||
('Categories', CATEGORIES_URL, CATEGORIES_SAVE_AS),
|
||||
('Archives', ARCHIVES_URL, ARCHIVES_SAVE_AS),
|
||||
)
|
||||
# additional menu items
|
||||
MENUITEMS = (
|
||||
('GitHub', 'https://github.com/'),
|
||||
('Linux Kernel', 'https://www.kernel.org/'),
|
||||
)
|
||||
```
|
||||
|
||||
## How to contribute
|
||||
Contributions are very welcome. Keep in mind that this theme goal is to be
|
||||
minimalistic/simple. Contributions will be accepted through Github Pull
|
||||
Requests. If you don’t have a Github account you can suggest me your
|
||||
changes by email (which you can find on my github profile).
|
||||
|
||||
## Contributors
|
||||
See [CONTRIBUTORS.md](CONTRIBUTORS.md).
|
||||
|
||||
## License
|
||||
Public domain.
|
||||
BIN
themes/blue-penguin/screenshot.png
Normal file
|
After Width: | Height: | Size: 984 KiB |
4
themes/blue-penguin/static/css/print.css
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
* { background: #fff; }
|
||||
body { font-family: georgia, times, serif; color: black; }
|
||||
blockquote { font-style: italic; color: black; }
|
||||
a:link, a:visited { border-bottom-width: 1px; border-bottom-style: solid; }
|
||||
87
themes/blue-penguin/static/css/pygments.css
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/* Solarized Dark
|
||||
|
||||
For use with Jekyll and Pygments
|
||||
|
||||
https://ethanschoonover.com/solarized
|
||||
|
||||
SOLARIZED HEX ROLE
|
||||
--------- -------- ------------------------------------------
|
||||
base03 #002b36 background
|
||||
base01 #586e75 comments / secondary content
|
||||
base1 #93a1a1 body text / default code / primary content
|
||||
orange #cb4b16 constants
|
||||
red #dc322f regex, special keywords
|
||||
blue #268bd2 reserved keywords
|
||||
cyan #2aa198 strings, numbers
|
||||
green #859900 operators, other keywords
|
||||
*/
|
||||
|
||||
.highlight { background-color: #002b36; color: #93a1a1 }
|
||||
.highlight .c { color: #586e75 } /* Comment */
|
||||
.highlight .err { color: #93a1a1 } /* Error */
|
||||
.highlight .g { color: #93a1a1 } /* Generic */
|
||||
.highlight .k { color: #859900 } /* Keyword */
|
||||
.highlight .l { color: #93a1a1 } /* Literal */
|
||||
.highlight .n { color: #93a1a1 } /* Name */
|
||||
.highlight .o { color: #859900 } /* Operator */
|
||||
.highlight .x { color: #cb4b16 } /* Other */
|
||||
.highlight .p { color: #93a1a1 } /* Punctuation */
|
||||
.highlight .cm { color: #586e75 } /* Comment.Multiline */
|
||||
.highlight .cp { color: #859900 } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #586e75 } /* Comment.Single */
|
||||
.highlight .cs { color: #859900 } /* Comment.Special */
|
||||
.highlight .gd { color: #2aa198 } /* Generic.Deleted */
|
||||
.highlight .ge { color: #93a1a1; font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #dc322f } /* Generic.Error */
|
||||
.highlight .gh { color: #cb4b16 } /* Generic.Heading */
|
||||
.highlight .gi { color: #859900 } /* Generic.Inserted */
|
||||
.highlight .go { color: #93a1a1 } /* Generic.Output */
|
||||
.highlight .gp { color: #93a1a1 } /* Generic.Prompt */
|
||||
.highlight .gs { color: #93a1a1; font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #cb4b16 } /* Generic.Subheading */
|
||||
.highlight .gt { color: #93a1a1 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #cb4b16 } /* Keyword.Constant */
|
||||
.highlight .kd { color: #268bd2 } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #859900 } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #859900 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #268bd2 } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #dc322f } /* Keyword.Type */
|
||||
.highlight .ld { color: #93a1a1 } /* Literal.Date */
|
||||
.highlight .m { color: #2aa198 } /* Literal.Number */
|
||||
.highlight .s { color: #2aa198 } /* Literal.String */
|
||||
.highlight .na { color: #93a1a1 } /* Name.Attribute */
|
||||
.highlight .nb { color: #B58900 } /* Name.Builtin */
|
||||
.highlight .nc { color: #268bd2 } /* Name.Class */
|
||||
.highlight .no { color: #cb4b16 } /* Name.Constant */
|
||||
.highlight .nd { color: #268bd2 } /* Name.Decorator */
|
||||
.highlight .ni { color: #cb4b16 } /* Name.Entity */
|
||||
.highlight .ne { color: #cb4b16 } /* Name.Exception */
|
||||
.highlight .nf { color: #268bd2 } /* Name.Function */
|
||||
.highlight .nl { color: #93a1a1 } /* Name.Label */
|
||||
.highlight .nn { color: #93a1a1 } /* Name.Namespace */
|
||||
.highlight .nx { color: #93a1a1 } /* Name.Other */
|
||||
.highlight .py { color: #93a1a1 } /* Name.Property */
|
||||
.highlight .nt { color: #268bd2 } /* Name.Tag */
|
||||
.highlight .nv { color: #268bd2 } /* Name.Variable */
|
||||
.highlight .ow { color: #859900 } /* Operator.Word */
|
||||
.highlight .w { color: #93a1a1 } /* Text.Whitespace */
|
||||
.highlight .mf { color: #2aa198 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #2aa198 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #2aa198 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #2aa198 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #586e75 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #2aa198 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #93a1a1 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #2aa198 } /* Literal.String.Double */
|
||||
.highlight .se { color: #cb4b16 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #93a1a1 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #2aa198 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #2aa198 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #dc322f } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #2aa198 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #2aa198 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #268bd2 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #268bd2 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #268bd2 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #268bd2 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #2aa198 } /* Literal.Number.Integer.Long */
|
||||
495
themes/blue-penguin/static/css/screen.css
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/* https://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
/* Mockingbird Theme by Nevan Scott nevanscott.com */
|
||||
/* Modified by Jody Frankowski */
|
||||
/* Modified by ix5 */
|
||||
/* Modified by Pascal Le Merrer */
|
||||
|
||||
:root {
|
||||
--link-color: #801515;
|
||||
--link-background-color: #abdae7;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
div,
|
||||
span,
|
||||
applet,
|
||||
object,
|
||||
iframe,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p,
|
||||
blockquote,
|
||||
pre,
|
||||
a,
|
||||
abbr,
|
||||
acronym,
|
||||
address,
|
||||
big,
|
||||
cite,
|
||||
code,
|
||||
del,
|
||||
dfn,
|
||||
em,
|
||||
img,
|
||||
ins,
|
||||
kbd,
|
||||
q,
|
||||
s,
|
||||
samp,
|
||||
small,
|
||||
strike,
|
||||
strong,
|
||||
sub,
|
||||
sup,
|
||||
tt,
|
||||
var,
|
||||
b,
|
||||
u,
|
||||
i,
|
||||
center,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
li,
|
||||
fieldset,
|
||||
form,
|
||||
label,
|
||||
legend,
|
||||
table,
|
||||
caption,
|
||||
tbody,
|
||||
tfoot,
|
||||
thead,
|
||||
tr,
|
||||
th,
|
||||
td,
|
||||
article,
|
||||
aside,
|
||||
canvas,
|
||||
details,
|
||||
embed,
|
||||
figure,
|
||||
figcaption,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
menu,
|
||||
nav,
|
||||
output,
|
||||
ruby,
|
||||
section,
|
||||
summary,
|
||||
time,
|
||||
mark,
|
||||
audio,
|
||||
video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
menu,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol,
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote,
|
||||
q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before,
|
||||
blockquote:after,
|
||||
q:before,
|
||||
q:after {
|
||||
content: "";
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
header,
|
||||
#wrapper {
|
||||
padding: 0 10px;
|
||||
max-width: 910px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
min-width: 500px;
|
||||
}
|
||||
|
||||
a {
|
||||
box-shadow: inset 0 0 0 0 var(--link-background-color);
|
||||
color: var(--link-color);
|
||||
padding: 0 0.25rem;
|
||||
margin: 0 -0.25rem;
|
||||
transition:
|
||||
color 0.3s ease-in-out,
|
||||
box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
box-shadow: inset 800px 0 0 0 var(--link-background-color);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: outside disc;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
line-height: 1em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
img,
|
||||
p,
|
||||
.post > .highlight,
|
||||
.highlighttable,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 1.5em 1.5em 1.5em 0.75em;
|
||||
padding-left: 0.75em;
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
|
||||
.date {
|
||||
color: #ccc;
|
||||
float: left;
|
||||
clear: both;
|
||||
width: 130px;
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
margin: 0 20px 1em 0;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-top: 1.3em;
|
||||
font-family: sans-serif;
|
||||
text-align: right;
|
||||
color: #bbb;
|
||||
}
|
||||
.info a {
|
||||
color: inherit;
|
||||
}
|
||||
.info a.tags {
|
||||
background: #ccc;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
padding: 0 0.3em;
|
||||
border: 1px transparent solid;
|
||||
border-radius: 5px;
|
||||
margin: 0 0 0.3em 0;
|
||||
}
|
||||
.info a.tags:hover {
|
||||
background: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
.info a.tags.selected {
|
||||
border: 1px #999 solid;
|
||||
}
|
||||
|
||||
.post {
|
||||
margin: 0 0 4.5em 150px;
|
||||
}
|
||||
.post.archives {
|
||||
margin-bottom: 1.5em;
|
||||
margin-left: 160px;
|
||||
}
|
||||
.post p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.page {
|
||||
margin: 0 90px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
border-radius: 3px;
|
||||
}
|
||||
.code > .highlight {
|
||||
border-radius: 0px 3px 3px 0px;
|
||||
}
|
||||
.linenos {
|
||||
border-radius: 3px 0px 0px 3px;
|
||||
background-color: #073642;
|
||||
border-right: 1px solid #00232c;
|
||||
color: #586e75;
|
||||
text-shadow: 0px -1px #021014;
|
||||
}
|
||||
td.code {
|
||||
width: 100%;
|
||||
max-width: 100px;
|
||||
}
|
||||
.linenos a {
|
||||
color: #586e75;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 6rem;
|
||||
margin-bottom: 6rem;
|
||||
}
|
||||
|
||||
/*sub and sup stolen from Twitter bootstrap.*/
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
.post pre,
|
||||
.page pre {
|
||||
padding: 0.8em;
|
||||
font-size: 12px;
|
||||
font-family: Monospace;
|
||||
line-height: 1.1em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
form.inline_edit {
|
||||
clear: both;
|
||||
margin: 4.5em 0;
|
||||
background-color: #ddd;
|
||||
color: #000;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.inline_edit .sub {
|
||||
color: #888;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.inline_edit label {
|
||||
float: left;
|
||||
clear: both;
|
||||
width: 140px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.inline_edit .buttons {
|
||||
display: block;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
nav a:hover {
|
||||
color: var(--link-color);
|
||||
text-decoration: underline;
|
||||
background-color: #d3d3d3;
|
||||
}
|
||||
|
||||
nav li.selected a {
|
||||
background-color: var(--link-background-color);
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
header .header_box {
|
||||
padding-top: 4.5em;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
header h2 {
|
||||
font-size: 1em;
|
||||
margin: 0.3em 0;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
.pages {
|
||||
font-family: sans-serif;
|
||||
line-height: 2.5em;
|
||||
margin: 4.5em 0 3em;
|
||||
background-color: #f9f9f9;
|
||||
color: #444;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.pages a.next_page {
|
||||
float: right;
|
||||
width: 140px;
|
||||
text-align: center;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
background-color: #eee;
|
||||
}
|
||||
.pages a.prev_page {
|
||||
float: left;
|
||||
width: 140px;
|
||||
text-align: center;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
background-color: #eee;
|
||||
}
|
||||
.pages a {
|
||||
color: inherit;
|
||||
border: none;
|
||||
}
|
||||
.pages a:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.pages span {
|
||||
display: block;
|
||||
margin: 0 160px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f9f2f4;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
color: #c7254e;
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
font-size: 12.6px;
|
||||
line-height: 18px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
padding-top: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
footer {
|
||||
font-family: sans-serif;
|
||||
line-height: 2.5em;
|
||||
text-align: center;
|
||||
color: #bbb;
|
||||
margin: 3em 0;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
}
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
header,
|
||||
#wrapper {
|
||||
max-width: 500px;
|
||||
min-width: 300px;
|
||||
}
|
||||
.page,
|
||||
.post {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
color: #cccccc;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
11
themes/blue-penguin/templates/analytics.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{% if GOOGLE_ANALYTICS %}
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
try {
|
||||
var pageTracker = _gat._getTracker("{{GOOGLE_ANALYTICS}}");
|
||||
pageTracker._trackPageview();
|
||||
} catch(err) {}</script>
|
||||
{% endif %}
|
||||
22
themes/blue-penguin/templates/archives.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ SITENAME }} | Archives{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h1>Archives</h1>
|
||||
|
||||
{# based on https://stackoverflow.com/questions/12764291/jinja2-group-by-month-year #}
|
||||
|
||||
{% for year, year_group in dates|groupby('date.year')|reverse %}
|
||||
{% for month, month_group in year_group|groupby('date.month')|reverse %}
|
||||
<h4 class="date">{{ (month_group|first).date|strftime('%b %Y') }}</h4>
|
||||
<div class="post archives">
|
||||
<ul>
|
||||
{% for article in month_group %}
|
||||
<li><a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
21
themes/blue-penguin/templates/article.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
{% if article.tags %}
|
||||
<meta name="keywords" content="{{ article.tags|join(",") }}" />
|
||||
{% endif %}
|
||||
{% if article.description %}
|
||||
<meta name="description" content="{{ article.description }}" />
|
||||
{% endif %}
|
||||
<script type="application/ld+json">
|
||||
{{ article.jsonld }}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ SITENAME }} | {{ article.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% include "article_stub.html" %}
|
||||
{% endblock %}
|
||||
37
themes/blue-penguin/templates/article_stub.html
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{% if not articles_page or first_article_of_day %}
|
||||
<h4 class="date">{{ article.date.strftime("%d %b %Y") }}</h4>
|
||||
{% endif %}
|
||||
|
||||
<article class="post">
|
||||
{% if article.title %}
|
||||
<h2 class="title">
|
||||
<a href="{{ SITEURL }}/{{ article.url }}" rel="bookmark" title="Permanent Link to "{{ article.title }}"">{{ article.title }}</a>
|
||||
</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if not articles_page %}
|
||||
{% include "translations.html" %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{{ article.content }}
|
||||
<div class="clear"></div>
|
||||
|
||||
<div class="info">
|
||||
<a href="{{ SITEURL }}/{{ article.url }}">Publié à {{ article.date.strftime("%H:%M") }}</a>
|
||||
{% if article.category.name != "misc" %}
|
||||
· <a href="{{ SITEURL }}/{{ article.category.url }}" rel="tag">{{ article.category }}</a>
|
||||
{% endif %}
|
||||
{% if article.tags %}
|
||||
·
|
||||
{% for t in article.tags %}
|
||||
<a href="{{ SITEURL }}/{{ t.url }}" class="tags{% if tag and tag.name == t.name %} selected{% endif %}">{{ t }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if articles_page and DISQUS_SITENAME %}
|
||||
<a href="{{ SITEURL }}/{{ article.url }}#disqus_thread">Click to read and post comments</a>
|
||||
{% else %}
|
||||
{% include "disqus.html" %}
|
||||
{% endif %}
|
||||
</article>
|
||||
7
themes/blue-penguin/templates/author.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{% extends "index.html" %}
|
||||
|
||||
{% block title %}{{ SITENAME }} | Articles by {{ author }}{% endblock %}
|
||||
{% block ephemeral_nav %}
|
||||
|
||||
{{ ephemeral_nav_link(author, output_file, True) }}
|
||||
{% endblock %}
|
||||
123
themes/blue-penguin/templates/base.html
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
{% macro ephemeral_nav_link(what, where, selected=False) -%}
|
||||
<li class="ephemeral{% if selected %} selected{% endif %}"><a href="{{ SITEURL }}/{{ where }}">{{what}}</a></li>
|
||||
{%- endmacro -%}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ DEFAULT_LANG }}">
|
||||
<head>
|
||||
{% block head %}
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>{% block title %}{{ SITENAME }}{% endblock title %}</title>
|
||||
{# favicon #}
|
||||
<link rel="shortcut icon" type="image/png" href="{{ SITEURL }}/favicon.png">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="{{ SITEURL }}/favicon.ico">
|
||||
{% if FEED_ALL_ATOM %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ FEED_ALL_ATOM }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Full Atom Feed" />
|
||||
{% endif %}
|
||||
{% if FEED_ALL_RSS %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ FEED_ALL_RSS }}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Full RSS Feed" />
|
||||
{% endif %}
|
||||
{% if FEED_ATOM %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ FEED_ATOM }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" />
|
||||
{% endif %}
|
||||
{% if FEED_RSS %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ FEED_RSS }}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" />
|
||||
{% endif %}
|
||||
{% if CATEGORY_FEED_ATOM and category %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ CATEGORY_FEED_ATOM.format(slug=category.slug) }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Categories Atom Feed" />
|
||||
{% endif %}
|
||||
{% if CATEGORY_FEED_RSS and category %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ CATEGORY_FEED_RSS.format(slug=category.slug) }}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Categories RSS Feed" />
|
||||
{% endif %}
|
||||
{% if TAG_FEED_ATOM and tag %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ TAG_FEED_ATOM.format(slug=tag.slug) }}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Tags Atom Feed" />
|
||||
{% endif %}
|
||||
{% if TAG_FEED_RSS and tag %}
|
||||
<link href="{{ FEED_DOMAIN }}/{{ TAG_FEED_RSS.format(slug=tag.slug) }}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" />
|
||||
{% endif %}
|
||||
<link rel="stylesheet" href="{{ SITEURL }}/theme/css/screen.css" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ SITEURL }}/theme/css/pygments.css" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ SITEURL }}/theme/css/print.css" type="text/css" media="print" />
|
||||
<meta name="generator" content="Pelican" />
|
||||
<meta name="description" content="{{ SITEDESCRIPTION }}" />
|
||||
<meta name="author" content="{{ AUTHOR }}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="{{ SITEURL }}" />
|
||||
<meta property="og:title" content="{{ SITENAME }}" />
|
||||
<meta property="og:image" content="{{ SITEURL }}/images/LogoCraftLetter-800px.png" />
|
||||
<meta property="og:image:width" content="800" />
|
||||
<meta property="og:image:height" content="222" />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:description" content="{{ SITEDESCRIPTION }}" />
|
||||
|
||||
<link rel="stylesheet" href="https://files.stork-search.net/basic.css" />
|
||||
{% endblock head %}
|
||||
</head>
|
||||
<body>
|
||||
{% if DISPLAY_HEADER or DISPLAY_HEADER is not defined %}
|
||||
<header>
|
||||
{% if DISPLAY_MENU or DISPLAY_MENU is not defined %}
|
||||
<nav>
|
||||
<ul>
|
||||
{% block ephemeral_nav %}{% endblock %}
|
||||
<!-- {% if DISPLAY_HOME or DISPLAY_HOME is not defined %} -->
|
||||
<!-- <li{% if output_file == "index.html" %} class="selected"{% endif %}><a href="{{ SITEURL }}/">Home</a></li> -->
|
||||
<!-- {% endif %} -->
|
||||
{% if DISPLAY_PAGES_ON_MENU %}
|
||||
{% for p in pages %}
|
||||
<li{% if p == page %} class="selected"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% for title, link in MENUITEMS %}
|
||||
<li><a href="{{ link }}">{{ title }}</a></li>
|
||||
{% endfor %}
|
||||
{% for name, link, file in MENU_INTERNAL_PAGES %}
|
||||
<li{% if output_file == file %} class="selected"{% endif %}><a href="{{ SITEURL }}/{{ link }}">{{ name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<ul>
|
||||
<search>Rechercher : <input data-stork="sitesearch" />
|
||||
<div data-stork="sitesearch-output"></div>
|
||||
</search>
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
<div class="header_box">
|
||||
<h1><a href="{{ SITEURL }}/">{{ SITENAME }}</a></h1>
|
||||
{% if SITESUBTITLE %}
|
||||
<h2>{{ SITESUBTITLE }}</h2>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
{% endif %}
|
||||
<div id="wrapper">
|
||||
<div id="content">
|
||||
<main>
|
||||
{%- block content -%}{%- endblock %}
|
||||
<!-- </main> -->
|
||||
{% if DISPLAY_FOOTER or DISPLAY_FOOTER is not defined %}
|
||||
<div class="clear"></div>
|
||||
<footer>
|
||||
<p>
|
||||
Thème dérivé de <a href="https://github.com/jody-frankowski/blue-penguin">Blue Penguin</a>
|
||||
·
|
||||
Propulsé par <a href="https://getpelican.com">Pelican</a>
|
||||
{% if FEED_ALL_RSS %}
|
||||
·
|
||||
<a href="{{ SITEURL }}/{{ FEED_ALL_RSS }}" rel="alternate">Flux RSS</a>
|
||||
{% endif %}
|
||||
<p>
|
||||
<a href="https://www.craftletter.fr">Craft Letter</a> © 2025 - 2026 par <a href="https://www.linkedin.com/in/pascal-le-merrer/">Pascal Le Merrer</a> est sous licence <a href="https://creativecommons.org/licenses/by-nc-nd/4.0/">CC BY-NC-ND 4.0</a><div><img src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt="CC" style="max-width: 1em;max-height:1em;margin-left: .2em;"><img src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt="BY" style="max-width: 1em;max-height:1em;margin-left: .2em;"><img src="https://mirrors.creativecommons.org/presskit/icons/nc.svg" alt="NC" style="max-width: 1em;max-height:1em;margin-left: .2em;"><img src="https://mirrors.creativecommons.org/presskit/icons/nd.svg" alt="ND" style="max-width: 1em;max-height:1em;margin-left: .2em;"></div>
|
||||
<p/>
|
||||
</footer>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<script src="https://files.stork-search.net/releases/v1.5.0/stork.js"></script>
|
||||
<script>
|
||||
stork.register("sitesearch", "{{ SITEURL }}/search-index.st");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
6
themes/blue-penguin/templates/category.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "index.html" %}
|
||||
{% block title %}{{ SITENAME }} | articles in the "{{ category }}" category{% if articles_page.number != 1 %} | Page {{ articles_page.number }}{% endif %}{% endblock %}
|
||||
{% block ephemeral_nav %}
|
||||
|
||||
{{ ephemeral_nav_link(category, output_file, True) }}
|
||||
{% endblock %}
|
||||
12
themes/blue-penguin/templates/disqus.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{% if DISQUS_SITENAME %}
|
||||
<div id="disqus_thread"></div>
|
||||
<script type="text/javascript">
|
||||
var disqus_shortname = '{{ DISQUS_SITENAME }}';
|
||||
(function() {
|
||||
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
||||
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
})();
|
||||
</script>
|
||||
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a></noscript>
|
||||
{% endif %}
|
||||
17
themes/blue-penguin/templates/index.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ SITENAME }}{% if articles_page.number != 1 %} | Page {{ articles_page.number }}{% endif %}{% endblock %}
|
||||
{% block content %}
|
||||
{% set date = None %}
|
||||
{% for article in articles_page.object_list %}
|
||||
{% if date != article.date.date() %}
|
||||
{% set first_article_of_day = True %}
|
||||
{% else %}
|
||||
{% set first_article_of_day = False %}
|
||||
{% endif %}
|
||||
{% set date = article.date.date() %}
|
||||
{% include "article_stub.html" %}
|
||||
{% endfor %}
|
||||
|
||||
{% include "pagination.html" %}
|
||||
{% endblock %}
|
||||
18
themes/blue-penguin/templates/page.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<script type="application/ld+json">
|
||||
{{ page.jsonld }}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ SITENAME }} | {{ page.title }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="page">
|
||||
<h1>{{ page.title }}</h1>
|
||||
{{ page.content }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
38
themes/blue-penguin/templates/pagination.html
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{# Use PAGINATION_PATTERNS or pagination may break #}
|
||||
{% if DEFAULT_PAGINATION and (articles_page.has_previous() or articles_page.has_next()) %}
|
||||
|
||||
<div class="clear"></div>
|
||||
<div class="pages">
|
||||
{% if PAGINATION_PATTERNS[0][0] != 0 %}
|
||||
{%- if articles_page.has_previous() %}
|
||||
{% if articles_page.previous_page_number() == 1 %}
|
||||
|
||||
<a href="{{ SITEURL }}/" class="prev_page">← Previous</a>
|
||||
{%- else %}
|
||||
|
||||
<a href="{{ SITEURL }}/page/{{ articles_page.previous_page_number() }}" class="prev_page">← Previous</a>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if articles_page.has_next() %}
|
||||
|
||||
<a href="{{ SITEURL }}/page/{{ articles_page.next_page_number() }}" class="next_page">Next →</a>
|
||||
{%- endif %}
|
||||
{% else %}
|
||||
{%- if articles_page.has_previous() %}
|
||||
{% if articles_page.previous_page_number() == 1 %}
|
||||
|
||||
<a href="{{ SITEURL }}/{{ page_name }}.html" class="prev_page">← Previous</a>
|
||||
{%- else %}
|
||||
|
||||
<a href="{{ SITEURL }}/{{ page_name }}{{ articles_page.previous_page_number() }}.html" class="prev_page">← Previous</a>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if articles_page.has_next() %}
|
||||
|
||||
<a href="{{ SITEURL }}/{{ page_name }}{{ articles_page.next_page_number() }}.html" class="next_page">Next →</a>
|
||||
{%- endif %}
|
||||
{% endif %}
|
||||
|
||||
<span>Page {{ articles_page.number }} of {{ articles_paginator.num_pages }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
5
themes/blue-penguin/templates/tag.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "index.html" %}
|
||||
{% block title %}{{ SITENAME }} | articles tagged "{{ tag }}"{% if articles_page.number != 1 %} | Page {{ articles_page.number }}{% endif %}{% endblock %}
|
||||
{% block ephemeral_nav %}
|
||||
{{ ephemeral_nav_link(tag, output_file, True) }}
|
||||
{% endblock %}
|
||||
8
themes/blue-penguin/templates/tags.html
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<ul>
|
||||
{% for tag, articles in tags %}
|
||||
<li><a href="{{ SITEURL }}/{{ tag.url }}">{{ tag }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
6
themes/blue-penguin/templates/translations.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{% if article.translations %}
|
||||
Translations:
|
||||
{% for translation in article.translations %}
|
||||
<a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||