From d14b59dcbec01f1a65714c36448e82ea8af63dd6 Mon Sep 17 00:00:00 2001 From: Ada Isopods Date: Fri, 23 Oct 2026 12:10:50 -0600 Subject: rearranging some stuff in preparation for a new deployment workflow --- .gitignore | 13 +- Parsedown.php | 1994 ++++++++++++++++++++ blog/posts/building_a_cooler_body_2/index.md | 3 - blog/posts/building_a_cooler_body_2/index.php | 1 - blog/posts/guide_sorcery_git/index.md | 183 -- blog/posts/guide_sorcery_git/index.php | 1 - blog/posts/invaluable_contributions/bg.png | Bin 0 -> 367568 bytes blog/posts/invaluable_contributions/index.md | 37 + blog/posts/invaluable_contributions/index.php | 1 + header.php | 2 +- .../AtkinsonHyperlegible-Bold.ttf | Bin 0 -> 54444 bytes .../AtkinsonHyperlegible-BoldItalic.ttf | Bin 0 -> 54608 bytes .../AtkinsonHyperlegible-Italic.ttf | Bin 0 -> 54200 bytes .../AtkinsonHyperlegible-Regular.ttf | Bin 0 -> 53504 bytes .../AtkinsonHyperlegibleMono-Bold.ttf | Bin 0 -> 34268 bytes .../AtkinsonHyperlegibleMono-BoldItalic.ttf | Bin 0 -> 35684 bytes .../AtkinsonHyperlegibleMono-Italic.ttf | Bin 0 -> 35668 bytes .../AtkinsonHyperlegibleMono-Regular.ttf | Bin 0 -> 34320 bytes stuff/fonts/Atkinson_Hyperlegible/OFL.txt | 93 + stuff/fonts/B612/B612-Bold.ttf | Bin 0 -> 90928 bytes stuff/fonts/B612/B612-BoldItalic.ttf | Bin 0 -> 93968 bytes stuff/fonts/B612/B612-Italic.ttf | Bin 0 -> 94960 bytes stuff/fonts/B612/B612-Regular.ttf | Bin 0 -> 142720 bytes stuff/fonts/B612/OFL.txt | 93 + stuff/fonts/B612_Mono/B612Mono-Bold.ttf | Bin 0 -> 135904 bytes stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf | Bin 0 -> 121732 bytes stuff/fonts/B612_Mono/B612Mono-Italic.ttf | Bin 0 -> 118888 bytes stuff/fonts/B612_Mono/B612Mono-Regular.ttf | Bin 0 -> 136712 bytes stuff/fonts/B612_Mono/OFL.txt | 93 + stuff/fonts/DS-DIGI.ttf | Bin 0 -> 24448 bytes stuff/fonts/Google_Sans/GoogleSans-Bold.ttf | Bin 0 -> 2001624 bytes stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf | Bin 0 -> 2062592 bytes stuff/fonts/Google_Sans/GoogleSans-Italic.ttf | Bin 0 -> 2060680 bytes stuff/fonts/Google_Sans/GoogleSans-Regular.ttf | Bin 0 -> 1999328 bytes stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf | Bin 0 -> 99680 bytes .../Google_Sans/GoogleSansCode-BoldItalic.ttf | Bin 0 -> 100560 bytes stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf | Bin 0 -> 100016 bytes stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf | Bin 0 -> 99180 bytes stuff/fonts/Google_Sans/OFL.txt | 91 + stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf | Bin 0 -> 405596 bytes stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf | Bin 0 -> 405892 bytes stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf | Bin 0 -> 506864 bytes stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf | Bin 0 -> 534540 bytes stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf | Bin 0 -> 534156 bytes stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf | Bin 0 -> 504932 bytes stuff/fonts/Noto_Serif/OFL.txt | 93 + stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf | Bin 0 -> 184004 bytes .../fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf | Bin 0 -> 234364 bytes stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf | Bin 0 -> 189768 bytes stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf | Bin 0 -> 175808 bytes .../OpenDyslexic/OpenDyslexicMono-Regular.otf | Bin 0 -> 51548 bytes stuff/fonts/Ubuntu/Ubuntu-Bold.ttf | Bin 0 -> 270164 bytes stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf | Bin 0 -> 283444 bytes stuff/fonts/Ubuntu/Ubuntu-Italic.ttf | Bin 0 -> 326932 bytes stuff/fonts/Ubuntu/Ubuntu-Regular.ttf | Bin 0 -> 299684 bytes stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf | Bin 0 -> 174860 bytes stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf | Bin 0 -> 199044 bytes stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf | Bin 0 -> 193936 bytes stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf | Bin 0 -> 189892 bytes stuff/fonts/atkinsonhyperlegible.css | 54 + stuff/fonts/atkinsonhyperlegiblemono.css | 29 + stuff/fonts/b612.css | 54 + stuff/fonts/b612mono.css | 29 + stuff/fonts/browserdefault.css | 9 + stuff/fonts/cafe.ttf | Bin 0 -> 32020 bytes stuff/fonts/firsttimewriting.ttf | Bin 0 -> 641428 bytes stuff/fonts/googlesans.css | 54 + stuff/fonts/googlesanscode.css | 29 + stuff/fonts/notoserif.css | 41 + stuff/fonts/opendyslexic.css | 35 + stuff/fonts/silkscreen.css | 16 + stuff/fonts/slkscr.ttf | Bin 0 -> 7636 bytes stuff/fonts/slkscrb.ttf | Bin 0 -> 6604 bytes stuff/fonts/ubuntu.css | 54 + style.css | 9 +- uses/cumulonimbus/index.php | 13 +- uses/servy586/index.php | 17 +- 77 files changed, 2930 insertions(+), 211 deletions(-) create mode 100644 Parsedown.php delete mode 100644 blog/posts/building_a_cooler_body_2/index.md delete mode 100644 blog/posts/building_a_cooler_body_2/index.php delete mode 100644 blog/posts/guide_sorcery_git/index.md delete mode 100644 blog/posts/guide_sorcery_git/index.php create mode 100644 blog/posts/invaluable_contributions/bg.png create mode 100644 blog/posts/invaluable_contributions/index.md create mode 100644 blog/posts/invaluable_contributions/index.php create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf create mode 100644 stuff/fonts/Atkinson_Hyperlegible/OFL.txt create mode 100644 stuff/fonts/B612/B612-Bold.ttf create mode 100644 stuff/fonts/B612/B612-BoldItalic.ttf create mode 100644 stuff/fonts/B612/B612-Italic.ttf create mode 100644 stuff/fonts/B612/B612-Regular.ttf create mode 100644 stuff/fonts/B612/OFL.txt create mode 100644 stuff/fonts/B612_Mono/B612Mono-Bold.ttf create mode 100644 stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf create mode 100644 stuff/fonts/B612_Mono/B612Mono-Italic.ttf create mode 100644 stuff/fonts/B612_Mono/B612Mono-Regular.ttf create mode 100644 stuff/fonts/B612_Mono/OFL.txt create mode 100644 stuff/fonts/DS-DIGI.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSans-Bold.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSans-Italic.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSans-Regular.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf create mode 100644 stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf create mode 100644 stuff/fonts/Google_Sans/OFL.txt create mode 100644 stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf create mode 100644 stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf create mode 100644 stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf create mode 100644 stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf create mode 100644 stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf create mode 100644 stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf create mode 100644 stuff/fonts/Noto_Serif/OFL.txt create mode 100644 stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf create mode 100644 stuff/fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf create mode 100644 stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf create mode 100644 stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf create mode 100644 stuff/fonts/OpenDyslexic/OpenDyslexicMono-Regular.otf create mode 100644 stuff/fonts/Ubuntu/Ubuntu-Bold.ttf create mode 100644 stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf create mode 100644 stuff/fonts/Ubuntu/Ubuntu-Italic.ttf create mode 100644 stuff/fonts/Ubuntu/Ubuntu-Regular.ttf create mode 100644 stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf create mode 100644 stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf create mode 100644 stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf create mode 100644 stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf create mode 100644 stuff/fonts/atkinsonhyperlegible.css create mode 100644 stuff/fonts/atkinsonhyperlegiblemono.css create mode 100644 stuff/fonts/b612.css create mode 100644 stuff/fonts/b612mono.css create mode 100644 stuff/fonts/browserdefault.css create mode 100644 stuff/fonts/cafe.ttf create mode 100644 stuff/fonts/firsttimewriting.ttf create mode 100644 stuff/fonts/googlesans.css create mode 100644 stuff/fonts/googlesanscode.css create mode 100644 stuff/fonts/notoserif.css create mode 100644 stuff/fonts/opendyslexic.css create mode 100644 stuff/fonts/silkscreen.css create mode 100644 stuff/fonts/slkscr.ttf create mode 100644 stuff/fonts/slkscrb.ttf create mode 100644 stuff/fonts/ubuntu.css diff --git a/.gitignore b/.gitignore index 03ddfe5..896df6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,2 @@ -pronouns.txt -blog/posts/invaluable_contributions -Parsedown.php -/stuff/fonts/* -guestbook/bannedwords.json -ditherizer.sh -posts.json -blog/posts/noterook/ -blog/posts/fedi_explainer/ -blog/posts/syscovery/ -blog/posts/building_a_partscaster/ +blog/posts/__WIP__/ +blog/__WIP__/ diff --git a/Parsedown.php b/Parsedown.php new file mode 100644 index 0000000..ae0cbde --- /dev/null +++ b/Parsedown.php @@ -0,0 +1,1994 @@ +textElements($text); + + # convert to markup + $markup = $this->elements($Elements); + + # trim line breaks + $markup = trim($markup, "\n"); + + return $markup; + } + + protected function textElements($text) + { + # make sure no definitions are set + $this->DefinitionData = array(); + + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + # remove surrounding line breaks + $text = trim($text, "\n"); + + # split text into lines + $lines = explode("\n", $text); + + # iterate through lines to identify blocks + return $this->linesElements($lines); + } + + # + # Setters + # + + function setBreaksEnabled($breaksEnabled) + { + $this->breaksEnabled = $breaksEnabled; + + return $this; + } + + protected $breaksEnabled; + + function setMarkupEscaped($markupEscaped) + { + $this->markupEscaped = $markupEscaped; + + return $this; + } + + protected $markupEscaped; + + function setUrlsLinked($urlsLinked) + { + $this->urlsLinked = $urlsLinked; + + return $this; + } + + protected $urlsLinked = true; + + function setSafeMode($safeMode) + { + $this->safeMode = (bool) $safeMode; + + return $this; + } + + protected $safeMode; + + function setStrictMode($strictMode) + { + $this->strictMode = (bool) $strictMode; + + return $this; + } + + protected $strictMode; + + protected $safeLinksWhitelist = array( + 'http://', + 'https://', + 'ftp://', + 'ftps://', + 'mailto:', + 'tel:', + 'data:image/png;base64,', + 'data:image/gif;base64,', + 'data:image/jpeg;base64,', + 'irc:', + 'ircs:', + 'git:', + 'ssh:', + 'news:', + 'steam:', + ); + + # + # Lines + # + + protected $BlockTypes = array( + '#' => array('Header'), + '*' => array('Rule', 'List'), + '+' => array('List'), + '-' => array('SetextHeader', 'Table', 'Rule', 'List'), + '0' => array('List'), + '1' => array('List'), + '2' => array('List'), + '3' => array('List'), + '4' => array('List'), + '5' => array('List'), + '6' => array('List'), + '7' => array('List'), + '8' => array('List'), + '9' => array('List'), + ':' => array('Table'), + '<' => array('Comment', 'Markup'), + '=' => array('SetextHeader'), + '>' => array('Quote'), + '[' => array('Reference'), + '_' => array('Rule'), + '`' => array('FencedCode'), + '|' => array('Table'), + '~' => array('FencedCode'), + ); + + # ~ + + protected $unmarkedBlockTypes = array( + 'Code', + ); + + # + # Blocks + # + + protected function lines(array $lines) + { + return $this->elements($this->linesElements($lines)); + } + + protected function linesElements(array $lines) + { + $Elements = array(); + $CurrentBlock = null; + + foreach ($lines as $line) + { + if (chop($line) === '') + { + if (isset($CurrentBlock)) + { + $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted']) + ? $CurrentBlock['interrupted'] + 1 : 1 + ); + } + + continue; + } + + while (($beforeTab = strstr($line, "\t", true)) !== false) + { + $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4; + + $line = $beforeTab + . str_repeat(' ', $shortage) + . substr($line, strlen($beforeTab) + 1) + ; + } + + $indent = strspn($line, ' '); + + $text = $indent > 0 ? substr($line, $indent) : $line; + + # ~ + + $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); + + # ~ + + if (isset($CurrentBlock['continuable'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Continue'; + $Block = $this->$methodName($Line, $CurrentBlock); + + if (isset($Block)) + { + $CurrentBlock = $Block; + + continue; + } + else + { + if ($this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + } + } + + # ~ + + $marker = $text[0]; + + # ~ + + $blockTypes = $this->unmarkedBlockTypes; + + if (isset($this->BlockTypes[$marker])) + { + foreach ($this->BlockTypes[$marker] as $blockType) + { + $blockTypes []= $blockType; + } + } + + # + # ~ + + foreach ($blockTypes as $blockType) + { + $Block = $this->{"block$blockType"}($Line, $CurrentBlock); + + if (isset($Block)) + { + $Block['type'] = $blockType; + + if ( ! isset($Block['identified'])) + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $Block['identified'] = true; + } + + if ($this->isBlockContinuable($blockType)) + { + $Block['continuable'] = true; + } + + $CurrentBlock = $Block; + + continue 2; + } + } + + # ~ + + if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph') + { + $Block = $this->paragraphContinue($Line, $CurrentBlock); + } + + if (isset($Block)) + { + $CurrentBlock = $Block; + } + else + { + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + $CurrentBlock = $this->paragraph($Line); + + $CurrentBlock['identified'] = true; + } + } + + # ~ + + if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) + { + $methodName = 'block' . $CurrentBlock['type'] . 'Complete'; + $CurrentBlock = $this->$methodName($CurrentBlock); + } + + # ~ + + if (isset($CurrentBlock)) + { + $Elements[] = $this->extractElement($CurrentBlock); + } + + # ~ + + return $Elements; + } + + protected function extractElement(array $Component) + { + if ( ! isset($Component['element'])) + { + if (isset($Component['markup'])) + { + $Component['element'] = array('rawHtml' => $Component['markup']); + } + elseif (isset($Component['hidden'])) + { + $Component['element'] = array(); + } + } + + return $Component['element']; + } + + protected function isBlockContinuable($Type) + { + return method_exists($this, 'block' . $Type . 'Continue'); + } + + protected function isBlockCompletable($Type) + { + return method_exists($this, 'block' . $Type . 'Complete'); + } + + # + # Code + + protected function blockCode($Line, $Block = null) + { + if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] >= 4) + { + $text = substr($Line['body'], 4); + + $Block = array( + 'element' => array( + 'name' => 'pre', + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ), + ); + + return $Block; + } + } + + protected function blockCodeContinue($Line, $Block) + { + if ($Line['indent'] >= 4) + { + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + $Block['element']['element']['text'] .= "\n"; + + $text = substr($Line['body'], 4); + + $Block['element']['element']['text'] .= $text; + + return $Block; + } + } + + protected function blockCodeComplete($Block) + { + return $Block; + } + + # + # Comment + + protected function blockComment($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (strpos($Line['text'], '') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + } + + protected function blockCommentContinue($Line, array $Block) + { + if (isset($Block['closed'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + if (strpos($Line['text'], '-->') !== false) + { + $Block['closed'] = true; + } + + return $Block; + } + + # + # Fenced Code + + protected function blockFencedCode($Line) + { + $marker = $Line['text'][0]; + + $openerLength = strspn($Line['text'], $marker); + + if ($openerLength < 3) + { + return; + } + + $infostring = trim(substr($Line['text'], $openerLength), "\t "); + + if (strpos($infostring, '`') !== false) + { + return; + } + + $Element = array( + 'name' => 'code', + 'text' => '', + ); + + if ($infostring !== '') + { + /** + * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes + * Every HTML element may have a class attribute specified. + * The attribute, if specified, must have a value that is a set + * of space-separated tokens representing the various classes + * that the element belongs to. + * [...] + * The space characters, for the purposes of this specification, + * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab), + * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and + * U+000D CARRIAGE RETURN (CR). + */ + $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r")); + + $Element['attributes'] = array('class' => "language-$language"); + } + + $Block = array( + 'char' => $marker, + 'openerLength' => $openerLength, + 'element' => array( + 'name' => 'pre', + 'element' => $Element, + ), + ); + + return $Block; + } + + protected function blockFencedCodeContinue($Line, $Block) + { + if (isset($Block['complete'])) + { + return; + } + + if (isset($Block['interrupted'])) + { + $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']); + + unset($Block['interrupted']); + } + + if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength'] + and chop(substr($Line['text'], $len), ' ') === '' + ) { + $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1); + + $Block['complete'] = true; + + return $Block; + } + + $Block['element']['element']['text'] .= "\n" . $Line['body']; + + return $Block; + } + + protected function blockFencedCodeComplete($Block) + { + return $Block; + } + + # + # Header + + protected function blockHeader($Line) + { + $level = strspn($Line['text'], '#'); + + if ($level > 6) + { + return; + } + + $text = trim($Line['text'], '#'); + + if ($this->strictMode and isset($text[0]) and $text[0] !== ' ') + { + return; + } + + $text = trim($text, ' '); + + $Block = array( + 'element' => array( + 'name' => 'h' . $level, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $text, + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + + # + # List + + protected function blockList($Line, array $CurrentBlock = null) + { + list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]'); + + if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches)) + { + $contentIndent = strlen($matches[2]); + + if ($contentIndent >= 5) + { + $contentIndent -= 1; + $matches[1] = substr($matches[1], 0, -$contentIndent); + $matches[3] = str_repeat(' ', $contentIndent) . $matches[3]; + } + elseif ($contentIndent === 0) + { + $matches[1] .= ' '; + } + + $markerWithoutWhitespace = strstr($matches[1], ' ', true); + + $Block = array( + 'indent' => $Line['indent'], + 'pattern' => $pattern, + 'data' => array( + 'type' => $name, + 'marker' => $matches[1], + 'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)), + ), + 'element' => array( + 'name' => $name, + 'elements' => array(), + ), + ); + $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/'); + + if ($name === 'ol') + { + $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0'; + + if ($listStart !== '1') + { + if ( + isset($CurrentBlock) + and $CurrentBlock['type'] === 'Paragraph' + and ! isset($CurrentBlock['interrupted']) + ) { + return; + } + + $Block['element']['attributes'] = array('start' => $listStart); + } + } + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => !empty($matches[3]) ? array($matches[3]) : array(), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + } + + protected function blockListContinue($Line, array $Block) + { + if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument'])) + { + return null; + } + + $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker'])); + + if ($Line['indent'] < $requiredIndent + and ( + ( + $Block['data']['type'] === 'ol' + and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) or ( + $Block['data']['type'] === 'ul' + and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches) + ) + ) + ) { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + unset($Block['li']); + + $text = isset($matches[1]) ? $matches[1] : ''; + + $Block['indent'] = $Line['indent']; + + $Block['li'] = array( + 'name' => 'li', + 'handler' => array( + 'function' => 'li', + 'argument' => array($text), + 'destination' => 'elements' + ) + ); + + $Block['element']['elements'] []= & $Block['li']; + + return $Block; + } + elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line)) + { + return null; + } + + if ($Line['text'][0] === '[' and $this->blockReference($Line)) + { + return $Block; + } + + if ($Line['indent'] >= $requiredIndent) + { + if (isset($Block['interrupted'])) + { + $Block['li']['handler']['argument'] []= ''; + + $Block['loose'] = true; + + unset($Block['interrupted']); + } + + $text = substr($Line['body'], $requiredIndent); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']); + + $Block['li']['handler']['argument'] []= $text; + + return $Block; + } + } + + protected function blockListComplete(array $Block) + { + if (isset($Block['loose'])) + { + foreach ($Block['element']['elements'] as &$li) + { + if (end($li['handler']['argument']) !== '') + { + $li['handler']['argument'] []= ''; + } + } + } + + return $Block; + } + + # + # Quote + + protected function blockQuote($Line) + { + if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block = array( + 'element' => array( + 'name' => 'blockquote', + 'handler' => array( + 'function' => 'linesElements', + 'argument' => (array) $matches[1], + 'destination' => 'elements', + ) + ), + ); + + return $Block; + } + } + + protected function blockQuoteContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches)) + { + $Block['element']['handler']['argument'] []= $matches[1]; + + return $Block; + } + + if ( ! isset($Block['interrupted'])) + { + $Block['element']['handler']['argument'] []= $Line['text']; + + return $Block; + } + } + + # + # Rule + + protected function blockRule($Line) + { + $marker = $Line['text'][0]; + + if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '') + { + $Block = array( + 'element' => array( + 'name' => 'hr', + ), + ); + + return $Block; + } + } + + # + # Setext + + protected function blockSetextHeader($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '') + { + $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; + + return $Block; + } + } + + # + # Markup + + protected function blockMarkup($Line) + { + if ($this->markupEscaped or $this->safeMode) + { + return; + } + + if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches)) + { + $element = strtolower($matches[1]); + + if (in_array($element, $this->textLevelElements)) + { + return; + } + + $Block = array( + 'name' => $matches[1], + 'element' => array( + 'rawHtml' => $Line['text'], + 'autobreak' => true, + ), + ); + + return $Block; + } + } + + protected function blockMarkupContinue($Line, array $Block) + { + if (isset($Block['closed']) or isset($Block['interrupted'])) + { + return; + } + + $Block['element']['rawHtml'] .= "\n" . $Line['body']; + + return $Block; + } + + # + # Reference + + protected function blockReference($Line) + { + if (strpos($Line['text'], ']') !== false + and preg_match('/^\[(.+?)\]:[ ]*+?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches) + ) { + $id = strtolower($matches[1]); + + $Data = array( + 'url' => $matches[2], + 'title' => isset($matches[3]) ? $matches[3] : null, + ); + + $this->DefinitionData['Reference'][$id] = $Data; + + $Block = array( + 'element' => array(), + ); + + return $Block; + } + } + + # + # Table + + protected function blockTable($Line, array $Block = null) + { + if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted'])) + { + return; + } + + if ( + strpos($Block['element']['handler']['argument'], '|') === false + and strpos($Line['text'], '|') === false + and strpos($Line['text'], ':') === false + or strpos($Block['element']['handler']['argument'], "\n") !== false + ) { + return; + } + + if (chop($Line['text'], ' -:|') !== '') + { + return; + } + + $alignments = array(); + + $divider = $Line['text']; + + $divider = trim($divider); + $divider = trim($divider, '|'); + + $dividerCells = explode('|', $divider); + + foreach ($dividerCells as $dividerCell) + { + $dividerCell = trim($dividerCell); + + if ($dividerCell === '') + { + return; + } + + $alignment = null; + + if ($dividerCell[0] === ':') + { + $alignment = 'left'; + } + + if (substr($dividerCell, - 1) === ':') + { + $alignment = $alignment === 'left' ? 'center' : 'right'; + } + + $alignments []= $alignment; + } + + # ~ + + $HeaderElements = array(); + + $header = $Block['element']['handler']['argument']; + + $header = trim($header); + $header = trim($header, '|'); + + $headerCells = explode('|', $header); + + if (count($headerCells) !== count($alignments)) + { + return; + } + + foreach ($headerCells as $index => $headerCell) + { + $headerCell = trim($headerCell); + + $HeaderElement = array( + 'name' => 'th', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $headerCell, + 'destination' => 'elements', + ) + ); + + if (isset($alignments[$index])) + { + $alignment = $alignments[$index]; + + $HeaderElement['attributes'] = array( + 'style' => "text-align: $alignment;", + ); + } + + $HeaderElements []= $HeaderElement; + } + + # ~ + + $Block = array( + 'alignments' => $alignments, + 'identified' => true, + 'element' => array( + 'name' => 'table', + 'elements' => array(), + ), + ); + + $Block['element']['elements'] []= array( + 'name' => 'thead', + ); + + $Block['element']['elements'] []= array( + 'name' => 'tbody', + 'elements' => array(), + ); + + $Block['element']['elements'][0]['elements'] []= array( + 'name' => 'tr', + 'elements' => $HeaderElements, + ); + + return $Block; + } + + protected function blockTableContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|')) + { + $Elements = array(); + + $row = $Line['text']; + + $row = trim($row); + $row = trim($row, '|'); + + preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches); + + $cells = array_slice($matches[0], 0, count($Block['alignments'])); + + foreach ($cells as $index => $cell) + { + $cell = trim($cell); + + $Element = array( + 'name' => 'td', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $cell, + 'destination' => 'elements', + ) + ); + + if (isset($Block['alignments'][$index])) + { + $Element['attributes'] = array( + 'style' => 'text-align: ' . $Block['alignments'][$index] . ';', + ); + } + + $Elements []= $Element; + } + + $Element = array( + 'name' => 'tr', + 'elements' => $Elements, + ); + + $Block['element']['elements'][1]['elements'] []= $Element; + + return $Block; + } + } + + # + # ~ + # + + protected function paragraph($Line) + { + return array( + 'type' => 'Paragraph', + 'element' => array( + 'name' => 'p', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $Line['text'], + 'destination' => 'elements', + ), + ), + ); + } + + protected function paragraphContinue($Line, array $Block) + { + if (isset($Block['interrupted'])) + { + return; + } + + $Block['element']['handler']['argument'] .= "\n".$Line['text']; + + return $Block; + } + + # + # Inline Elements + # + + protected $InlineTypes = array( + '!' => array('Image'), + '&' => array('SpecialCharacter'), + '*' => array('Emphasis'), + ':' => array('Url'), + '<' => array('UrlTag', 'EmailTag', 'Markup'), + '[' => array('Link'), + '_' => array('Emphasis'), + '`' => array('Code'), + '~' => array('Strikethrough'), + '\\' => array('EscapeSequence'), + ); + + # ~ + + protected $inlineMarkerList = '!*_&[:<`~\\'; + + # + # ~ + # + + public function line($text, $nonNestables = array()) + { + return $this->elements($this->lineElements($text, $nonNestables)); + } + + protected function lineElements($text, $nonNestables = array()) + { + # standardize line breaks + $text = str_replace(array("\r\n", "\r"), "\n", $text); + + $Elements = array(); + + $nonNestables = (empty($nonNestables) + ? array() + : array_combine($nonNestables, $nonNestables) + ); + + # $excerpt is based on the first occurrence of a marker + + while ($excerpt = strpbrk($text, $this->inlineMarkerList)) + { + $marker = $excerpt[0]; + + $markerPosition = strlen($text) - strlen($excerpt); + + $Excerpt = array('text' => $excerpt, 'context' => $text); + + foreach ($this->InlineTypes[$marker] as $inlineType) + { + # check to see if the current inline type is nestable in the current context + + if (isset($nonNestables[$inlineType])) + { + continue; + } + + $Inline = $this->{"inline$inlineType"}($Excerpt); + + if ( ! isset($Inline)) + { + continue; + } + + # makes sure that the inline belongs to "our" marker + + if (isset($Inline['position']) and $Inline['position'] > $markerPosition) + { + continue; + } + + # sets a default inline position + + if ( ! isset($Inline['position'])) + { + $Inline['position'] = $markerPosition; + } + + # cause the new element to 'inherit' our non nestables + + + $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables']) + ? array_merge($Inline['element']['nonNestables'], $nonNestables) + : $nonNestables + ; + + # the text that comes before the inline + $unmarkedText = substr($text, 0, $Inline['position']); + + # compile the unmarked text + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + # compile the inline + $Elements[] = $this->extractElement($Inline); + + # remove the examined text + $text = substr($text, $Inline['position'] + $Inline['extent']); + + continue 2; + } + + # the marker does not belong to an inline + + $unmarkedText = substr($text, 0, $markerPosition + 1); + + $InlineText = $this->inlineText($unmarkedText); + $Elements[] = $InlineText['element']; + + $text = substr($text, $markerPosition + 1); + } + + $InlineText = $this->inlineText($text); + $Elements[] = $InlineText['element']; + + foreach ($Elements as &$Element) + { + if ( ! isset($Element['autobreak'])) + { + $Element['autobreak'] = false; + } + } + + return $Elements; + } + + # + # ~ + # + + protected function inlineText($text) + { + $Inline = array( + 'extent' => strlen($text), + 'element' => array(), + ); + + $Inline['element']['elements'] = self::pregReplaceElements( + $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/', + array( + array('name' => 'br'), + array('text' => "\n"), + ), + $text + ); + + return $Inline; + } + + protected function inlineCode($Excerpt) + { + $marker = $Excerpt['text'][0]; + + if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(? strlen($matches[0]), + 'element' => array( + 'name' => 'code', + 'text' => $text, + ), + ); + } + } + + protected function inlineEmailTag($Excerpt) + { + $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'; + + $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@' + . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*'; + + if (strpos($Excerpt['text'], '>') !== false + and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches) + ){ + $url = $matches[1]; + + if ( ! isset($matches[2])) + { + $url = "mailto:$url"; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $matches[1], + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + protected function inlineEmphasis($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + $marker = $Excerpt['text'][0]; + + if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'strong'; + } + elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) + { + $emphasis = 'em'; + } + else + { + return; + } + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => $emphasis, + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + + protected function inlineEscapeSequence($Excerpt) + { + if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) + { + return array( + 'element' => array('rawHtml' => $Excerpt['text'][1]), + 'extent' => 2, + ); + } + } + + protected function inlineImage($Excerpt) + { + if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') + { + return; + } + + $Excerpt['text']= substr($Excerpt['text'], 1); + + $Link = $this->inlineLink($Excerpt); + + if ($Link === null) + { + return; + } + + $Inline = array( + 'extent' => $Link['extent'] + 1, + 'element' => array( + 'name' => 'img', + 'attributes' => array( + 'src' => $Link['element']['attributes']['href'], + 'alt' => $Link['element']['handler']['argument'], + ), + 'autobreak' => true, + ), + ); + + $Inline['element']['attributes'] += $Link['element']['attributes']; + + unset($Inline['element']['attributes']['href']); + + return $Inline; + } + + protected function inlineLink($Excerpt) + { + $Element = array( + 'name' => 'a', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => null, + 'destination' => 'elements', + ), + 'nonNestables' => array('Url', 'Link'), + 'attributes' => array( + 'href' => null, + 'title' => null, + ), + ); + + $extent = 0; + + $remainder = $Excerpt['text']; + + if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches)) + { + $Element['handler']['argument'] = $matches[1]; + + $extent += strlen($matches[0]); + + $remainder = substr($remainder, $extent); + } + else + { + return; + } + + if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches)) + { + $Element['attributes']['href'] = $matches[1]; + + if (isset($matches[2])) + { + $Element['attributes']['title'] = substr($matches[2], 1, - 1); + } + + $extent += strlen($matches[0]); + } + else + { + if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) + { + $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument']; + $definition = strtolower($definition); + + $extent += strlen($matches[0]); + } + else + { + $definition = strtolower($Element['handler']['argument']); + } + + if ( ! isset($this->DefinitionData['Reference'][$definition])) + { + return; + } + + $Definition = $this->DefinitionData['Reference'][$definition]; + + $Element['attributes']['href'] = $Definition['url']; + $Element['attributes']['title'] = $Definition['title']; + } + + return array( + 'extent' => $extent, + 'element' => $Element, + ); + } + + protected function inlineMarkup($Excerpt) + { + if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) + { + return; + } + + if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + + if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches)) + { + return array( + 'element' => array('rawHtml' => $matches[0]), + 'extent' => strlen($matches[0]), + ); + } + } + + protected function inlineSpecialCharacter($Excerpt) + { + if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false + and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches) + ) { + return array( + 'element' => array('rawHtml' => '&' . $matches[1] . ';'), + 'extent' => strlen($matches[0]), + ); + } + + return; + } + + protected function inlineStrikethrough($Excerpt) + { + if ( ! isset($Excerpt['text'][1])) + { + return; + } + + if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) + { + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'del', + 'handler' => array( + 'function' => 'lineElements', + 'argument' => $matches[1], + 'destination' => 'elements', + ) + ), + ); + } + } + + protected function inlineUrl($Excerpt) + { + if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') + { + return; + } + + if (strpos($Excerpt['context'], 'http') !== false + and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE) + ) { + $url = $matches[0][0]; + + $Inline = array( + 'extent' => strlen($matches[0][0]), + 'position' => $matches[0][1], + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + + return $Inline; + } + } + + protected function inlineUrlTag($Excerpt) + { + if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches)) + { + $url = $matches[1]; + + return array( + 'extent' => strlen($matches[0]), + 'element' => array( + 'name' => 'a', + 'text' => $url, + 'attributes' => array( + 'href' => $url, + ), + ), + ); + } + } + + # ~ + + protected function unmarkedText($text) + { + $Inline = $this->inlineText($text); + return $this->element($Inline['element']); + } + + # + # Handlers + # + + protected function handle(array $Element) + { + if (isset($Element['handler'])) + { + if (!isset($Element['nonNestables'])) + { + $Element['nonNestables'] = array(); + } + + if (is_string($Element['handler'])) + { + $function = $Element['handler']; + $argument = $Element['text']; + unset($Element['text']); + $destination = 'rawHtml'; + } + else + { + $function = $Element['handler']['function']; + $argument = $Element['handler']['argument']; + $destination = $Element['handler']['destination']; + } + + $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']); + + if ($destination === 'handler') + { + $Element = $this->handle($Element); + } + + unset($Element['handler']); + } + + return $Element; + } + + protected function handleElementRecursive(array $Element) + { + return $this->elementApplyRecursive(array($this, 'handle'), $Element); + } + + protected function handleElementsRecursive(array $Elements) + { + return $this->elementsApplyRecursive(array($this, 'handle'), $Elements); + } + + protected function elementApplyRecursive($closure, array $Element) + { + $Element = call_user_func($closure, $Element); + + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']); + } + + return $Element; + } + + protected function elementApplyRecursiveDepthFirst($closure, array $Element) + { + if (isset($Element['elements'])) + { + $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']); + } + elseif (isset($Element['element'])) + { + $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']); + } + + $Element = call_user_func($closure, $Element); + + return $Element; + } + + protected function elementsApplyRecursive($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursive($closure, $Element); + } + + return $Elements; + } + + protected function elementsApplyRecursiveDepthFirst($closure, array $Elements) + { + foreach ($Elements as &$Element) + { + $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element); + } + + return $Elements; + } + + protected function element(array $Element) + { + if ($this->safeMode) + { + $Element = $this->sanitiseElement($Element); + } + + # identity map if element has no handler + $Element = $this->handle($Element); + + $hasName = isset($Element['name']); + + $markup = ''; + + if ($hasName) + { + $markup .= '<' . $Element['name']; + + if (isset($Element['attributes'])) + { + foreach ($Element['attributes'] as $name => $value) + { + if ($value === null) + { + continue; + } + + $markup .= " $name=\"".self::escape($value).'"'; + } + } + } + + $permitRawHtml = false; + + if (isset($Element['text'])) + { + $text = $Element['text']; + } + // very strongly consider an alternative if you're writing an + // extension + elseif (isset($Element['rawHtml'])) + { + $text = $Element['rawHtml']; + + $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode']; + $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode; + } + + $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']); + + if ($hasContent) + { + $markup .= $hasName ? '>' : ''; + + if (isset($Element['elements'])) + { + $markup .= $this->elements($Element['elements']); + } + elseif (isset($Element['element'])) + { + $markup .= $this->element($Element['element']); + } + else + { + if (!$permitRawHtml) + { + $markup .= self::escape($text, true); + } + else + { + $markup .= $text; + } + } + + $markup .= $hasName ? '' : ''; + } + elseif ($hasName) + { + $markup .= ' />'; + } + + return $markup; + } + + protected function elements(array $Elements) + { + $markup = ''; + + $autoBreak = true; + + foreach ($Elements as $Element) + { + if (empty($Element)) + { + continue; + } + + $autoBreakNext = (isset($Element['autobreak']) + ? $Element['autobreak'] : isset($Element['name']) + ); + // (autobreak === false) covers both sides of an element + $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext; + + $markup .= ($autoBreak ? "\n" : '') . $this->element($Element); + $autoBreak = $autoBreakNext; + } + + $markup .= $autoBreak ? "\n" : ''; + + return $markup; + } + + # ~ + + protected function li($lines) + { + $Elements = $this->linesElements($lines); + + if ( ! in_array('', $lines) + and isset($Elements[0]) and isset($Elements[0]['name']) + and $Elements[0]['name'] === 'p' + ) { + unset($Elements[0]['name']); + } + + return $Elements; + } + + # + # AST Convenience + # + + /** + * Replace occurrences $regexp with $Elements in $text. Return an array of + * elements representing the replacement. + */ + protected static function pregReplaceElements($regexp, $Elements, $text) + { + $newElements = array(); + + while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE)) + { + $offset = $matches[0][1]; + $before = substr($text, 0, $offset); + $after = substr($text, $offset + strlen($matches[0][0])); + + $newElements[] = array('text' => $before); + + foreach ($Elements as $Element) + { + $newElements[] = $Element; + } + + $text = $after; + } + + $newElements[] = array('text' => $text); + + return $newElements; + } + + # + # Deprecated Methods + # + + function parse($text) + { + $markup = $this->text($text); + + return $markup; + } + + protected function sanitiseElement(array $Element) + { + static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/'; + static $safeUrlNameToAtt = array( + 'a' => 'href', + 'img' => 'src', + ); + + if ( ! isset($Element['name'])) + { + unset($Element['attributes']); + return $Element; + } + + if (isset($safeUrlNameToAtt[$Element['name']])) + { + $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]); + } + + if ( ! empty($Element['attributes'])) + { + foreach ($Element['attributes'] as $att => $val) + { + # filter out badly parsed attribute + if ( ! preg_match($goodAttribute, $att)) + { + unset($Element['attributes'][$att]); + } + # dump onevent attribute + elseif (self::striAtStart($att, 'on')) + { + unset($Element['attributes'][$att]); + } + } + } + + return $Element; + } + + protected function filterUnsafeUrlInAttribute(array $Element, $attribute) + { + foreach ($this->safeLinksWhitelist as $scheme) + { + if (self::striAtStart($Element['attributes'][$attribute], $scheme)) + { + return $Element; + } + } + + $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]); + + return $Element; + } + + # + # Static Methods + # + + protected static function escape($text, $allowQuotes = false) + { + return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8'); + } + + protected static function striAtStart($string, $needle) + { + $len = strlen($needle); + + if ($len > strlen($string)) + { + return false; + } + else + { + return strtolower(substr($string, 0, $len)) === strtolower($needle); + } + } + + static function instance($name = 'default') + { + if (isset(self::$instances[$name])) + { + return self::$instances[$name]; + } + + $instance = new static(); + + self::$instances[$name] = $instance; + + return $instance; + } + + private static $instances = array(); + + # + # Fields + # + + protected $DefinitionData; + + # + # Read-Only + + protected $specialCharacters = array( + '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~' + ); + + protected $StrongRegex = array( + '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s', + '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us', + ); + + protected $EmRegex = array( + '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', + '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', + ); + + protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+'; + + protected $voidElements = array( + 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', + ); + + protected $textLevelElements = array( + 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', + 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', + 'i', 'rp', 'del', 'code', 'strike', 'marquee', + 'q', 'rt', 'ins', 'font', 'strong', + 's', 'tt', 'kbd', 'mark', + 'u', 'xm', 'sub', 'nobr', + 'sup', 'ruby', + 'var', 'span', + 'wbr', 'time', + ); +} diff --git a/blog/posts/building_a_cooler_body_2/index.md b/blog/posts/building_a_cooler_body_2/index.md deleted file mode 100644 index 8f6fe6b..0000000 --- a/blog/posts/building_a_cooler_body_2/index.md +++ /dev/null @@ -1,3 +0,0 @@ -It has certainly been a very interesting year for my endocrine system. - -As of publishing, I started estrogen exactly one year ago, and the [blog post](../building_a_cooler_body/) about my Journey™ towards this also went up exactly one year ago. \ No newline at end of file diff --git a/blog/posts/building_a_cooler_body_2/index.php b/blog/posts/building_a_cooler_body_2/index.php deleted file mode 100644 index 952e6d9..0000000 --- a/blog/posts/building_a_cooler_body_2/index.php +++ /dev/null @@ -1 +0,0 @@ - -su git -nano ~/.ssh/authorized_keys - -``` - -This is actually what I did. - -Test to make sure ssh login works, and if it does, the git server is now technically set up. You can create repositories anywhere on the server that the `git` user has read/write permissions by creating a directory for the repo (convention dictates that you call it `repoName.git` but you don't have to) and initializing a bare repository in there: - -``` -mkdir reponame.git -cd reponame.git -git init --bare -``` - -Now you should be able to add it as a remote with `git remote add origin git@your.domain:/absolute/path/to/repoName.git` on your machine, or if you're lazy like me and just put your repositories in a folder in the git user's home directory, with `git remote add origin git@your.domain:relativePathTo/repoName.git`. - -Sorcery expects a folder structure like this for your repositories: - -``` -reposFolder -├─userFolder -│ ├─repoName.git -│ └─repoName2.git -└─userFolder -``` - -Now on to the interesting part. - -# Installing the fucker from source - -Sorcery doesn't have a precompiled binary to use that I could find, so it has to be built from source. Due to the developer's choices, this will require the use of Nix. I'm installing and configuring it through the distro package manager on Ubuntu Server, so this part might be a little different for you if you're using something else. - -First, naturally, Nix needs to be installed and the source code cloned: - -``` -apt install -y nix -git clone https://git.t4t.associates/char/sorcery -cd sorcery -``` - -If we try to `nix build` now, Nix is gonna give us some errors, so let's fix those. First, it'll complain about a couple of "experimental features" not being enabled. Enable the relevant ones by appending the following to `/etc/nix/nix.conf`: - -``` -experimental-features = nix-command flakes -``` - -If you're in my situation, that file should look like this after: - -

/etc/nix/nix.conf

- -``` -# see https://nixos.org/manual/nix/stable/command-ref/conf-file - -sandbox = true -experimental-features = nix-command flakes -``` - -Now it's probably gonna complain that you've been denied permission to get the status of some kind of daemon-socket. You can gain permission by adding yourself to the `nix-users` group, like so: - -``` -sudo usermod -a -G nix-users yourusername -``` - -Make sure to log out and back in after you do that. - -Okay, *now* we can run `nix build` in the git repo to get our binary: - -``` -nix build -``` - -It'll show up inside the cloned repo at `result/bin/sorceryd`. Now move it somewhere that's not that — the Sorcery README suggests moving it to `/usr/local/bin/` "or whatever". Installing it there will make some pre-provided things like the systemd unit work with fewer changes, so I recommend you do that. - -``` -mv result/bin/sorceryd /usr/local/bin/ -``` - -If you put it somewhere else, replace mentions of `/usr/local/bin/` accordingly. - -# Reverse proxy configuration - -The dev provides an nginx config for Sorcery through a script included in the repo that generates one. It's pretty elaborate, so I'm gonna have to run the script and reverse engineer its output to make a Caddy config. If you're using Nginx, I'm guessing this next part will be relevant to you. If you're using Caddy, skip ahead to where I provide the working Caddy config I used. - -## Extracting the Nginx config - -The script in question is a Typescript file, and the dev recommends using Deno, so we're gonna have to install that first. Annoyingly, Deno doesn't publish to most distro package managers, so that'll look about like this: - -``` -curl -fsSL https://deno.land/install.sh | sh -``` - -Yucky, but fortunately after that it just works, assuming you told it to add itself to the PATH when it asked. Now run the script: - -``` -deno run sorcery.ngx.ts > sorcery.conf -``` - -If you're using Nginx, edit the newly generated `sorcery.conf` accordingly and do whatever it is you do with it. - -## Caddy config - -Wow, that was tough. Thanks to my hard work, you may now simply copy this into your Caddyfile and you're golden: - -``` - -``` - -# systemd configuration - -Sorcery's README provides a systemd unit and the environment file it expects. We'll put the environment file in place first — copy this to `/etc/sorcery/env` and edit accordingly: - -

/etc/sorcery/env

- -``` -SORCERY_REPOSITORIES=/absolute/path/to/reposFolder -SORCERY_CACHE=/var/cache/sorcery -SORCERY_SOCKET=/run/sorcery/sock -SORCERY_INSTANCE_NAME=your.domain -SORCERY_CLONE_URL_BASE=https://your.domain -SORCERY_CONTROL_SOCKET=/run/sorcery/control -``` - -Now paste the following systemd unit to `/etc/systemd/system/sorceryd.service`: - -

/etc/systemd/system/sorceryd.service

- -``` -[Unit] -Description=Sorcery Git forge -After=network.target - -[Service] -Type=simple -User=git -Group=git -RuntimeDirectory=sorcery -CacheDirectory=sorcery -ConfigurationDirectory=sorcery -EnvironmentFile=/etc/sorcery/env -ExecStart=/usr/local/bin/sorceryd -Restart=on-failure -RestartSec=2 -UMask=0027 -NoNewPrivileges=true -PrivateTmp=true -ProtectSystem=strict -ProtectHome=read-only - -[Install] -WantedBy=multi-user.target -``` - -Mercifully, if you've followed this guide so far, you shouldn't need to change anything in there. Now you can start 'er up: - -``` -sudo systemctl daemon-reload -sudo systemctl enable --now sorceryd.service -``` \ No newline at end of file diff --git a/blog/posts/guide_sorcery_git/index.php b/blog/posts/guide_sorcery_git/index.php deleted file mode 100644 index 952e6d9..0000000 --- a/blog/posts/guide_sorcery_git/index.php +++ /dev/null @@ -1 +0,0 @@ -This article was written with the assistance of ChatGPT.

\ No newline at end of file diff --git a/blog/posts/invaluable_contributions/index.php b/blog/posts/invaluable_contributions/index.php new file mode 100644 index 0000000..952e6d9 --- /dev/null +++ b/blog/posts/invaluable_contributions/index.php @@ -0,0 +1 @@ +
-

v4

+

v4

bugwo.men v4
diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf new file mode 100644 index 0000000..80da7d0 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf new file mode 100644 index 0000000..d39bfaa Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf new file mode 100644 index 0000000..35f4fb7 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf new file mode 100644 index 0000000..f0edd19 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf new file mode 100644 index 0000000..8069fa6 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf new file mode 100644 index 0000000..44155b1 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf new file mode 100644 index 0000000..3541e33 Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf new file mode 100644 index 0000000..157d62e Binary files /dev/null and b/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf differ diff --git a/stuff/fonts/Atkinson_Hyperlegible/OFL.txt b/stuff/fonts/Atkinson_Hyperlegible/OFL.txt new file mode 100644 index 0000000..9d23fa3 --- /dev/null +++ b/stuff/fonts/Atkinson_Hyperlegible/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 Braille Institute of America, Inc. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/stuff/fonts/B612/B612-Bold.ttf b/stuff/fonts/B612/B612-Bold.ttf new file mode 100644 index 0000000..9c12c10 Binary files /dev/null and b/stuff/fonts/B612/B612-Bold.ttf differ diff --git a/stuff/fonts/B612/B612-BoldItalic.ttf b/stuff/fonts/B612/B612-BoldItalic.ttf new file mode 100644 index 0000000..6007ef3 Binary files /dev/null and b/stuff/fonts/B612/B612-BoldItalic.ttf differ diff --git a/stuff/fonts/B612/B612-Italic.ttf b/stuff/fonts/B612/B612-Italic.ttf new file mode 100644 index 0000000..06e4437 Binary files /dev/null and b/stuff/fonts/B612/B612-Italic.ttf differ diff --git a/stuff/fonts/B612/B612-Regular.ttf b/stuff/fonts/B612/B612-Regular.ttf new file mode 100644 index 0000000..ab83ba3 Binary files /dev/null and b/stuff/fonts/B612/B612-Regular.ttf differ diff --git a/stuff/fonts/B612/OFL.txt b/stuff/fonts/B612/OFL.txt new file mode 100644 index 0000000..0b5d530 --- /dev/null +++ b/stuff/fonts/B612/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2012 The B612 Project Authors (https://github.com/polarsys/b612) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/stuff/fonts/B612_Mono/B612Mono-Bold.ttf b/stuff/fonts/B612_Mono/B612Mono-Bold.ttf new file mode 100644 index 0000000..b282d8d Binary files /dev/null and b/stuff/fonts/B612_Mono/B612Mono-Bold.ttf differ diff --git a/stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf b/stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf new file mode 100644 index 0000000..97b92cc Binary files /dev/null and b/stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf differ diff --git a/stuff/fonts/B612_Mono/B612Mono-Italic.ttf b/stuff/fonts/B612_Mono/B612Mono-Italic.ttf new file mode 100644 index 0000000..c633e93 Binary files /dev/null and b/stuff/fonts/B612_Mono/B612Mono-Italic.ttf differ diff --git a/stuff/fonts/B612_Mono/B612Mono-Regular.ttf b/stuff/fonts/B612_Mono/B612Mono-Regular.ttf new file mode 100644 index 0000000..ed013f2 Binary files /dev/null and b/stuff/fonts/B612_Mono/B612Mono-Regular.ttf differ diff --git a/stuff/fonts/B612_Mono/OFL.txt b/stuff/fonts/B612_Mono/OFL.txt new file mode 100644 index 0000000..0b5d530 --- /dev/null +++ b/stuff/fonts/B612_Mono/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2012 The B612 Project Authors (https://github.com/polarsys/b612) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/stuff/fonts/DS-DIGI.ttf b/stuff/fonts/DS-DIGI.ttf new file mode 100644 index 0000000..0925877 Binary files /dev/null and b/stuff/fonts/DS-DIGI.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSans-Bold.ttf b/stuff/fonts/Google_Sans/GoogleSans-Bold.ttf new file mode 100644 index 0000000..fe51a05 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSans-Bold.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf b/stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf new file mode 100644 index 0000000..69f2274 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSans-Italic.ttf b/stuff/fonts/Google_Sans/GoogleSans-Italic.ttf new file mode 100644 index 0000000..205dbcc Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSans-Italic.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSans-Regular.ttf b/stuff/fonts/Google_Sans/GoogleSans-Regular.ttf new file mode 100644 index 0000000..c732115 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSans-Regular.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf b/stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf new file mode 100644 index 0000000..b673c75 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf b/stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf new file mode 100644 index 0000000..fadb647 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf b/stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf new file mode 100644 index 0000000..07aa7de Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf differ diff --git a/stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf b/stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf new file mode 100644 index 0000000..8b34039 Binary files /dev/null and b/stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf differ diff --git a/stuff/fonts/Google_Sans/OFL.txt b/stuff/fonts/Google_Sans/OFL.txt new file mode 100644 index 0000000..5d6f71c --- /dev/null +++ b/stuff/fonts/Google_Sans/OFL.txt @@ -0,0 +1,91 @@ +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf b/stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf new file mode 100644 index 0000000..c56c765 Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf differ diff --git a/stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf b/stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf new file mode 100644 index 0000000..5470d50 Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf differ diff --git a/stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf b/stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf new file mode 100644 index 0000000..519d313 Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf differ diff --git a/stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf b/stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf new file mode 100644 index 0000000..23ea70a Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf differ diff --git a/stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf b/stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf new file mode 100644 index 0000000..c3ccb5f Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf differ diff --git a/stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf b/stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf new file mode 100644 index 0000000..1b13cd7 Binary files /dev/null and b/stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf differ diff --git a/stuff/fonts/Noto_Serif/OFL.txt b/stuff/fonts/Noto_Serif/OFL.txt new file mode 100644 index 0000000..09f020b --- /dev/null +++ b/stuff/fonts/Noto_Serif/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Noto Project Authors (https://github.com/notofonts/latin-greek-cyrillic) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf b/stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf new file mode 100644 index 0000000..fc14a5a Binary files /dev/null and b/stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf differ diff --git a/stuff/fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf b/stuff/fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf new file mode 100644 index 0000000..99b4b1d Binary files /dev/null and b/stuff/fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf differ diff --git a/stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf b/stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf new file mode 100644 index 0000000..8f53b29 Binary files /dev/null and b/stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf differ diff --git a/stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf b/stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf new file mode 100644 index 0000000..039ceda Binary files /dev/null and b/stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf differ diff --git a/stuff/fonts/OpenDyslexic/OpenDyslexicMono-Regular.otf b/stuff/fonts/OpenDyslexic/OpenDyslexicMono-Regular.otf new file mode 100644 index 0000000..543d46b Binary files /dev/null and b/stuff/fonts/OpenDyslexic/OpenDyslexicMono-Regular.otf differ diff --git a/stuff/fonts/Ubuntu/Ubuntu-Bold.ttf b/stuff/fonts/Ubuntu/Ubuntu-Bold.ttf new file mode 100644 index 0000000..c2293d5 Binary files /dev/null and b/stuff/fonts/Ubuntu/Ubuntu-Bold.ttf differ diff --git a/stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf b/stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf new file mode 100644 index 0000000..a3f4996 Binary files /dev/null and b/stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf differ diff --git a/stuff/fonts/Ubuntu/Ubuntu-Italic.ttf b/stuff/fonts/Ubuntu/Ubuntu-Italic.ttf new file mode 100644 index 0000000..6bd39b0 Binary files /dev/null and b/stuff/fonts/Ubuntu/Ubuntu-Italic.ttf differ diff --git a/stuff/fonts/Ubuntu/Ubuntu-Regular.ttf b/stuff/fonts/Ubuntu/Ubuntu-Regular.ttf new file mode 100644 index 0000000..b5505e6 Binary files /dev/null and b/stuff/fonts/Ubuntu/Ubuntu-Regular.ttf differ diff --git a/stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf b/stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf new file mode 100644 index 0000000..01ad81b Binary files /dev/null and b/stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf differ diff --git a/stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf b/stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf new file mode 100644 index 0000000..731884e Binary files /dev/null and b/stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf differ diff --git a/stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf b/stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf new file mode 100644 index 0000000..b89338d Binary files /dev/null and b/stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf differ diff --git a/stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf b/stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf new file mode 100644 index 0000000..4977028 Binary files /dev/null and b/stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf differ diff --git a/stuff/fonts/atkinsonhyperlegible.css b/stuff/fonts/atkinsonhyperlegible.css new file mode 100644 index 0000000..972f456 --- /dev/null +++ b/stuff/fonts/atkinsonhyperlegible.css @@ -0,0 +1,54 @@ +@font-face { + font-family: atkinsonhyperlegible; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegible-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: atkinsonhyperlegible, sans-serif; + --monofont: atkinsonhyperlegible_mono, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/atkinsonhyperlegiblemono.css b/stuff/fonts/atkinsonhyperlegiblemono.css new file mode 100644 index 0000000..0814af9 --- /dev/null +++ b/stuff/fonts/atkinsonhyperlegiblemono.css @@ -0,0 +1,29 @@ +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: atkinsonhyperlegible_mono; + src: url(https://bugwo.men/stuff/fonts/Atkinson_Hyperlegible/AtkinsonHyperlegibleMono-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: atkinsonhyperlegible_mono, monospace; + --monofont: atkinsonhyperlegible_mono, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/b612.css b/stuff/fonts/b612.css new file mode 100644 index 0000000..eefcb0f --- /dev/null +++ b/stuff/fonts/b612.css @@ -0,0 +1,54 @@ +@font-face { + font-family: b612; + src: url(https://bugwo.men/stuff/fonts/B612/B612-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: b612; + src: url(https://bugwo.men/stuff/fonts/B612/B612-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: b612; + src: url(https://bugwo.men/stuff/fonts/B612/B612-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: b612; + src: url(https://bugwo.men/stuff/fonts/B612/B612-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: b612, sans-serif; + --monofont: b612_mono, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/b612mono.css b/stuff/fonts/b612mono.css new file mode 100644 index 0000000..f015de5 --- /dev/null +++ b/stuff/fonts/b612mono.css @@ -0,0 +1,29 @@ +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: b612_mono; + src: url(https://bugwo.men/stuff/fonts/B612_Mono/B612Mono-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: b612_mono, monospace; + --monofont: b612_mono, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/browserdefault.css b/stuff/fonts/browserdefault.css new file mode 100644 index 0000000..07038c8 --- /dev/null +++ b/stuff/fonts/browserdefault.css @@ -0,0 +1,9 @@ +/* :root { + --bodyfont: sans-serif; + --monofont: monospace; +} */ + +:root { + --bodyfont: unset; + --monofont: unset; +} \ No newline at end of file diff --git a/stuff/fonts/cafe.ttf b/stuff/fonts/cafe.ttf new file mode 100644 index 0000000..e31d5fd Binary files /dev/null and b/stuff/fonts/cafe.ttf differ diff --git a/stuff/fonts/firsttimewriting.ttf b/stuff/fonts/firsttimewriting.ttf new file mode 100644 index 0000000..180df00 Binary files /dev/null and b/stuff/fonts/firsttimewriting.ttf differ diff --git a/stuff/fonts/googlesans.css b/stuff/fonts/googlesans.css new file mode 100644 index 0000000..59b3785 --- /dev/null +++ b/stuff/fonts/googlesans.css @@ -0,0 +1,54 @@ +@font-face { + font-family: googlesans; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSans-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: googlesans; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSans-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: googlesans; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSans-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: googlesans; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSans-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: googlesans, sans-serif; + --monofont: googlesanscode, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/googlesanscode.css b/stuff/fonts/googlesanscode.css new file mode 100644 index 0000000..5f701a8 --- /dev/null +++ b/stuff/fonts/googlesanscode.css @@ -0,0 +1,29 @@ +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: googlesanscode; + src: url(https://bugwo.men/stuff/fonts/Google_Sans/GoogleSansCode-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: googlesanscode, sans-serif; + --monofont: googlesanscode, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/notoserif.css b/stuff/fonts/notoserif.css new file mode 100644 index 0000000..e1df357 --- /dev/null +++ b/stuff/fonts/notoserif.css @@ -0,0 +1,41 @@ +@font-face { + font-family: notoserif; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSerif-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: notoserif; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSerif-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: notoserif; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSerif-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: notoserif; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSerif-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: notosansmono; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSansMono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: notosansmono; + src: url(https://bugwo.men/stuff/fonts/Noto_Serif/NotoSansMono-Bold.ttf); + font-weight: bold; + font-display: swap; +} + +:root { + --bodyfont: notoserif, serif; + --monofont: notosansmono, monospace; +} \ No newline at end of file diff --git a/stuff/fonts/opendyslexic.css b/stuff/fonts/opendyslexic.css new file mode 100644 index 0000000..294b74c --- /dev/null +++ b/stuff/fonts/opendyslexic.css @@ -0,0 +1,35 @@ +@font-face { + font-family: opendyslexic; + src: url(https://bugwo.men/stuff/fonts/OpenDyslexic/OpenDyslexic-Regular.otf); + font-display: swap; +} +@font-face { + font-family: opendyslexic; + src: url(https://bugwo.men/stuff/fonts/OpenDyslexic/OpenDyslexic-Bold.otf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: opendyslexic; + src: url(https://bugwo.men/stuff/fonts/OpenDyslexic/OpenDyslexic-Italic.otf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: opendyslexic; + src: url(https://bugwo.men/stuff/fonts/OpenDyslexic/OpenDyslexic-BoldItalic.otf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: opendyslexic_mono; + src: url(https://bugwo.men/stuff/fonts/OpenDyslexic/OpenDyslexicMono-Regular.otf); + font-display: swap; +} + +:root { + --bodyfont: "opendyslexic", sans-serif; + --monofont: "opendyslexic_mono", monospace; +} \ No newline at end of file diff --git a/stuff/fonts/silkscreen.css b/stuff/fonts/silkscreen.css new file mode 100644 index 0000000..636da3e --- /dev/null +++ b/stuff/fonts/silkscreen.css @@ -0,0 +1,16 @@ +@font-face { + font-family: silkscreen; + src: url(https://bugwo.men/stuff/fonts/slkscr.ttf); + font-display: swap; +} +@font-face { + font-family: silkscreen; + src: url(https://bugwo.men/stuff/fonts/slkscrb.ttf); + font-weight: bold; + font-display: swap; +} + +:root { + --bodyfont: "silkscreen", sans-serif; + --monofont: "silkscreen", monospace; +} \ No newline at end of file diff --git a/stuff/fonts/slkscr.ttf b/stuff/fonts/slkscr.ttf new file mode 100644 index 0000000..85a2037 Binary files /dev/null and b/stuff/fonts/slkscr.ttf differ diff --git a/stuff/fonts/slkscrb.ttf b/stuff/fonts/slkscrb.ttf new file mode 100644 index 0000000..2619b36 Binary files /dev/null and b/stuff/fonts/slkscrb.ttf differ diff --git a/stuff/fonts/ubuntu.css b/stuff/fonts/ubuntu.css new file mode 100644 index 0000000..0a67621 --- /dev/null +++ b/stuff/fonts/ubuntu.css @@ -0,0 +1,54 @@ +@font-face { + font-family: ubuntu; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/Ubuntu-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: ubuntu; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/Ubuntu-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: ubuntu; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/Ubuntu-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: ubuntu; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/Ubuntu-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: ubuntu_mono; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/UbuntuMono-Regular.ttf); + font-display: swap; +} +@font-face { + font-family: ubuntu_mono; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/UbuntuMono-Bold.ttf); + font-weight: bold; + font-display: swap; +} +@font-face { + font-family: ubuntu_mono; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/UbuntuMono-Italic.ttf); + font-style: italic; + font-display: swap; +} +@font-face { + font-family: ubuntu_mono; + src: url(https://bugwo.men/stuff/fonts/Ubuntu/UbuntuMono-BoldItalic.ttf); + font-weight: bold; + font-style: italic; + font-display: swap; +} + +:root { + --bodyfont: "ubuntu", sans-serif; + --monofont: "ubuntu_mono", monospace; +} \ No newline at end of file diff --git a/style.css b/style.css index e9741c6..750a712 100644 --- a/style.css +++ b/style.css @@ -84,11 +84,11 @@ body > p:last-child { /* Links */ a { - color: var(--accent1); + color: var(--linkcolor); } a:hover, a:focus { - color: var(--accent2); + color: var(--linkhover); } .backlink { border-left: var(--stdpadding) solid var(--accent1); @@ -112,6 +112,11 @@ header * { pointer-events: auto; } +header h1 a { + color: var(--fg0); + text-decoration: none; +} + .headerbar { /* This div represents the top header bar */ display: flex; flex-direction: row; diff --git a/uses/cumulonimbus/index.php b/uses/cumulonimbus/index.php index 105f0b6..b75dd32 100644 --- a/uses/cumulonimbus/index.php +++ b/uses/cumulonimbus/index.php @@ -58,13 +58,6 @@

I used to use Forgejo, which I like and would still be using if I was sharing it with other people, but I switched because I wasn't using literally any of its many features and I didn't want to worry about LLM scrapers finding it and bringing both it and my server to their knees at an arbitrary point in the future.

-
-

FreshRSS

-

I ended up with this because I elected to ditch Nextcloud in the process of migrating hosting providers, and this was the first RSS reader that I managed to get working on the new server. I swear, it's like the RSS 2.0 spec states that your self-hosted RSS reader has to have installation instructions that don't work.

-

I've yet to find an RSS reader with a user experience I like, but this one is tolerable enough that I don't think "I should really find a replacement for this" every time I use it like I did when I was using Whatever Nextcloud Has™, plus it supports a couple common APIs so I can replace the frontend if I decide I hate it.

-

Speaking of which, I'm currently using a mobile app called Capy Reader to access this on my phone since the mobile web UI kind of sucks.

-
-

rss-bridge

Extracts RSS feeds from a genuinely kind of shocking number of websites that don't otherwise have them. I make generous use of this. Feel free to use my instance if you want.

@@ -90,6 +83,12 @@

Nepenthes

A tarpit for AI scrapers. Self-explanatory at this point.

+ +
+

Crafty Controller

+

A convenient admin panel for my Minecraft server(s). It's easier than administrating the servers manually, which for something as trivial as a Minecraft server is saying something.

+

I used to run this on the beefier server in my house, but when I was most recently called upon to spin up a minecraft server I was faced with the choice between finally setting up WireGuard again and just accepting the potentially slower performance of the cloud server, this is what I picked.

+
diff --git a/uses/servy586/index.php b/uses/servy586/index.php index 899752e..b0b39f6 100644 --- a/uses/servy586/index.php +++ b/uses/servy586/index.php @@ -115,7 +115,7 @@

OS - TrueNAS Scale

-

I could probably recreate my elaborate configuration on like, baseline debian or something, but I don't want to. Between four ZFS pools, virtual machines, a slightly convoluted system of SMB shares, and various other services, the slick web GUI TrueNAS provides makes everything far more convenient. Its configuration export feature was also very handy when migrating to the new machine.

+

I could probably recreate my elaborate configuration on like, baseline debian or something, but I don't want to. Between four ZFS pools, virtual machines, a slightly convoluted system of file shares, and various other services, the slick web GUI TrueNAS provides makes everything far more convenient. Its configuration export feature was also very handy when migrating to the new machine.

It's got some idiosyncracies to it, but in general TrueNAS smooths out the experience of running this server enough that I'm doing a lot of things I probably couldn't be bothered to otherwise.

@@ -140,6 +140,19 @@
+

Tailscale

+

A "mesh VPN", whatever that means. In practice, Tailscale lets me connect to any of my devices from any other as though they're sharing a local LAN. You know, the thing VPNs are actually for. Half the stuff on this server is only worth running because Tailscale lets me access it away from my house LAN, especially now that I'm routinely bringing a computer outside the house with me for school.

+
+ +
+

FreshRSS

+

I ended up with this because I elected to ditch Nextcloud in the process of migrating hosting providers, and this was the first RSS reader that I managed to get working post cloud provider migration. I swear, it's like the RSS 2.0 spec states that your self-hosted RSS reader has to have installation instructions that don't work.

+

This used to be on the cloud server, but then a "turn your shit off NOW until you can update" level vuln was discovered in every PHP version released in the past 14 years and I could think of no undertaking more nightmarish than trying to manually set this thing up again. Fortunately, since the last time I deployed an RSS reader I had set up Tailscale on my TrueNAS box, so I could just put it there and both mitigate the vulnerability and offload my self-hosted RSS reader curse to the machines in one fell swoop. Nice!

+

I've yet to find an RSS reader with a user experience I like, but this one is tolerable enough that I don't think "I should really find a replacement for this" every time I use it like I did when I was using Whatever Nextcloud Has™, plus it supports a couple common APIs so I can replace the frontend if I decide I hate it.

+

Speaking of which, I'm currently using a mobile app called Capy Reader to access this on my phone since the mobile web UI kind of sucks.

+
+ + -- cgit v1.2.3