roundabout,
created on Friday, 29 March 2024, 14:19:58 (1711721998),
received on Wednesday, 31 July 2024, 06:54:43 (1722408883)
Author identity: vlad <vlad.muntoiu@gmail.com>
27d17ece01b688bf45527e34503662cb231c8cbc
markdown.py
@@ -104,6 +104,59 @@ class Paragraph(Container):
return "p" class CodeBlock(Element): def __init__(self, content, language="text"): super().__init__() self.content = content self.language = language def __repr__(self): return f"Code block ({self.language}):\n\t" + repr(self.content) @property def tag_name(self): return "pre" class UnorderedList(Element): def __init__(self, content): super().__init__() self.content = content def __repr__(self): return "Unordered list:\n\t" + repr(self.content) @property def tag_name(self): return "ul" class OrderedList(Element): def __init__(self, content): super().__init__() self.content = content def __repr__(self): return "Ordered list:\n\t" + repr(self.content) @property def tag_name(self): return "ol" class ListItem(Paragraph): def __init__(self, content): super().__init__("") self.content = tokenise(content) def __repr__(self): return "List item:\n\t" + repr(self.content) @property def tag_name(self): return "li" class Blockquote(Paragraph): def __init__(self, content): super().__init__("")
@@ -244,11 +297,12 @@ def tokenise(source):
current_block = Element() lines = source.split("\n")lines = [line[1:] if line.startswith(" ") else line for line in source.split("\n")] # remove leading spacesi = 0 while i < len(lines): line = lines[i] print(i, line)if not line.strip(): # Void block
@@ -256,6 +310,21 @@ def tokenise(source):
current_block = Element() i += 1 elif (lines[i].startswith("*") or lines[i].startswith("+") or lines[i].startswith("-")) and lines[i][1:].startswith(" "): if not isinstance(current_block, UnorderedList): tokens.append(current_block) content = [] while i < len(lines) and ((lines[i].startswith("*") or lines[i].startswith("+") or lines[i].startswith("-")) and lines[i][1:].startswith(" ")): inner_content = lines[i][2:].strip() + "\n" i += 1 while i < len(lines) and lines[i].startswith(" "): inner_content += lines[i][2:] + "\n" i += 1 content.append(ListItem(inner_content)) current_block = UnorderedList(content)elif only_chars(line.strip(), "-_* ") and len(line.strip()) >= 3: # Horizontal rule
@@ -276,20 +345,43 @@ def tokenise(source):
content = "" while i < len(lines) and lines[i].startswith(">"):content += lines[i].lstrip(">").strip() + "\n"while i < len(lines) and (lines[i].startswith(">") or (not lines[i].startswith("#") and not lines[i].startswith(">") and lines[i].strip()) and not only_chars(line.strip(), "-_* ") and len(line.strip()) >= 3): content += lines[i].lstrip(">") + "\n"i += 1 current_block = Blockquote(content) elif leading(line, "~") == 3 or leading(line, "`") == 3: if not isinstance(current_block, CodeBlock): tokens.append(current_block) language = line.lstrip("`~").strip() content = "" i += 1 # skip the opening fence while i < len(lines) and not lines[i].strip() in ("```", "~~~"): content += lines[i] + "\n" i += 1 if i < len(lines): i += 1 # prevent a new block from beginning with the closing fence current_block = CodeBlock(content, language=language)else: if not isinstance(current_block, Paragraph): # Paragraph is default# Create a paragraph, if there is no other specifiertokens.append(current_block) content = "" while i < len(lines) and not lines[i].startswith("#") and not lines[i].startswith(">") and lines[i].strip():while (i < len(lines) and not lines[i].startswith("#") and not lines[i].startswith(">") and not lines[i].startswith("* ") and not lines[i].startswith("+ ") and not lines[i].startswith("- ") and not lines[i].startswith("~~~") and not lines[i].startswith("```") and lines[i].strip()):content += lines[i].strip() + "\n" i += 1
@@ -331,28 +423,27 @@ if __name__ == '__main__':
# Generate an AST from a markdown file ast = tokenise( r""" # Hello World!## Title 1### Part 1#### Chapter _1_##### Article 1###### Section 1Lorem **i`p`sum**dolor `sit` ametconsectetur \*adipiscing* elit* * *> Make it as simple as possible, [but not simpler](https://wikipedia.org).> > If you can't explain it simply, you don't understand it well enough....> This is a blockquote > that spans multiple lines > and contains a list: > > - Item 1 > - Item 2 > - Item 3 > - Subitem 1 > - Subitem 2 > > And some more text > Does it also support that bullet? Or continuation lines? * Alternatively, this is a list * That uses asterisks""" ) for i in ast:print(repr(i))# for i in ast: # print(repr(i))# Now convert the AST to HTML print(make_html(ast).prettify(formatter=beautifulsoup.formatter.HTMLFormatter(indent=4)))
static/logo-inkscape.svg
@@ -8,14 +8,13 @@
version="1.1" id="svg1" xml:space="preserve" inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"sodipodi:docname="logo.svg"inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" sodipodi:docname="logo-inkscape.svg"inkscape:export-filename="android-chrome-512x512.png" inkscape:export-xdpi="1024" inkscape:export-ydpi="1024" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink"xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview id="namedview1"
@@ -27,9 +26,9 @@
inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="px" inkscape:zoom="11.253144"inkscape:cx="16.88417"inkscape:cy="23.104654"inkscape:zoom="7.2404119" inkscape:cx="80.31311" inkscape:cy="43.229585"inkscape:current-layer="layer1" showgrid="false" /><defs id="defs1"><clipPath
@@ -197,7 +196,7 @@
style="fill:#fafafa;stroke-width:0.312501;stroke-miterlimit:8" d="M 0,0.49999974 0.99999986,0 0.87499955,0.49999974 0.99999986,0.99999986 Z" sodipodi:nodetypes="ccccc" /></marker><marker markerWidth="4"markerWidth="3.4641015"markerHeight="4" refX="6.9282032" refY="8.0000001"
@@ -210,51 +209,87 @@
style="vector-effect:non-scaling-stroke;fill:#ffffff;stroke-width:0.388505;stroke-miterlimit:8;-inkscape-stroke:hairline" d="M 13.856406,0 12,8.0000001 13.856406,16 0,8.0000001 Z" sodipodi:nodetypes="ccccc" inkscape:transform-center-x="0.61102905" /></marker></defs><ginkscape:transform-center-x="0.61102905" /></marker><marker markerWidth="4" markerHeight="3.464" refX="6.7499981" refY="6.7499989" orient="0.00" id="marker12" viewBox="0 0 13.499996 13.499998" preserveAspectRatio="none" markerUnits="userSpaceOnUse"><path id="path10" style="color:#000000;fill:#ffffff;stroke-width:3.77953;stroke-miterlimit:8;-inkscape-stroke:none" d="M 6.7500019,0 13.499996,13.499998 6.7500019,11.812494 0,13.499998 Z" sodipodi:nodetypes="ccccc" /></marker></defs><ginkscape:label="Strat 1" inkscape:groupmode="layer" id="layer1"><circlestyle="vector-effect:non-scaling-stroke;fill:#2196f3;stroke-width:0.264583;stroke-miterlimit:8;-inkscape-stroke:hairline"id="path1"cx="6.3500004"cy="6.3500004"r="6.3500004" /><gid="layer1"><gid="path5" inkscape:transform-center-x="0.20362483" inkscape:transform-center-y="-3.1617043" transform="rotate(-120)" /><pathtransform="rotate(-120)" /><circle style="vector-effect:non-scaling-stroke;fill:#2196f3;stroke-width:0.264583;stroke-miterlimit:8;-inkscape-stroke:hairline" id="circle1" cx="6.3500004" cy="6.3500004" r="6.3500004" /><pathstyle="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.19062;stroke-linecap:butt;stroke-miterlimit:8;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker3)" id="path4"id="path3"sodipodi:type="arc" sodipodi:cx="-8.674262"sodipodi:cy="2.3242614"sodipodi:cx="-8.6742611" sodipodi:cy="2.3242612"sodipodi:rx="3.7041667" sodipodi:ry="3.7041667" sodipodi:start="1.8325957" sodipodi:end="3.403392" sodipodi:arc-type="arc" d="M -9.6329709,5.9022117 A 3.7041667,3.7041667 0 0 1 -12.252212,1.3655527"d="M -9.6329699,5.9022114 A 3.7041667,3.7041667 0 0 1 -12.252211,1.3655525"sodipodi:open="true" transform="rotate(-120)" inkscape:transform-center-x="-2.9765626" inkscape:transform-center-y="1.2049253" /><usex="0"y="0"xlink:href="#path4"inkscape:transform-center-x="0.41097738"inkscape:transform-center-y="-3.3875401"id="use7"transform="rotate(-120,6.3500004,6.3500004)" /><usex="0"y="0"xlink:href="#use7"inkscape:transform-center-x="2.4979692"inkscape:transform-center-y="1.9167591"id="use8"transform="rotate(-120,6.3500004,6.3500004)" /><rectinkscape:transform-center-y="1.2049253" /><path style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.19062;stroke-linecap:butt;stroke-miterlimit:8;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker3)" id="use3" sodipodi:type="arc" sodipodi:cx="2.3242612" sodipodi:cy="-8.674262" sodipodi:rx="3.7041667" sodipodi:ry="3.7041667" sodipodi:start="1.8325957" sodipodi:end="3.403392" sodipodi:arc-type="arc" d="m 1.3655524,-5.0963118 a 3.7041667,3.7041667 0 0 1 -2.6192415,-4.536659" sodipodi:open="true" transform="rotate(120)" inkscape:transform-center-x="-2.9765626" inkscape:transform-center-y="1.2049253" /><path style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.19062;stroke-linecap:butt;stroke-miterlimit:8;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker3)" id="use4" sodipodi:type="arc" sodipodi:cx="6.3500004" sodipodi:cy="6.3499999" sodipodi:rx="3.7041667" sodipodi:ry="3.7041667" sodipodi:start="1.8325957" sodipodi:end="3.403392" sodipodi:arc-type="arc" d="M 5.3912916,9.9279502 A 3.7041667,3.7041667 0 0 1 2.7720501,5.3912912" sodipodi:open="true" inkscape:transform-center-x="-2.9765626" inkscape:transform-center-y="1.2049253" /><rectstyle="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:1.19062;stroke-linecap:butt;stroke-miterlimit:8;stroke-dasharray:none;stroke-opacity:1" id="rect8"id="rect4"width="12.7" height="12.7" x="0"y="0" /></g></svg>x="9.5367433e-08" y="9.5367433e-08" /><g id="path9"><path style="color:#000000;fill:#607d8b;-inkscape-stroke:none" d="m -17.20504,-11.301342 0.0208,-0.008" id="path11" /><path style="color:#000000;fill:#673ab7;-inkscape-stroke:none" d="m -17.398437,-11.865234 -0.01953,0.0078 0.425782,1.111328 0.02148,-0.0078 z" id="path12" /><g id="g10" /></g></g></svg>