"sha256-ko4j5rn874LF8dHwW29/xabhh8YBleWfvxb8nQce4Fc=", "coy" => "sha256-gkHLZLptZZHaBY+jqrRkAVzOGfMa4HBhSCJteem8wy8=", "dark" => "sha256-l+VX6V333ll/PXrjqG1W6DyZvDEw+50M7aAP6dcD7Qc=", "funky" => "sha256-l9GTgvTMmAvPQ6IlNCd/I2FQwXVlJCLbGId7z6QlOpo=", "okaidia" => "sha256-zzHVEO0xOoVm0I6bT9v5SgpRs1cYNyvEvHXW/1yCgqU=", "solarizedlight" => "sha256-Lr49DyE+/KstnLdBxqZBoDYgNi6ONfZyAZw3LDhxB9I=", "tomorrow" => "sha256-GxX+KXGZigSK67YPJvbu12EiBx257zuZWr0AMiT1Kpg=", "twilight" => "sha256-R7PF7y9XAuz19FB93NgH/WQUVGk30iytl7EwtETrypo=" ]; /** * The theme */ const CONF_PRISM_THEME = "prismTheme"; const PRISM_THEME_DEFAULT = "tomorrow"; const SNIPPET_ID_AUTOLOADER = self::SNIPPET_NAME . "-autoloader"; /** * * @param $theme * * Ter info: The theme of the default wiki is in the print.css file (search for code blocks) */ public static function addSnippet($theme) { $BASE_PRISM_CDN = self::BASE_PRISM_CDN; if ($theme == self::PRISM_THEME) { $themeStyleSheet = "prism.min.css"; } else { $themeStyleSheet = "prism-$theme.min.css"; } $themeIntegrity = self::THEMES_INTEGRITY[$theme]; /** * We miss a bottom margin * as a paragraph */ $snippetManager = PluginUtility::getSnippetManager(); $snippetManager->attachCssInternalStyleSheet(self::SNIPPET_NAME); /** * Javascript */ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/components/prism-core.min.js", "sha256-vlRYHThwdq55dA+n1BKQRzzLwFtH9VINdSI68+5JhpU="); $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/toolbar/prism-toolbar.min.js", "sha256-FyIVdIHL0+ppj4Q4Ft05K3wyCsYikpHIDGI7dcaBalU=" ); $snippetManager->attachRemoteCssStyleSheet( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/toolbar/prism-toolbar.css", "sha256-kK4/JIYJUKI4Zdg9ZQ7FYyRIqeWPfYKi5QZHO2n/lJI=" ); // https://prismjs.com/plugins/normalize-whitespace/ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/normalize-whitespace/prism-normalize-whitespace.min.js", "sha256-gBzABGbXfQYYnyr8xmDFjx6KGO9dBYuypG1QBjO76pY="); // https://prismjs.com/plugins/copy-to-clipboard/ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js", "sha512-pUNGXbOrc+Y3dm5z2ZN7JYQ/2Tq0jppMDOUsN4sQHVJ9AUQpaeERCUfYYBAnaRB9r8d4gtPKMWICNhm3tRr4Fg=="); // https://prismjs.com/plugins/show-language/ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/show-language/prism-show-language.min.js", "sha256-Z3GTw2RIadLG7KyP/OYB+aAxVYzvg2PByKzYrJlA1EM="); // https://prismjs.com/plugins/command-line/ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/command-line/prism-command-line.min.js", "sha256-9WlakH0Upf3N8DDteHlbeKCHxSsljby+G9ucUCQNiU0="); $snippetManager->attachRemoteCssStyleSheet( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/command-line/prism-command-line.css", "sha256-UvoA9bIYCYQkCMTYG5p2LM8ZpJmnC4G8k0oIc89nuQA=" ); //https://prismjs.com/plugins/line-numbers/ $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/line-numbers/prism-line-numbers.min.js", "sha256-K837BwIyiXo5k/9fCYgqUyA14bN4/Ve9P2SIT0KmZD0="); $snippetManager->attachRemoteCssStyleSheet( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/line-numbers/prism-line-numbers.css", "sha256-ye8BkHf2lHXUtqZ18U0KI3xjJ1Yv7P8lvdKBt9xmVJM=" ); // https://prismjs.com/plugins/download-button/--> $snippetManager->attachRemoteJavascriptLibrary( self::SNIPPET_NAME, "$BASE_PRISM_CDN/plugins/download-button/prism-download-button.min.js", "sha256-CQyVQ5ejeTshlzOS/eCiry40br9f4fQ9jb5e4qPl7ZA="); // Loading the theme $snippetManager->attachRemoteCssStyleSheet( self::SNIPPET_NAME, "$BASE_PRISM_CDN/themes/$themeStyleSheet", $themeIntegrity ); $javascriptCode = << { Prism.plugins.NormalizeWhitespace.setDefaults({ 'remove-trailing': true, 'remove-indent': true, 'left-trim': true, 'right-trim': true, }); }); EOD; $snippetManager->attachJavascriptFromComponentId(self::SNIPPET_NAME, $javascriptCode); } /** * Add the first block of prism * @param \Doku_Renderer_xhtml $renderer * @param TagAttributes $attributes * @param \DokuWiki_Syntax_Plugin $plugin */ public static function htmlEnter(\Doku_Renderer_xhtml $renderer, \DokuWiki_Syntax_Plugin $plugin, $attributes = null) { if ($attributes == null) { $attributes = TagAttributes::createEmpty(); } /** * Display none, no rendering */ $display = $attributes->getValueAndRemove("display"); if ($display != null) { if ($display == "none") { return; } } /** * Add prism theme */ $theme = $plugin->getConf(Prism::CONF_PRISM_THEME,Prism::PRISM_THEME_DEFAULT); Prism::addSnippet($theme); /** * Logical tag */ $logicalTag = $plugin->getPluginComponent(); if ($attributes->getLogicalTag() != null) { $logicalTag = $attributes->getLogicalTag(); } // for the https://combostrap.com/styling/userstyle $attributes->setLogicalTag($logicalTag . "-container"); /** * The child element (code) of the `pre` element * The container is the passed `attributes` * We can then constrained in height ... * It contains the language */ $codeAttributes = TagAttributes::createEmpty($logicalTag); $codeAttributes->setType($attributes->getType()); $language = $attributes->getValue(TagAttributes::TYPE_KEY); if ($language == null) { // Prism does not have any default language // There is a bug has it tried to download the txt javascript // but without language, there is no styling $language = "txt"; } else { $language = strtolower($language); Prism::addAutoloaderSnippet(); } if (in_array($language, Tag\WebCodeTag::MARKIS)) { // Marki is not fully markdown // because it accepts space in super set html container and // prism will highlight them as indented code $language = "html"; } /** * Language name mapping between the syntax name and prism */ switch ($language) { case "rsplus": $language = "r"; break; case "dos": case "bat": $language = "batch"; break; case "grok": $language = "regex"; break; case "jinja": // https://github.com/PrismJS/prism/issues/759 $language = "twig"; break; case "apache": $language = "apacheconf"; break; case "babel": $language = "jsx"; break; case "antlr": $language = "g4"; break; } StringUtility::addEolCharacterIfNotPresent($renderer->doc); $codeAttributes->addClassName('language-' . $language); /** * Code element * Don't put a fucking EOL after it * Otherwise it fucked up the output as the text below a code tag is printed */ $codeHtml = $codeAttributes->toHtmlEnterTag('code'); $attributes->addHtmlAfterEnterTag($codeHtml); /** * Pre Element * Line numbers */ if ($attributes->hasComponentAttribute("line-numbers")) { $attributes->removeComponentAttribute("line-numbers"); $attributes->addClassName('line-numbers'); } // Command line if ($attributes->hasComponentAttribute("prompt")) { $attributes->addClassName("command-line"); $attributes->addOutputAttributeValue("data-prompt", $attributes->getValueAndRemove("prompt")); } else { switch ($language) { case "bash": $attributes->addClassName("command-line"); $attributes->addOutputAttributeValue("data-prompt", $plugin->getConf(self::CONF_BASH_PROMPT)); break; case "batch": $attributes->addClassName("command-line"); $batch = trim($plugin->getConf(self::CONF_BATCH_PROMPT)); if (!empty($batch)) { if (!strpos($batch, -1) == ">") { $batch .= ">"; } } $attributes->addOutputAttributeValue("data-prompt", $batch); break; case "powershell": $attributes->addClassName("command-line"); $powerShell = trim($plugin->getConf(self::CONF_POWERSHELL_PROMPT)); if (!empty($powerShell)) { if (!strpos($powerShell, -1) == ">") { $powerShell .= ">"; } } $attributes->addOutputAttributeValue("data-prompt", $powerShell); break; } } // Download $attributes->addOutputAttributeValue('data-download-link', true); if ($attributes->hasComponentAttribute(syntax_plugin_combo_code::FILE_PATH_KEY)) { $fileSrc = $attributes->getValueAndRemove(syntax_plugin_combo_code::FILE_PATH_KEY); $attributes->addOutputAttributeValue('data-src', $fileSrc); $attributes->addOutputAttributeValue('data-download-link-label', "Download " . $fileSrc); } else { $fileName = "file." . $language; $attributes->addOutputAttributeValue('data-src', $fileName); } /** * No end of line after the pre, please, otherwise we get a new line * in the code output */ $htmlCode = $attributes->toHtmlEnterTag("pre"); /** * Return */ $renderer->doc .= $htmlCode; } /** * @param Doku_Renderer_xhtml $renderer * @param TagAttributes $attributes */ public static function htmlExit(\Doku_Renderer_xhtml $renderer, $attributes = null) { if ($attributes != null) { /** * Display none, no rendering */ $display = $attributes->getValueAndRemove("display"); if ($display != null) { if ($display == "none") { return; } } } $renderer->doc .= '' . DOKU_LF . '' . DOKU_LF; } /** * The autoloader try to download all language * Even the one such as txt that does not exist * This function was created to add it conditionally */ private static function addAutoloaderSnippet() { PluginUtility::getSnippetManager() ->attachRemoteJavascriptLibrary( self::SNIPPET_ID_AUTOLOADER, self::BASE_PRISM_CDN . "/plugins/autoloader/prism-autoloader.min.js" ); } }