Skip to content

Commit 09f5c20

Browse files
committed
last commit using pelican as a static site generator
1 parent 2d6a802 commit 09f5c20

8 files changed

Lines changed: 660 additions & 4 deletions

File tree

content/code/start_springable.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from springable.simulation import simulate_model
2+
3+
simulate_model('my_spring_model.csv')

content/pages/research.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,36 @@
11
Title: Research
22
Save_as: index.html
33

4-
I'm a researcher interested in nonlinear mechanics and metamaterials! I seek a deeper understanding of the interplay between
4+
I'm a researcher{% sidenote 'side-note-id' 'PhD candidate at AMOLF' %}
5+
interested in nonlinear mechanics and metamaterials
6+
<!-- {% marginnote 'margin-note-id' 'margin-note' %} -->
7+
! I seek a deeper understanding of the interplay between
58
geometry and elasticity in structures. In particular, I'm focusing on harnessing instabilities to embed complex behaviors
9+
<!-- {% marginfigure 'margin-figure-id' 'https://placehold.jp/300x300.png' 'this is the caption' ['alternate image text'] %} -->
610
and functions in mechanical systems.
11+
{% fullwidth 'https://placehold.jp/640x480.png' 'Caption for the image' ['alternate image text']%}
712

8-
What structural design lead to a given functionality? Can we find
13+
14+
{% newthought Start of new paragraph %} What structural design lead to a given functionality? Can we find
915
the building blocks to assemble to form a structure with a desired deformation path?
1016

17+
Here is a YT video
18+
19+
{% youtube KxtkcL0z5j0 %}
20+
21+
what do you think?
22+
23+
A new sound is something that really changes the way you look at the world and maybe decide your next career.
24+
25+
26+
<!-- {% audio 'http://commondatastorage.googleapis.com/codeskulptor-assets/Epoq-Lepidoptera.ogg' %} -->
27+
28+
29+
Ok? Nice?
30+
Text2
31+
{% include_code start_springable.py lang:python :hideall: %}
32+
bonjour
33+
34+
35+
1136

content/publications/countersnapping.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ Date: 2025
77
Link: https://www.pnas.org/doi/10.1073/pnas.2423301122
88
Image: https://placehold.jp/300x300.png
99

10-
Mechanical snapping instabilities are leveraged by natural systems, metamaterials, and devices for rapid sensing, actuation, and shape changes, as well as to absorb impact. In all current forms of snapping, shapes deform in the same direction as the exerted forces, even though there is no physical law that dictates this. Here, we realize countersnapping mechanical structures that respond in the opposite way. In contrast to regular snapping, countersnapping manifests itself in a sudden shortening transition under increasing tension or a sudden increase in tensile force under increasing extension. We design these structures by combining basic flexible building blocks that leverage geometric nonlinearities. We demonstrate experimentally that countersnapping can be employed to obtain new exotic properties, such as unidirectional stick–slip motion, switchable stiffness that does not otherwise affect the state of the system, and passive resonance avoidance. Moreover, we demonstrate that combining multiple countersnapping elements allows sequential stiffness switching for elements coupled in parallel, or instantaneous collective switching for elements in series. By expanding the repertoire of realizable elastic instabilities, our work opens routes to principles for mechanical sensing, computation, and actuation.
10+
Mechanical snapping instabilities. This is a sidenote with a reference are leveraged by natural systems, metamaterials, and devices for rapid sensing, actuation, and shape changes, as well as to absorb impact. In all current forms of snapping, shapes deform in the same direction as the exerted forces, even though there is no physical law that dictates this. Here, we realize countersnapping mechanical structures that respond in the opposite way. In contrast to regular snapping, countersnapping manifests itself in a sudden shortening transition under increasing tension or a[^1] sudden increase in tensile force under increasing extension. We design these structures by combining basic flexible building blocks that leverage geometric nonlinearities. We demonstrate experimentally that countersnapping can be employed to obtain new exotic properties, such as unidirectional stick–slip motion, switchable stiffness that does not otherwise affect the state of the system, and passive resonance avoidance. Moreover, we demonstrate that combining multiple countersnapping elements allows sequential stiffness switching for elements coupled in parallel, or instantaneous collective switching for elements in series. This is a margin note.
11+
. By expanding the repertoire of realizable elastic instabilities, our work opens routes to principles for mechanical sensing, computation, and actuation.
12+
13+
14+
[^1]: This is the footnote text.

pelicanconf.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,24 @@
1212

1313
DEFAULT_LANG = 'EN'
1414

15+
PLUGIN_PATHS = ['plugins']
16+
PLUGINS = ['tufte_liquid_tags']
17+
18+
LIQUID_TAGS = ["img", "literal", "youtube", "audio", "include_code"]
19+
YOUTUBE_THUMB_ONLY = True
20+
YOUTUBE_THUMB_SIZE = 'mq'
21+
CODE_DIR = 'code'
22+
NOTEBOOK_DIR = 'notebooks'
23+
24+
1525
# Feed generation is usually not desired when developing
1626
FEED_ALL_ATOM = None
1727
CATEGORY_FEED_ATOM = None
1828
TRANSLATION_FEED_ATOM = None
1929
AUTHOR_FEED_ATOM = None
2030
AUTHOR_FEED_RSS = None
2131

32+
2233
# Blogroll
2334
LINKS = (
2435
('AMOLF', 'https://amolf.nl/'),

plugins/__init__.py

Whitespace-only changes.

plugins/tufte_liquid_tags.py

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
"""
2+
Sidenote and Margin Tags
3+
----------
4+
This implements a Liquid-style tags margin and side notes
5+
for Pelican
6+
7+
Syntax
8+
------
9+
10+
{% newthought 'Start of new paragraph' %}
11+
{% sidenote 'side-note-id' 'side-note' %}
12+
{% marginnote 'margin-note-id' 'margin-note' %}
13+
{% marginfigure 'margin-figure-id' 'path/to/image' 'this is the caption' ['alternate image text'] %}
14+
{% fullwidth 'path/to/image' 'Caption for the image' ['alternate image text']%}
15+
Output
16+
------
17+
<label for="margin-note-id" class="margin-toggle">+</label>
18+
<input type="checkbox" id="margin-note-id" class="margin-toggle" />
19+
<span class="marginnote">'margin-note'</span>
20+
21+
"""
22+
import re
23+
from pelican.plugins.liquid_tags.mdx_liquid_tags import LiquidTags
24+
25+
NEWTHOUGHTSYNTAX = '''{% newthought some text %}'''
26+
newthought_RE = re.compile('''(?P<newthought_text>.*)''')
27+
28+
MARGINSYNTAX = '''{% marginnote ["margin-note-id"|'margin-note-id'] ["margin-note-id"|'margin-note-id']%}'''
29+
marginnote_RE = re.compile(r'''(?:"|')(?P<marginid>[^"']+)(?:"|')\s+(?:"|')(?P<marginnote>[^"']+)(?:"|')''')
30+
31+
SIDESYNTAX = '''{% sidenote ["side-note-id"|'side-note-id'] ["side-note-id"|'side-note-id']%}'''
32+
sidenote_RE = re.compile(r'''(?:"|')(?P<sideid>[^"']+)(?:"|')\s+(?:"|')(?P<sidenote>[^"']+)(?:"|')''')
33+
34+
FULLWIDTHSYNTAX = '''{% fullwidth [https?:/]/path/to/image "image caption"%}'''
35+
fullwidth_RE = re.compile(r'''(?:"|')(?P<fullwidth_image_path>[^"']+)(?:"|')\s+(?:"|')(?P<fullwidth_image_caption>[^"']+)(?:"|')''')
36+
37+
MAINCOLUMNSYNTAX = '''{% maincolumn "[https?:/]/path/to/image" "image caption" %}'''
38+
maincolumn_RE = re.compile(r'''((['"])(?P<maincolumn_image_path>.*)([^\1]))\s+((['"])(?P<maincolumn_image_caption>.*)([^\4]))''')
39+
40+
MARGINFIGURESYNTAX = '''{% marginfigure "marginfigure_id" "[https?:/]/path/to/image" "image caption"%}'''
41+
marginfigure_RE = re.compile(r'''((['"])(?P<marginfigure_id>.*)([^\1]))\s+((['"])(?P<marginfigure_image_path>.*)([^\4]))\s+((['"])(?P<marginfigure_image_caption>.*)([^\7]))''')
42+
43+
@LiquidTags.register('marginnote')
44+
def marginnote(preprocessor, tag, markup):
45+
marginnote_attrs = None
46+
47+
# Parse the markup string
48+
marginnote_match = marginnote_RE.search(markup)
49+
if marginnote_match:
50+
marginnote_attrs = marginnote_match.groupdict()
51+
else:
52+
raise ValueError('Error processing input. '
53+
'Expected syntax: {0}'.format(MARGINSYNTAX))
54+
55+
marginnote_html = '''<label for="''' + marginnote_attrs['marginid']
56+
marginnote_html += '''" class="margin-toggle">&#8853;</label>'''
57+
marginnote_html += '''<input type="checkbox" id="'''
58+
marginnote_html += marginnote_attrs['marginid']
59+
marginnote_html += '''" class="margin-toggle" />'''
60+
marginnote_html += '''<span class="marginnote">'''
61+
marginnote_html += marginnote_attrs['marginnote']
62+
marginnote_html += '''</span>'''
63+
64+
return marginnote_html
65+
66+
67+
@LiquidTags.register('sidenote')
68+
def sidenote(preprocessor, tag, markup):
69+
sidenote_attrs = None
70+
71+
# Parse the markup string
72+
sidenote_match = sidenote_RE.search(markup)
73+
if sidenote_match:
74+
sidenote_attrs = sidenote_match.groupdict()
75+
else:
76+
raise ValueError('Error processing input. '
77+
'Expected syntax: {0}'.format(SIDESYNTAX))
78+
79+
sidenote_html = '''<label for="''' + sidenote_attrs['sideid']
80+
#This is the difference between sidenote and margin note
81+
sidenote_html += '''" class="margin-toggle sidenote-number"></label>'''
82+
sidenote_html += '''<input type="checkbox" id="'''
83+
sidenote_html += sidenote_attrs['sideid']
84+
sidenote_html += '''" class="margin-toggle" />'''
85+
sidenote_html += '''<span class="sidenote">'''
86+
sidenote_html += sidenote_attrs['sidenote']
87+
sidenote_html += '''</span>'''
88+
89+
return sidenote_html
90+
91+
92+
@LiquidTags.register('newthought')
93+
def newthought(preprocessor, tag, markup):
94+
newthought_attrs = None
95+
96+
# Parse the markup string
97+
newthought_match = newthought_RE.search(markup)
98+
if newthought_match:
99+
newthought_attrs = newthought_match.groupdict()
100+
else:
101+
raise ValueError('Error processing input. '
102+
'Expected syntax: {0}'.format(NEWTHOUGHTSYNTAX))
103+
104+
newthought_html = '''<span class='newthought'>'''
105+
newthought_html += newthought_attrs['newthought_text']
106+
newthought_html += '''</span>'''
107+
108+
return newthought_html
109+
110+
@LiquidTags.register('fullwidth')
111+
def fullwidth(preprocessor, tag, markup):
112+
fullwidth_attrs = None
113+
114+
# Parse the markup string
115+
fullwidth_match = fullwidth_RE.search(markup)
116+
if fullwidth_match:
117+
fullwidth_attrs = fullwidth_match.groupdict()
118+
else:
119+
raise ValueError('Error processing fullwidth input.'
120+
'Expected syntax: {0}'.format(FULLWIDTHSYNTAX))
121+
122+
fullwidth_html = '''<figure class="fullwidth">'''
123+
fullwidth_html += '''<img src="'''
124+
fullwidth_html += fullwidth_attrs['fullwidth_image_path']
125+
fullwidth_html += '''">'''
126+
fullwidth_html += '''<figcaption>'''
127+
fullwidth_html += fullwidth_attrs['fullwidth_image_caption']
128+
fullwidth_html += '''</figcation></figure>'''
129+
130+
return fullwidth_html
131+
132+
133+
@LiquidTags.register('maincolumn')
134+
def maincolumn(preprocessor, tag, markup):
135+
maincolumn_attrs = None
136+
137+
# Parse the markup string
138+
maincolumn_match = maincolumn_RE.search(markup)
139+
if maincolumn_match:
140+
maincolumn_attrs = maincolumn_match.groupdict()
141+
else:
142+
raise ValueError('Error processing maincolumn input. '
143+
'Expected syntax: {0}'.format(MAINCOLUMNSYNTAX))
144+
145+
maincolumn_html = '''<figure>'''
146+
maincolumn_html += '''<figcaption>'''
147+
maincolumn_html += maincolumn_attrs['maincolumn_image_caption']
148+
maincolumn_html += '''</figcaption>'''
149+
maincolumn_html += '''<img src="'''
150+
maincolumn_html += maincolumn_attrs['maincolumn_image_path']
151+
maincolumn_html += '''"/></figure>'''
152+
153+
return maincolumn_html
154+
155+
156+
@LiquidTags.register('marginfigure')
157+
def marginfigure(preprocessor, tag, markup):
158+
marginfigure_attrs = None
159+
160+
# Parse the markup string
161+
marginfigure_match = marginfigure_RE.search(markup)
162+
if marginfigure_match:
163+
marginfigure_attrs = marginfigure_match.groupdict()
164+
else:
165+
raise ValueError('Error processing marginfigure input. \n'
166+
'Expected syntax: {0}'.format(MARGINFIGURESYNTAX))
167+
168+
marginfigure_html = '''<label for="''' + marginfigure_attrs['marginfigure_id']
169+
marginfigure_html += '''" class="margin-toggle">&#8853;</label>'''
170+
marginfigure_html += '''<input type="checkbox" id="'''
171+
marginfigure_html += marginfigure_attrs['marginfigure_id']
172+
marginfigure_html += '''" class="margin-toggle" />'''
173+
marginfigure_html += '''<span class="marginnote">'''
174+
marginfigure_html += '''<img class="fullwidth" src="'''
175+
marginfigure_html += marginfigure_attrs['marginfigure_image_path']
176+
marginfigure_html += '''" alt="'''
177+
marginfigure_html += marginfigure_attrs['marginfigure_image_caption']
178+
marginfigure_html += '''"/><br/>'''
179+
marginfigure_html += marginfigure_attrs['marginfigure_image_caption']
180+
marginfigure_html += '''</span>'''
181+
182+
return marginfigure_html
183+
184+
185+
186+
#----------------------------------------------------------------------
187+
# This import allows Tufte tags to be a Pelican plugin
188+
from pelican.plugins.liquid_tags import register

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
pelican[markdown]
1+
pelican[markdown]
2+
pelican-liquid-tags

0 commit comments

Comments
 (0)