diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9593e387a8c303867b1a83d240ce5a94ca28af2e --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# cobbled paths + +from figlet2svgbob, creating contextual stroke font ready to plot. + +this is called _cobbled paths_ as a reminder of the permeability between the discrete and the continuous. +smooth connected paths are made out of an extremely restrictive grid, like multiple blocky stones form a tortuous path. + +## dependencies + +## font database + +* figlet offical ftp at <ftp://ftp.figlet.org> + * `ours` the original default font made by the developper and given with the program, in early 1993 + * `contributed` fonts made by figlet amateur and submitted to the official figlet ftp, from before 1993 to 2005 + * `c64` are fonts that are only made of the `#` character, the most black ascii char, is if it was a pixel + * `bdffont` are fonts automatically made using bdf2figlet, converting [Glyph Bitmap Distribution Format](https://en.wikipedia.org/wiki/Glyph_Bitmap_Distribution_Format), often from adobe to `c64` like font. +* figlet font library of JavE (a free Ascii Editor), <http://www.jave.de/figlet/fonts.html>. those also include the figlet ftp native, they where sorted in order to keep only the uniques ones. + + +## todo + +* redo catalogue! + + +* iframe per category for less computing time +* left and right reload in draw & font +* input listen when opening page (for browser history remember) +* factorise JS +* factorise CSS +* show font-info file +* option to save as hpgl \ No newline at end of file diff --git a/__pycache__/hpgl_multipen_encoder.cpython-38.pyc b/__pycache__/hpgl_multipen_encoder.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c390ed8b16536a524da8eaa5025e7c96e43f5b19 Binary files /dev/null and b/__pycache__/hpgl_multipen_encoder.cpython-38.pyc differ diff --git a/__pycache__/hpgl_multipen_output.cpython-38.pyc b/__pycache__/hpgl_multipen_output.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94a2efa6330955f9b6e8c3e64c6e2df8c230d724 Binary files /dev/null and b/__pycache__/hpgl_multipen_output.cpython-38.pyc differ diff --git a/__pycache__/hpgl_output_adapted.cpython-38.pyc b/__pycache__/hpgl_output_adapted.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b340e0ced3933964ec6b1496ef29b43225f81a72 Binary files /dev/null and b/__pycache__/hpgl_output_adapted.cpython-38.pyc differ diff --git a/__pycache__/svg_to_hpgl.cpython-38.pyc b/__pycache__/svg_to_hpgl.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be192cfd0cc31c634a451d5fb59e06108bf8fb6f Binary files /dev/null and b/__pycache__/svg_to_hpgl.cpython-38.pyc differ diff --git a/app.py b/app.py index 9d34b60b5b247bc6c96a93e2c78fe807389f7938..c5d1896187f1d8d3c2dbe62975ccb021268c29af 100644 --- a/app.py +++ b/app.py @@ -75,15 +75,28 @@ autofix = [ def most_common(lst): return max(set(lst), key=lst.count) -def text2figlet(input, figfont): - figlet = subprocess.run(["figlet", input, "-f", figfont, "-w", "160"], stdout = subprocess.PIPE, text=True) - return figlet.stdout - -def ascii2svg(ascii_input, weight): - svgbob = subprocess.run(["svgbob_cli", '--stroke-width', weight], input = ascii_input, stdout = subprocess.PIPE, text=True) - return svgbob.stdout +def text2figlet(text, figfont): + print('--- FIGLET SUBPROCESS') + figlet = subprocess.run(["figlet", text, "-f", figfont, "-w", "160"], stdout = subprocess.PIPE, stderr = subprocess.PIPE, text=True) + print(figlet.stdout) + + if figlet.returncode == 0: + answer = (True, figlet.stdout) + else: + answer = (False, figlet.stderr) + + return answer + +def ascii2svg(ascii, weight): + if ascii: + print('--- SVGBOB SUBPROCESS') + svgbob = subprocess.run(["svgbob_cli", '--stroke-width', weight], input = ascii, stdout = subprocess.PIPE, text=True) + return svgbob.stdout + else: + return "ERROR: etherpad request failed" def ascii_autofix(ascii): + print('--- REGEX AUTOFIX') for regex, replace in autofix: ascii = re.sub(regex, replace, ascii) return ascii @@ -92,11 +105,29 @@ def autofix_indication(ascii): for regex, replace in autofix: # the two markers have to not appear in any regex ascii = re.sub(regex, "$" + replace + "€", ascii) - ascii = re.sub("[\$]", "<span class='fix'>", ascii) ascii = re.sub("[\€]", "</span>", ascii) return ascii +def get_pad(url): + # get pad content + print('--- ETHERPAD REQUEST') + print(url) + pad_export = requests.get(url + '/export/txt') + if pad_export.status_code == requests.codes.ok: + answer = (True, pad_export.text) + else: + answer = (False, "ERROR: etherpad request failed") + return answer + +def make_figfont(ascii): + print('--- MAKE TEMP FIGFONT') + (figfont_file, figfont_path) = tempfile.mkstemp(suffix='.flf') + print(figfont_path) + with open(figfont_path, 'w') as figfont_file: + figfont_file.write(ascii) + return figfont_path + # ROUTES # ------------------------------ @@ -151,13 +182,12 @@ def drawing(id): } params['pad-full'] = etherpad + prefix + params['pad'] - # get pad content - print(' getting ' + params['pad-full']) - pad_export = requests.get(params['pad-full'] + '/export/txt') - ascii_input = pad_export.text - - # to SVG - svg = ascii2svg(ascii_input, params['weight']) + pad_answer = get_pad(params['pad-full']) + if pad_answer[0]: + ascii = pad_answer[1] + svg = ascii2svg(ascii, params['weight']) + else: + svg = pad_answer[1] return render_template( 'drawing.html', @@ -178,7 +208,7 @@ def drawing(id): def font(): params = { - 'text': request.args.get('t') or 'Cobbled Paths', + 'text': request.args.get('t') or 'the quick brown fox jumps over the lazy dog', 'pad': request.args.get('p') or 'standard', 'weight': request.args.get('w') or '3', } @@ -193,30 +223,29 @@ def font(): def writing(id): params = { - 'text': request.args.get('t') or 'Cobbled Paths', + 'text': request.args.get('t') or 'the quick brown fox jumps over the lazy dog', 'pad': id or 'standard', 'weight': request.args.get('w') or '3', } params['pad-full'] = etherpad + prefix + params['pad'] - # get pad content - print(' getting ' + params['pad-full']) - pad_export = requests.get(params['pad-full'] + '/export/txt') - ascii_input = pad_export.text + pad_answer = get_pad(params['pad-full']) + # TODO: only create new file if content of pad changed # store as a temporary file - print('--- saving figfont as temp ---') - (figfont_file, figfont_path) = tempfile.mkstemp(suffix='.flf') - print(figfont_path) - with open(figfont_path, 'w') as figfont_file: - figfont_file.write(ascii_input) - - print('--- opening the figfont ---') - ascii = text2figlet(params['text'], figfont_path) - print(ascii) - print('--- rendering to svg ---') - svg = ascii2svg(ascii, params['weight']) + if pad_answer[0]: + ascii = pad_answer[1] + figfont = make_figfont(ascii) + figlet_answer = text2figlet(params['text'], figfont) + if figlet_answer[0]: + ascii = figlet_answer[1] + svg = ascii2svg(figlet_answer[1], params['weight']) + else: + ascii = svg = figlet_answer[1] + + else: + ascii = svg = pad_answer[1] return render_template( 'writing.html', @@ -234,51 +263,51 @@ def writing(id): # # FIGLET 2 SVGBOB INTERACTIVE CATALOGUE -@app.route("/catalogue.html") -def catalogue(): +# @app.route("/catalogue.html") +# def catalogue(): - # text and weight as get parameter - params = { - 'text': request.args.get('t') or 'Echoes', - 'weight': request.args.get('w') or '3', - } - - # walk in the figlet font directory - for root, dirs, files in os.walk(fonts_directory): - for name in files: - - (basename, ext) = os.path.splitext(name) - if ext in possible_extensions: - - figfont = os.path.join(root, name) - print(figfont) - - # get font category out of last folder - catalogue = root.split('/')[-2] - type = root.split('/')[-1] - if type in output: +# # text and weight as get parameter +# params = { +# 'text': request.args.get('t') or 'Echoes', +# 'weight': request.args.get('w') or '3', +# } + +# # walk in the figlet font directory +# for root, dirs, files in os.walk(fonts_directory): +# for name in files: + +# (basename, ext) = os.path.splitext(name) +# if ext in possible_extensions: + +# figfont = os.path.join(root, name) +# print(figfont) + +# # get font category out of last folder +# catalogue = root.split('/')[-2] +# type = root.split('/')[-1] +# if type in output: - f = {} - output[type]['fonts'].append(f) - f['name'] = name - f['catalogue'] = catalogue - f['ascii'] = text2figlet(params['text'], figfont) - f['svg'] = ascii2svg(f['ascii'], params['weight']) +# f = {} +# output[type]['fonts'].append(f) +# f['name'] = name +# f['catalogue'] = catalogue +# f['ascii'] = text2figlet(params['text'], figfont) +# f['svg'] = ascii2svg(f['ascii'], params['weight']) - # regex auto_fix - f['ascii_fix'] = ascii_autofix(f['ascii']) +# # regex auto_fix +# f['ascii_fix'] = ascii_autofix(f['ascii']) - if f['ascii'] != f['ascii_fix']: - f['autofix'] = True - f['ascii_fix_indication'] = autofix_indication(f['ascii_fix']) - f['svg_fix'] = ascii2svg(f['ascii_fix'], params['weight']) +# if f['ascii'] != f['ascii_fix']: +# f['autofix'] = True +# f['ascii_fix_indication'] = autofix_indication(f['ascii_fix']) +# f['svg_fix'] = ascii2svg(f['ascii_fix'], params['weight']) - return render_template( - 'catalogue.html', - title = title, - databases = databases, - output = output, - params = params) +# return render_template( +# 'catalogue.html', +# title = title, +# databases = databases, +# output = output, +# params = params) # _ _ _ @@ -302,10 +331,10 @@ def hpgl (id): # get pad content print(' getting ' + params['pad-full']) pad_export = requests.get(params['pad-full'] + '/export/txt') - ascii_input = pad_export.text + ascii = pad_export.text # to SVG - svg = ascii2svg(ascii_input, params['weight']) + svg = ascii2svg(ascii, params['weight']) # store as a temporary file (svg_file, svg_path) = tempfile.mkstemp() diff --git a/hpgl_output_adapted.py b/hpgl_output_adapted.py index 688e169301b11a7864af1b3d8d7b4905d4443dd2..7e694f7a2931d2e41a42e97b32d4aed6bd28e86a 100644 --- a/hpgl_output_adapted.py +++ b/hpgl_output_adapted.py @@ -19,8 +19,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from __future__ import print_function +import sys sys.path.append('/usr/share/inkscape/extensions') +sys.path.append('/snap/inkscape/10555/share/inkscape/extensions') import inkex from inkex.localization import inkex_gettext as _ @@ -70,6 +72,7 @@ class HpglOutputAdapted(inkex.OutputExtension): ) def save(self, stream): + print('start') self.options.debug = False # get hpgl data if len(self.svg.xpath("//svg:use|//svg:flowRoot|//svg:text")) > 0: @@ -79,6 +82,9 @@ class HpglOutputAdapted(inkex.OutputExtension): hpgl = encoder.getHpgl() except hpgl_encoder.NoPathError: raise inkex.AbortExtension(_("No convertible objects were found")) + + print('middle') + # convert raw HPGL to HPGL hpgl_init = "IN" # if self.options.force > 0: @@ -88,7 +94,9 @@ class HpglOutputAdapted(inkex.OutputExtension): hpgl = hpgl_init + hpgl + ";SP0;PU0,0;IN; " # Make it available externally self.hpgl = hpgl - stream.write(hpgl.encode("utf-8")) + # stream.write(hpgl.encode("utf-8")) + + print('end') if __name__ == "__main__": diff --git a/static/css/interface.css b/static/css/interface.css index 72a86b2e32806b2cb9c03e5de51965805450d92b..d27881819c0120eaeabf4919c97c74f37666a886 100644 --- a/static/css/interface.css +++ b/static/css/interface.css @@ -1,11 +1,13 @@ :root{ --bar-h: 3rem; + --c-link: blue; + --c-back: whitesmoke; + --c-default: black; --c-contributed: palegreen; --c-jave: mediumpurple; - --c-back: whitesmoke; } .default{ --c: var(--c-default); @@ -24,28 +26,13 @@ body{ line-height: 1.45; } a{ - color: currentColor; + color: var(--c-link); } a:hover{ font-weight: bold; } - -ul.special{ - display: flex; - gap: 1rem; - justify-content: center; - align-items: baseline; -} -.special a{ - display: block; - border: 1px solid black; - padding: 2rem 3rem; - border-radius: 2rem; - text-decoration: none; -} -ul.classic{ - list-style: initial; - padding: 0 1rem; +p{ + margin: 0.5rem 0; } /* BAR @@ -62,25 +49,14 @@ body.draw{ nav ul, .controls{ box-sizing: border-box; - height: var(--bar-h); position: fixed; width: 100%; z-index: 999; - gap: 1rem; display: flex; align-items: center; - border-bottom: 1px solid black; } nav ul{ top: 0; - background: black; - color: white; -} -.controls{ - top: var(--bar-h); - background-color: var(--c-back); - border-bottom: 1px solid black; - padding: 1rem 2rem; } nav ul li{ flex-grow: 1; @@ -89,16 +65,32 @@ nav ul li:not(:last-child){ border-right: 1px solid var(--c-back); } nav ul a{ - padding: 1rem 2rem; + color: white; + padding: 0 2rem; display: flex; align-items: center; justify-content: center; text-decoration: none; + height: var(--bar-h); + background-color: black; + box-sizing: border-box; +} +nav ul a.active{ + background-color: var(--c-link); } /* CONTROLS ================================================= */ +.controls{ + gap: 0.5rem; + top: var(--bar-h); + background-color: var(--c-back); + border-bottom: 1px solid black; + padding: 0rem 2rem; + height: var(--bar-h); +} + h1,h2{ font-weight: bold; } @@ -127,6 +119,14 @@ label{ padding: 1rem 2rem; border-bottom: 1px solid black; } +.two-columns{ + display: flex; + flex-wrap: wrap; + gap: var(--bar-h); +} +.two-columns > *{ + flex: 1 1 0%; +} .legend::before{ content: ''; @@ -267,13 +267,7 @@ span.fix{ fill: red !important; } -/* font info */ -.info-label{ - border-bottom: solid mediumblue 3px; -} - /* body class checkboxes */ - .font div.fix{ visibility: hidden; } @@ -286,30 +280,53 @@ body.check-fix .font div.fix{ body.check-text .svgbob text{ visibility: visible; } -/* .fix{ - visibility: hidden; -} -body.check-fix .fix{ - visibility: visible; -} */ /* TITLE ================================================= */ .title.font{ - padding: 1rem 2rem; + padding: 3rem 2rem; + gap: 1rem var(--bar-h); + grid-template-columns: repeat(2, calc(50% - calc(var(--bar-h) / 2))); } .title .f-ascii{ margin-left: auto; padding: 0; background: initial; + grid-row: auto; } .title .f-svg{ + grid-row: auto; margin-right: auto; padding: 0; background: initial; } +.title .special{ + grid-column: 1 / -1; + grid-row: 2 / span 1; +} +ul.special{ + display: flex; + gap: 1rem; + justify-content: center; + align-items: baseline; +} +.special a{ + display: block; + border: 1px solid currentColor; + padding: 2rem 3rem; + border-radius: 2rem; + text-decoration: none; +} +ul.classic{ + list-style: initial; + padding: 0 1rem; + margin: 0.5rem 0; +} + +/* DRAW + ================================================= */ .draw .font{ height: calc(100vh - var(--bar-h) * 2); @@ -336,4 +353,23 @@ body.check-fix .fix{ width: 100%; height: 100%; display: block; +} + +.figfont{ + grid-template-columns: 32rem 1fr; +} + +.reload::after{ + content: 'reload'; + position: absolute; + inset: 0; + background-color: rgba(0,0,205,0.2); + z-index: 999; + pointer-events: none; + color: white; + display: flex; + justify-content: center; + align-items: center; + font-weight: bold; + } \ No newline at end of file diff --git a/svg_to_hpgl.py b/svg_to_hpgl.py index 0a3acf36e9f2f95f24cb5a6c56adebf9a927b042..9b1930d2fa35a874ba6392945d51864197efb75c 100644 --- a/svg_to_hpgl.py +++ b/svg_to_hpgl.py @@ -3,7 +3,7 @@ from hpgl_output_adapted import HpglOutputAdapted def svgToHPGL (path, speed=1, penCount=8, force=2): e = HpglOutputAdapted() - e.affect([ + e.run([ '--orientation', '0', '--force', '0', '--overcut', '0', @@ -12,7 +12,6 @@ def svgToHPGL (path, speed=1, penCount=8, force=2): '--toolOffset', '0', '--autoAlign', 'false', '--speed', str(speed), - '--penCount', str(penCount), '--force', str(force), path], False) diff --git a/templates/base.html b/templates/base.html index e4ddc5bc9b52023e84fb33235437b276ed159d92..19b91b2387a25b86e47d4648954fe6dfadb495f0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -24,10 +24,10 @@ <nav> <ul> - <li><a href="/">index</a></li> - <li><a href="/draw.html">draw</a></li> - <li><a href="/font.html">font</a></li> - <!-- <li><a href="/catalogue.html">catalogue</a></li> --> + <li><a {% if request.url_rule.endpoint == "index" %}class="active"{% endif %} href="/"> index</a></li> + <li><a {% if request.url_rule.endpoint == "draw" %}class="active"{% endif %} href="/draw.html">draw</a></li> + <li><a {% if request.url_rule.endpoint == "font" %}class="active"{% endif %} href="/font.html">font</a></li> + <li><a {% if request.url_rule.endpoint == "catalogue" %}class="active"{% endif %} href="/catalogue.html">catalogue</a></li> </ul> </nav> diff --git a/templates/font.html b/templates/font.html index 540ce82baf588430939d29c5ace1186ddf10121b..6a943d8b422fc518835b5af7f95e678845f1a9f1 100644 --- a/templates/font.html +++ b/templates/font.html @@ -13,89 +13,118 @@ <button id="button-svg">generate</button> - <input class="get-input" type="text" value="{{params['text']}}" data-name="t" data-frame="svg-iframe"/> + <input class="get-input" id="text-input" type="text" value="{{params['text']}}" data-name="t" data-frame="svg-iframe"/> + + <label for="upper-checkbox">uppercase</label> + <input id="upper-checkbox" type="checkbox"/> <label>weight</label> <input class="get-input" type="range" min="1" max="8" value="{{params['weight']}}" data-name="w" data-frame="svg-iframe"/> - <label class="text-label" for="text-checkbox" + <label for="text-checkbox" title="display the remaining text in the svg output in red"> output text</label> <input id="text-checkbox" type="checkbox" class="get-input" class="body-class-check" value="check-text" data-name="c" data-frame="svg-iframe" checked/> - - <script> - function updateGET(frame, param, value){ - // object from GET parameters - let [base_src, params_src] = frame.src.split("?"); - let params = new URLSearchParams(params_src); - // update param - params.set(param, value); - // reconstituate URL - let new_src = base_src + "?" + params.toString(); - // set and refresh - frame.src = new_src; - } - - let button_pad = document.getElementById('button-pad'); - let button_svg = document.getElementById('button-svg'); - - // --- pad go button - button_pad.addEventListener('click', function(){ - let svg_iframe = document.getElementById('svg-iframe'); - let pad_iframe = document.getElementById('pad-iframe'); - let input = document.getElementById(button_pad.dataset.use); - let value = input.value; - let param = input.dataset.name; - - let pad_src = pad_iframe.src; - pad_src = pad_src.split('-'); - pad_src[pad_src.length-1] = value; - pad_src = pad_src.join('-'); - pad_iframe.src = pad_src; - - let svg_src = svg_iframe.src; - svg_src = svg_src.split('/'); - svg_src[svg_src.length-1] = value; - svg_src = svg_src.join('/'); - svg_iframe.src = svg_src; - - }); - - // --- svg generation button - button_svg.addEventListener('click', function(){ - let svg_iframe = document.getElementById('svg-iframe'); - console.log("IFRAME RELOAD"); - svg_iframe.contentWindow.location.reload(); - }); - - // --- get-input but on the pad and checkbox but on the pad - let inputs = document.getElementsByClassName('get-input'); - for(let input of inputs){ - input.addEventListener('input', function(){ - let frame = document.getElementById(input.dataset.frame); - const url = new URL(frame.src); - - if(input.type == 'checkbox'){ - url.searchParams.set(input.dataset.name, input.checked); - } - else{ - url.searchParams.set(input.dataset.name, input.value); - } - console.log(url); - // frame.contentWindow.history.replaceState(null, null, url); - frame.src = url - }); - } - </script> </header> - <div class="font"> + <div class="font figfont reload" id="main"> <iframe class="f-ascii" id="pad-iframe" src="{{params['pad-full']}}"> </iframe> <iframe class="f-double" id="svg-iframe" src="/writing/{{params['pad']}}"> </iframe> </div> + <script> + let button_pad = document.getElementById('button-pad'); + let button_svg = document.getElementById('button-svg'); + let svg_iframe = document.getElementById('svg-iframe'); + let pad_iframe = document.getElementById('pad-iframe'); + + function updateGET(frame, param, value){ + // object from GET parameters + let [base_src, params_src] = frame.src.split("?"); + let params = new URLSearchParams(params_src); + // update param + params.set(param, value); + // reconstituate URL + let new_src = base_src + "?" + params.toString(); + // set and refresh + frame.src = new_src; + } + + // --- pad go button + button_pad.addEventListener('click', function(){ + let input = document.getElementById(button_pad.dataset.use); + let value = input.value; + let param = input.dataset.name; + + let pad_src = pad_iframe.src; + pad_src = pad_src.split('-'); + pad_src[pad_src.length-1] = value; + pad_src = pad_src.join('-'); + pad_iframe.src = pad_src; + + let svg_src = svg_iframe.src; + svg_src = svg_src.split('/'); + svg_src[svg_src.length-1] = value; + svg_src = svg_src.join('/'); + + document.getElementById('main').classList.add("reload"); + svg_iframe.src = svg_src; + + }); + + // --- svg generation button + button_svg.addEventListener('click', function(){ + document.getElementById('main').classList.add("reload"); + svg_iframe.contentWindow.location.reload(); + }); + + // --- get-input but on the pad and checkbox but on the pad + let inputs = document.getElementsByClassName('get-input'); + for(let input of inputs){ + input.addEventListener('change', function(){ + let frame = document.getElementById(input.dataset.frame); + const url = new URL(frame.src); + + if(input.type == 'checkbox'){ + url.searchParams.set(input.dataset.name, input.checked); + } + else{ + url.searchParams.set(input.dataset.name, input.value); + } + // frame.contentWindow.history.replaceState(null, null, url); + document.getElementById('main').classList.add("reload"); + frame.src = url; + }); + } + + let upper_checkbox = document.getElementById('upper-checkbox'); + let text_input = document.getElementById('text-input'); + upper_checkbox.addEventListener('change', function(){ + if(upper_checkbox.checked){ + text_input.value = text_input.value.toUpperCase(); + let frame = document.getElementById("svg-iframe"); + const url = new URL(frame.src); + url.searchParams.set(text_input.dataset.name, text_input.value); + document.getElementById('main').classList.add("reload"); + frame.src = url + } + else{ + text_input.value = text_input.value.toLowerCase(); + let frame = document.getElementById("svg-iframe"); + const url = new URL(frame.src); + url.searchParams.set(text_input.dataset.name, text_input.value); + document.getElementById('main').classList.add("reload"); + frame.src = url + } + }) + + svg_iframe.addEventListener("load", function() { + document.getElementById('main').classList.remove("reload"); + }); +</script> + {% endblock %} diff --git a/templates/index.html b/templates/index.html index 83773f404022ac289937e44ef9914f1231990bf1..7ec3f73e6450583e03b735d28355ca9c2c038e53 100644 --- a/templates/index.html +++ b/templates/index.html @@ -12,252 +12,12 @@ -____- \\ / \\/ \\/ \\ \\ / \\/ </pre> </div> <div class="f-svg"> - <svg xmlns="http://www.w3.org/2000/svg" width="440" height="112" class="svgbob"> - <style>.svgbob line, .svgbob path, .svgbob circle, .svgbob rect, .svgbob polygon { - stroke: blue; - stroke-width: 2.5; - stroke-opacity: 1; - fill-opacity: 1; - stroke-linecap: round; - stroke-linejoin: miter; - } - - .svgbob text { - white-space: pre; - fill: black; - font-family: Iosevka Fixed, monospace; - font-size: 14px; - } - - .svgbob rect.backdrop { - stroke: none; - fill: none; - } - - .svgbob .broken { - stroke-dasharray: 8; - } - - .svgbob .filled { - fill: black; - } - - .svgbob .bg_filled { - fill: white; - stroke-width: 1; - } - - .svgbob .nofill { - fill: white; - } - - .svgbob .end_marked_arrow { - marker-end: url(#arrow); - } - - .svgbob .start_marked_arrow { - marker-start: url(#arrow); - } - - .svgbob .end_marked_diamond { - marker-end: url(#diamond); - } - - .svgbob .start_marked_diamond { - marker-start: url(#diamond); - } - - .svgbob .end_marked_circle { - marker-end: url(#circle); - } - - .svgbob .start_marked_circle { - marker-start: url(#circle); - } - - .svgbob .end_marked_open_circle { - marker-end: url(#open_circle); - } - - .svgbob .start_marked_open_circle { - marker-start: url(#open_circle); - } - - .svgbob .end_marked_big_open_circle { - marker-end: url(#big_open_circle); - } - - .svgbob .start_marked_big_open_circle { - marker-start: url(#big_open_circle); - } - - </style> - <defs> - <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,0 0,4 4,2 0,0"></polygon> - </marker> - <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon> - </marker> - <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="filled"></circle> - </marker> - <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="2" class="bg_filled"></circle> - </marker> - <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> - <circle cx="4" cy="4" r="3" class="bg_filled"></circle> - </marker> - </defs> - <rect class="backdrop" x="0" y="0" width="440" height="112"></rect> - <text x="258" y="12">'</text> - <text x="426" y="12">.</text> - <text x="178" y="44">.</text> - <text x="130" y="60">.</text> - <line x1="136" y1="64" x2="168" y2="64" class="solid"></line> - <text x="170" y="60">.'</text> - <text x="266" y="60">.</text> - <text x="314" y="60">.</text> - <text x="50" y="76">`</text> - <text x="90" y="76">:'</text> - <text x="210" y="76">.</text> - <line x1="216" y1="80" x2="224" y2="80" class="solid"></line> - <text x="98" y="92">.</text> - <text x="170" y="92">'</text> - <text x="218" y="92">`</text> - <line x1="224" y1="88" x2="232" y2="88" class="solid"></line> - <text x="250" y="92">.</text> - <text x="330" y="92">.</text> - <g> - <path d="M 24,8 A 8,8 0,0,1 30,12" class="nofill"></path> - <line x1="30" y1="12" x2="32" y2="16" class="solid"></line> - <path d="M 32,8 A 8,8 0,0,0 26,12" class="nofill"></path> - <line x1="26" y1="12" x2="24" y2="16" class="solid"></line> - <line x1="32" y1="8" x2="40" y2="8" class="solid"></line> - <path d="M 40,8 A 8,8 0,0,1 46,12" class="nofill"></path> - <line x1="46" y1="12" x2="48" y2="16" class="solid"></line> - <path d="M 24,16 A 16,16 0,0,0 24,32" class="nofill"></path> - <line x1="24" y1="32" x2="32" y2="32" class="solid"></line> - <path d="M 32,16 A 16,16 0,0,1 32,32" class="nofill"></path> - <path d="M 48,16 A 16,16 0,0,1 48,32" class="nofill"></path> - <line x1="48" y1="32" x2="16" y2="96" class="solid"></line> - <path d="M 16,72 A 8,8 0,0,0 10,76" class="nofill"></path> - <line x1="10" y1="76" x2="8" y2="80" class="solid"></line> - <line x1="16" y1="72" x2="28" y2="72" class="solid"></line> - <path d="M 8,80 A 16,16 0,0,0 8,96" class="nofill"></path> - <line x1="8" y1="96" x2="16" y2="96" class="solid"></line> - </g> - <g> - <line x1="152" y1="0" x2="112" y2="80" class="solid"></line> - <line x1="152" y1="0" x2="156" y2="8" class="solid"></line> - <line x1="156" y1="8" x2="156" y2="84" class="solid"></line> - <path d="M 156,84 A 4,4 0,0,0 160,88" class="nofill"></path> - <line x1="160" y1="88" x2="168" y2="88" class="solid"></line> - <path d="M 88,72 A 8,8 0,0,0 82,76" class="nofill"></path> - <line x1="82" y1="76" x2="80" y2="80" class="solid"></line> - <path d="M 80,80 A 16,16 0,0,0 80,96" class="nofill"></path> - <line x1="80" y1="96" x2="96" y2="96" class="solid"></line> - <path d="M 112,80 A 32,32 0,0,1 96,96" class="nofill"></path> - </g> - <g> - <path d="M 184,8 A 8,8 0,0,1 190,12" class="nofill"></path> - <line x1="190" y1="12" x2="192" y2="16" class="solid"></line> - <path d="M 192,8 A 8,8 0,0,0 186,12" class="nofill"></path> - <line x1="186" y1="12" x2="184" y2="16" class="solid"></line> - <line x1="192" y1="8" x2="256" y2="8" class="solid"></line> - <path d="M 184,16 A 16,16 0,0,0 184,32" class="nofill"></path> - <line x1="184" y1="32" x2="192" y2="32" class="solid"></line> - <path d="M 192,16 A 16,16 0,0,1 192,32" class="nofill"></path> - </g> - <g> - <path d="M 256,0 A 32,32 0,0,1 272,16" class="nofill"></path> - <line x1="272" y1="16" x2="280" y2="32" class="solid"></line> - <path d="M 280,32 A 16,16 0,0,1 280,48" class="nofill"></path> - <line x1="280" y1="48" x2="264" y2="80" class="solid"></line> - <line x1="272" y1="64" x2="312" y2="64" class="solid"></line> - <line x1="320" y1="0" x2="304" y2="32" class="solid"></line> - <path d="M 304,32 A 16,16 0,0,0 304,48" class="nofill"></path> - <line x1="304" y1="48" x2="320" y2="80" class="solid"></line> - <path d="M 320,80 A 32,32 0,0,0 336,96" class="nofill"></path> - <path d="M 248,72 A 8,8 0,0,0 242,76" class="nofill"></path> - <line x1="242" y1="76" x2="240" y2="80" class="solid"></line> - <path d="M 240,80 A 16,16 0,0,0 240,96" class="nofill"></path> - <line x1="240" y1="96" x2="248" y2="96" class="solid"></line> - <path d="M 264,80 A 32,32 0,0,1 248,96" class="nofill"></path> - </g> - <g> - <path d="M 412,8 A 8,8 0,0,0 404,16" class="nofill"></path> - <line x1="412" y1="8" x2="424" y2="8" class="solid"></line> - </g> - <g> - <line x1="56" y1="24" x2="64" y2="24" class="solid"></line> - <path d="M 64,24 A 8,8 0,0,1 70,28" class="nofill"></path> - <line x1="70" y1="28" x2="80" y2="48" class="solid"></line> - <path d="M 80,48 A 16,16 0,0,1 80,64" class="nofill"></path> - <line x1="80" y1="64" x2="78" y2="68" class="solid"></line> - <line x1="56" y1="72" x2="72" y2="72" class="solid"></line> - <path d="M 78,68 A 8,8 0,0,1 72,72" class="nofill"></path> - </g> - <g> - <line x1="112" y1="32" x2="120" y2="32" class="solid"></line> - <path d="M 112,32 A 16,16 0,0,0 112,48" class="nofill"></path> - <line x1="112" y1="48" x2="114" y2="52" class="solid"></line> - <path d="M 114,52 A 8,8 0,0,0 120,56" class="nofill"></path> - </g> - <g> - <line x1="232" y1="16" x2="192" y2="96" class="solid"></line> - <path d="M 192,72 A 8,8 0,0,0 186,76" class="nofill"></path> - <line x1="186" y1="76" x2="184" y2="80" class="solid"></line> - <line x1="192" y1="72" x2="204" y2="72" class="solid"></line> - <path d="M 184,80 A 16,16 0,0,0 184,96" class="nofill"></path> - <line x1="184" y1="96" x2="192" y2="96" class="solid"></line> - </g> - <g> - <line x1="256" y1="32" x2="264" y2="32" class="solid"></line> - <path d="M 256,32 A 16,16 0,0,0 256,48" class="nofill"></path> - <line x1="256" y1="48" x2="258" y2="52" class="solid"></line> - <path d="M 258,52 A 8,8 0,0,0 264,56" class="nofill"></path> - </g> - <g> - <path d="M 328,16 A 16,16 0,0,0 328,32" class="nofill"></path> - <path d="M 328,32 A 16,16 0,0,1 328,48" class="nofill"></path> - <line x1="328" y1="48" x2="326" y2="52" class="solid"></line> - <path d="M 326,52 A 8,8 0,0,1 320,56" class="nofill"></path> - </g> - <g> - <path d="M 368,24 A 8,8 0,0,0 362,28" class="nofill"></path> - <line x1="362" y1="28" x2="360" y2="32" class="solid"></line> - <line x1="368" y1="24" x2="384" y2="24" class="solid"></line> - <path d="M 384,24 A 8,8 0,0,1 390,28" class="nofill"></path> - <line x1="390" y1="28" x2="392" y2="32" class="solid"></line> - <path d="M 360,32 A 16,16 0,0,0 360,48" class="nofill"></path> - <line x1="360" y1="48" x2="362" y2="52" class="solid"></line> - <path d="M 362,52 A 8,8 0,0,0 368,56" class="nofill"></path> - <line x1="368" y1="56" x2="376" y2="56" class="solid"></line> - <path d="M 376,56 A 8,8 0,0,1 382,60" class="nofill"></path> - <line x1="382" y1="60" x2="384" y2="64" class="solid"></line> - <path d="M 384,64 A 16,16 0,0,1 384,80" class="nofill"></path> - <line x1="384" y1="80" x2="382" y2="84" class="solid"></line> - <path d="M 392,24 A 8,8 0,0,0 386,28" class="nofill"></path> - <line x1="386" y1="28" x2="384" y2="32" class="solid"></line> - <line x1="392" y1="24" x2="404" y2="24" class="solid"></line> - <path d="M 412,16 A 8,8 0,0,1 404,24" class="nofill"></path> - <path d="M 384,32 A 16,16 0,0,0 384,48" class="nofill"></path> - <line x1="384" y1="48" x2="392" y2="48" class="solid"></line> - <path d="M 392,32 A 16,16 0,0,1 392,48" class="nofill"></path> - <line x1="344" y1="80" x2="352" y2="80" class="solid"></line> - <path d="M 344,80 A 16,16 0,0,0 344,96" class="nofill"></path> - <line x1="344" y1="96" x2="352" y2="96" class="solid"></line> - <line x1="360" y1="88" x2="352" y2="96" class="solid"></line> - <line x1="360" y1="88" x2="376" y2="88" class="solid"></line> - <path d="M 382,84 A 8,8 0,0,1 376,88" class="nofill"></path> - </g> - </svg> - </div> + {% include 'logo.svg' %} </div> - <div class="box"> - <ul class="special"> + <ul class="special"> + <li><a href="https://etherpad.org/" target="_blank">Etherpad</a></li> + <li>2</li> <li><a href="http://www.figlet.org/" target="_blank">FIGlet</a></li> <li>2</li> <li><a href="https://ivanceras.github.io/svgbob-editor/" target="_blank">Svgbob.rs</a></li> @@ -265,8 +25,13 @@ <li><a href="https://en.wikipedia.org/wiki/HP-GL" target="_blank">HPGL</a></li> </ul> </div> - <div class="box"> + <div class="box two-columns"> + <div> <h2>Cobbled paths</h2> + <p> + It is a web interface that brings multiple tools together, to allow experimental and direct collaboration on + pen-plotted drawings by making Ascii art. + </p> <p> It makes a way from the blocky discontinuity of Ascii drawings, to the smoothness of bezier curves, @@ -279,9 +44,8 @@ Like cobbled paths, it is a reminder of the permeability between the discrete and the continuous, and how regular stones can form tortuous paths. </p> - </div> - - <div class="box"> + </div> + <div> <h2>Handfull links</h2> <ul class="classic"> <li><a href="http://www.jave.de/figlet/figfont.html">FIGfont Specification</a>, everything about FIGlet font file format</li> @@ -291,6 +55,7 @@ <li><a href="http://www.jave.de/">JavE</a>, an ascii drawing editor</li> <li><a href="https://adelfaure.net/">adel faure</a>, an ascii artist</li> </ul> + </div> </div> {% endblock %} diff --git a/templates/logo.svg b/templates/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..ef2ec1857a3cff9310c63597cdc63049bacd1a48 --- /dev/null +++ b/templates/logo.svg @@ -0,0 +1,242 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="440" height="112" class="svgbob"> + <style>.svgbob line, .svgbob path, .svgbob circle, .svgbob rect, .svgbob polygon { + stroke: black; + vector-effect: non-scaling-stroke; + stroke-width: 1.5px; + stroke-opacity: 1; + fill-opacity: 1; + stroke-linecap: round; + stroke-linejoin: miter; + } + + .svgbob text { + white-space: pre; + fill: black; + font-family: Iosevka Fixed, monospace; + font-size: 14px; + } + + .svgbob rect.backdrop { + stroke: none; + fill: none; + } + + .svgbob .broken { + stroke-dasharray: 8; + } + + .svgbob .filled { + fill: black; + } + + .svgbob .bg_filled { + fill: white; + stroke-width: 1; + } + + .svgbob .nofill { + fill: white; + } + + .svgbob .end_marked_arrow { + marker-end: url(#arrow); + } + + .svgbob .start_marked_arrow { + marker-start: url(#arrow); + } + + .svgbob .end_marked_diamond { + marker-end: url(#diamond); + } + + .svgbob .start_marked_diamond { + marker-start: url(#diamond); + } + + .svgbob .end_marked_circle { + marker-end: url(#circle); + } + + .svgbob .start_marked_circle { + marker-start: url(#circle); + } + + .svgbob .end_marked_open_circle { + marker-end: url(#open_circle); + } + + .svgbob .start_marked_open_circle { + marker-start: url(#open_circle); + } + + .svgbob .end_marked_big_open_circle { + marker-end: url(#big_open_circle); + } + + .svgbob .start_marked_big_open_circle { + marker-start: url(#big_open_circle); + } + + </style> + <defs> + <marker id="arrow" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> + <polygon points="0,0 0,4 4,2 0,0"></polygon> + </marker> + <marker id="diamond" viewBox="-2 -2 8 8" refX="4" refY="2" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> + <polygon points="0,2 2,0 4,2 2,4 0,2"></polygon> + </marker> + <marker id="circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> + <circle cx="4" cy="4" r="2" class="filled"></circle> + </marker> + <marker id="open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> + <circle cx="4" cy="4" r="2" class="bg_filled"></circle> + </marker> + <marker id="big_open_circle" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto-start-reverse"> + <circle cx="4" cy="4" r="3" class="bg_filled"></circle> + </marker> + </defs> + <rect class="backdrop" x="0" y="0" width="440" height="112"></rect> + <text x="258" y="12">'</text> + <text x="426" y="12">.</text> + <text x="178" y="44">.</text> + <text x="130" y="60">.</text> + <line x1="136" y1="64" x2="168" y2="64" class="solid"></line> + <text x="170" y="60">.'</text> + <text x="266" y="60">.</text> + <text x="314" y="60">.</text> + <text x="50" y="76">`</text> + <text x="90" y="76">:'</text> + <text x="210" y="76">.</text> + <line x1="216" y1="80" x2="224" y2="80" class="solid"></line> + <text x="98" y="92">.</text> + <text x="170" y="92">'</text> + <text x="218" y="92">`</text> + <line x1="224" y1="88" x2="232" y2="88" class="solid"></line> + <text x="250" y="92">.</text> + <text x="330" y="92">.</text> + <g> + <path d="M 24,8 A 8,8 0,0,1 30,12" class="nofill"></path> + <line x1="30" y1="12" x2="32" y2="16" class="solid"></line> + <path d="M 32,8 A 8,8 0,0,0 26,12" class="nofill"></path> + <line x1="26" y1="12" x2="24" y2="16" class="solid"></line> + <line x1="32" y1="8" x2="40" y2="8" class="solid"></line> + <path d="M 40,8 A 8,8 0,0,1 46,12" class="nofill"></path> + <line x1="46" y1="12" x2="48" y2="16" class="solid"></line> + <path d="M 24,16 A 16,16 0,0,0 24,32" class="nofill"></path> + <line x1="24" y1="32" x2="32" y2="32" class="solid"></line> + <path d="M 32,16 A 16,16 0,0,1 32,32" class="nofill"></path> + <path d="M 48,16 A 16,16 0,0,1 48,32" class="nofill"></path> + <line x1="48" y1="32" x2="16" y2="96" class="solid"></line> + <path d="M 16,72 A 8,8 0,0,0 10,76" class="nofill"></path> + <line x1="10" y1="76" x2="8" y2="80" class="solid"></line> + <line x1="16" y1="72" x2="28" y2="72" class="solid"></line> + <path d="M 8,80 A 16,16 0,0,0 8,96" class="nofill"></path> + <line x1="8" y1="96" x2="16" y2="96" class="solid"></line> + </g> + <g> + <line x1="152" y1="0" x2="112" y2="80" class="solid"></line> + <line x1="152" y1="0" x2="156" y2="8" class="solid"></line> + <line x1="156" y1="8" x2="156" y2="84" class="solid"></line> + <path d="M 156,84 A 4,4 0,0,0 160,88" class="nofill"></path> + <line x1="160" y1="88" x2="168" y2="88" class="solid"></line> + <path d="M 88,72 A 8,8 0,0,0 82,76" class="nofill"></path> + <line x1="82" y1="76" x2="80" y2="80" class="solid"></line> + <path d="M 80,80 A 16,16 0,0,0 80,96" class="nofill"></path> + <line x1="80" y1="96" x2="96" y2="96" class="solid"></line> + <path d="M 112,80 A 32,32 0,0,1 96,96" class="nofill"></path> + </g> + <g> + <path d="M 184,8 A 8,8 0,0,1 190,12" class="nofill"></path> + <line x1="190" y1="12" x2="192" y2="16" class="solid"></line> + <path d="M 192,8 A 8,8 0,0,0 186,12" class="nofill"></path> + <line x1="186" y1="12" x2="184" y2="16" class="solid"></line> + <line x1="192" y1="8" x2="256" y2="8" class="solid"></line> + <path d="M 184,16 A 16,16 0,0,0 184,32" class="nofill"></path> + <line x1="184" y1="32" x2="192" y2="32" class="solid"></line> + <path d="M 192,16 A 16,16 0,0,1 192,32" class="nofill"></path> + </g> + <g> + <path d="M 256,0 A 32,32 0,0,1 272,16" class="nofill"></path> + <line x1="272" y1="16" x2="280" y2="32" class="solid"></line> + <path d="M 280,32 A 16,16 0,0,1 280,48" class="nofill"></path> + <line x1="280" y1="48" x2="264" y2="80" class="solid"></line> + <line x1="272" y1="64" x2="312" y2="64" class="solid"></line> + <line x1="320" y1="0" x2="304" y2="32" class="solid"></line> + <path d="M 304,32 A 16,16 0,0,0 304,48" class="nofill"></path> + <line x1="304" y1="48" x2="320" y2="80" class="solid"></line> + <path d="M 320,80 A 32,32 0,0,0 336,96" class="nofill"></path> + <path d="M 248,72 A 8,8 0,0,0 242,76" class="nofill"></path> + <line x1="242" y1="76" x2="240" y2="80" class="solid"></line> + <path d="M 240,80 A 16,16 0,0,0 240,96" class="nofill"></path> + <line x1="240" y1="96" x2="248" y2="96" class="solid"></line> + <path d="M 264,80 A 32,32 0,0,1 248,96" class="nofill"></path> + </g> + <g> + <path d="M 412,8 A 8,8 0,0,0 404,16" class="nofill"></path> + <line x1="412" y1="8" x2="424" y2="8" class="solid"></line> + </g> + <g> + <line x1="56" y1="24" x2="64" y2="24" class="solid"></line> + <path d="M 64,24 A 8,8 0,0,1 70,28" class="nofill"></path> + <line x1="70" y1="28" x2="80" y2="48" class="solid"></line> + <path d="M 80,48 A 16,16 0,0,1 80,64" class="nofill"></path> + <line x1="80" y1="64" x2="78" y2="68" class="solid"></line> + <line x1="56" y1="72" x2="72" y2="72" class="solid"></line> + <path d="M 78,68 A 8,8 0,0,1 72,72" class="nofill"></path> + </g> + <g> + <line x1="112" y1="32" x2="120" y2="32" class="solid"></line> + <path d="M 112,32 A 16,16 0,0,0 112,48" class="nofill"></path> + <line x1="112" y1="48" x2="114" y2="52" class="solid"></line> + <path d="M 114,52 A 8,8 0,0,0 120,56" class="nofill"></path> + </g> + <g> + <line x1="232" y1="16" x2="192" y2="96" class="solid"></line> + <path d="M 192,72 A 8,8 0,0,0 186,76" class="nofill"></path> + <line x1="186" y1="76" x2="184" y2="80" class="solid"></line> + <line x1="192" y1="72" x2="204" y2="72" class="solid"></line> + <path d="M 184,80 A 16,16 0,0,0 184,96" class="nofill"></path> + <line x1="184" y1="96" x2="192" y2="96" class="solid"></line> + </g> + <g> + <line x1="256" y1="32" x2="264" y2="32" class="solid"></line> + <path d="M 256,32 A 16,16 0,0,0 256,48" class="nofill"></path> + <line x1="256" y1="48" x2="258" y2="52" class="solid"></line> + <path d="M 258,52 A 8,8 0,0,0 264,56" class="nofill"></path> + </g> + <g> + <path d="M 328,16 A 16,16 0,0,0 328,32" class="nofill"></path> + <path d="M 328,32 A 16,16 0,0,1 328,48" class="nofill"></path> + <line x1="328" y1="48" x2="326" y2="52" class="solid"></line> + <path d="M 326,52 A 8,8 0,0,1 320,56" class="nofill"></path> + </g> + <g> + <path d="M 368,24 A 8,8 0,0,0 362,28" class="nofill"></path> + <line x1="362" y1="28" x2="360" y2="32" class="solid"></line> + <line x1="368" y1="24" x2="384" y2="24" class="solid"></line> + <path d="M 384,24 A 8,8 0,0,1 390,28" class="nofill"></path> + <line x1="390" y1="28" x2="392" y2="32" class="solid"></line> + <path d="M 360,32 A 16,16 0,0,0 360,48" class="nofill"></path> + <line x1="360" y1="48" x2="362" y2="52" class="solid"></line> + <path d="M 362,52 A 8,8 0,0,0 368,56" class="nofill"></path> + <line x1="368" y1="56" x2="376" y2="56" class="solid"></line> + <path d="M 376,56 A 8,8 0,0,1 382,60" class="nofill"></path> + <line x1="382" y1="60" x2="384" y2="64" class="solid"></line> + <path d="M 384,64 A 16,16 0,0,1 384,80" class="nofill"></path> + <line x1="384" y1="80" x2="382" y2="84" class="solid"></line> + <path d="M 392,24 A 8,8 0,0,0 386,28" class="nofill"></path> + <line x1="386" y1="28" x2="384" y2="32" class="solid"></line> + <line x1="392" y1="24" x2="404" y2="24" class="solid"></line> + <path d="M 412,16 A 8,8 0,0,1 404,24" class="nofill"></path> + <path d="M 384,32 A 16,16 0,0,0 384,48" class="nofill"></path> + <line x1="384" y1="48" x2="392" y2="48" class="solid"></line> + <path d="M 392,32 A 16,16 0,0,1 392,48" class="nofill"></path> + <line x1="344" y1="80" x2="352" y2="80" class="solid"></line> + <path d="M 344,80 A 16,16 0,0,0 344,96" class="nofill"></path> + <line x1="344" y1="96" x2="352" y2="96" class="solid"></line> + <line x1="360" y1="88" x2="352" y2="96" class="solid"></line> + <line x1="360" y1="88" x2="376" y2="88" class="solid"></line> + <path d="M 382,84 A 8,8 0,0,1 376,88" class="nofill"></path> + </g> + </svg> \ No newline at end of file diff --git a/templates/writing.html b/templates/writing.html index bd602ed704b49c1b2cf17ba96d86897a500f411e..46aa591f5a6305e247ee13f8368d5aa0a055802a 100644 --- a/templates/writing.html +++ b/templates/writing.html @@ -41,6 +41,9 @@ font-size: 1rem; } + .f-svg svg{ + overflow: visible; + } </style> </head>