From c1e6ae947adf7ba4a5f6c1f59d14d1a0dc39230c Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 14 Feb 2025 18:14:13 +0100 Subject: [PATCH 01/11] Add codeblocks --- docs/syntax/code.md | 72 +++++++++++++++++-- src/Elastic.Markdown/Assets/markdown/code.css | 57 +++++++++++++++ src/Elastic.Markdown/Assets/styles.css | 1 + 3 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 src/Elastic.Markdown/Assets/markdown/code.css diff --git a/docs/syntax/code.md b/docs/syntax/code.md index 8c3e2d920..07ef99e41 100644 --- a/docs/syntax/code.md +++ b/docs/syntax/code.md @@ -2,10 +2,15 @@ Code blocks can be used to display multiple lines of code. They preserve formatting and provide syntax highlighting when possible. -## Syntax +## Basic Start and end a code block with a code fence. A code fence is a sequence of at least three consecutive backtick characters (~```~). You can optionally add a language identifier to enable syntax highlighting. + +::::{tab-set} + +:::{tab-item} Markdown + ````markdown ```yaml project: @@ -14,22 +19,35 @@ project: ``` ```` +::: + +:::{tab-item} Output + ```yaml project: title: MyST Markdown github: https://github.com/jupyter-book/mystmd ``` -### Code callouts +::: + +:::: + +## Code callouts There are two ways to add callouts to a code block. When using callouts, you must use one callout format. You cannot combine explicit and magic callouts. -#### Explicit callouts +### Explicit callouts Add `<\d+>` to the end of a line to explicitly create a code callout. An ordered list with the same number of items as callouts must follow the code block. If the number of list items doesn’t match the callouts, docs-builder will throw an error. + +::::{tab-set} + +:::{tab-item} Markdown + ````markdown ```yaml project: @@ -40,6 +58,10 @@ project: 1. The license ```` +::: + +:::{tab-item} Output + ```yaml project: license: @@ -48,11 +70,21 @@ project: 1. The license +::: + -#### Magic Callouts +:::: + + +### Magic Callouts If a code block contains code comments in the form of `//` or `#`, callouts will be magically created 🪄. + +::::{tab-set} + +:::{tab-item} Markdown + ````markdown ```csharp var apiKey = new ApiKey(""); // Set up the api key @@ -60,13 +92,25 @@ var client = new ElasticsearchClient("", apiKey); ``` ```` +::: + +:::{tab-item} Output + ```csharp var apiKey = new ApiKey(""); // Set up the api key var client = new ElasticsearchClient("", apiKey); ``` +::: + +:::: + Code comments must follow code to be hoisted as a callout. For example: +::::{tab-set} + +:::{tab-item} Markdown + ````markdown ```csharp // THIS IS NOT A CALLOUT @@ -75,12 +119,19 @@ var client = new ElasticsearchClient("", apiKey); ``` ```` +::: + +:::{tab-item} Output + ```csharp // THIS IS NOT A CALLOUT var apiKey = new ApiKey(""); // This is a callout var client = new ElasticsearchClient("", apiKey); ``` +::: + +:::: ## Console code blocks @@ -92,6 +143,10 @@ We document a lot of API endpoints at Elastic. For these endpoints, we support ` In a console code block, the first line is highlighted as a dev console string and the remainder as json: +::::{tab-set} + +:::{tab-item} Markdown + ````markdown ```console GET /mydocuments/_search @@ -104,6 +159,11 @@ GET /mydocuments/_search ``` ```` +::: + +:::{tab-item} Output + + ```console GET /mydocuments/_search { @@ -113,3 +173,7 @@ GET /mydocuments/_search } } ``` + +::: + +:::: diff --git a/src/Elastic.Markdown/Assets/markdown/code.css b/src/Elastic.Markdown/Assets/markdown/code.css new file mode 100644 index 000000000..02f17d961 --- /dev/null +++ b/src/Elastic.Markdown/Assets/markdown/code.css @@ -0,0 +1,57 @@ +@layer components { + .markdown-content { + + pre { + @apply grid mb-6; + code { + @apply text-sm; + } + code:first-child { + @apply rounded-t-sm; + } + code:last-child { + @apply rounded-b-sm; + } + code.language-apiheader { + @apply border-b-1 border-b-gray-700; + } + } + + pre code .code-callout { + &>.hljs-number { + @apply text-white!; + } + transform: translateY(-1px); + user-select: none; + } + } + + ol.code-callouts { + li { + @apply relative pl-1; + counter-increment: code-callout-counter; + list-style-type: none; + } + + li::before { + content: counter(code-callout-counter); + position: absolute; + top: 1px; + left: calc(-1 * var(--spacing) * 6); + } + } + + pre code .code-callout, + ol.code-callouts li::before { + @apply text-xs! + text-white + font-mono + bg-blue-elastic + rounded-full + size-5 + inline-flex + justify-center + items-center + ; + } +} diff --git a/src/Elastic.Markdown/Assets/styles.css b/src/Elastic.Markdown/Assets/styles.css index ebf9d0200..821de7632 100644 --- a/src/Elastic.Markdown/Assets/styles.css +++ b/src/Elastic.Markdown/Assets/styles.css @@ -5,6 +5,7 @@ @import "./markdown/typography.css"; @import "./markdown/list.css"; @import "./markdown/tabs.css"; +@import "./markdown/code.css"; #default-search::-webkit-search-cancel-button { padding-right: calc(var(--spacing) * 2); From 2feea2b5cefe5740e1590c15088c13c4803dbc22 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Sat, 15 Feb 2025 01:21:25 +0100 Subject: [PATCH 02/11] Add copy button and fine-tune typography --- docs/contribute/move.md | 6 +- docs/syntax/code.md | 103 +++++-- src/Elastic.Markdown/Assets/copybutton.css | 98 +++++++ src/Elastic.Markdown/Assets/copybutton.ts | 261 ++++++++++++++++++ src/Elastic.Markdown/Assets/main.ts | 2 + src/Elastic.Markdown/Assets/markdown/code.css | 41 ++- src/Elastic.Markdown/Assets/markdown/list.css | 4 +- src/Elastic.Markdown/Assets/markdown/tabs.css | 4 +- .../Assets/markdown/typography.css | 18 +- src/Elastic.Markdown/Assets/styles.css | 3 +- src/Elastic.Markdown/package-lock.json | 39 +++ src/Elastic.Markdown/package.json | 1 + 12 files changed, 525 insertions(+), 55 deletions(-) create mode 100644 src/Elastic.Markdown/Assets/copybutton.css create mode 100644 src/Elastic.Markdown/Assets/copybutton.ts diff --git a/docs/contribute/move.md b/docs/contribute/move.md index fdebd5784..4277227e5 100644 --- a/docs/contribute/move.md +++ b/docs/contribute/move.md @@ -6,7 +6,7 @@ When you move a source file or folder, you must also update all inbound and outb Move a file or folder from one location to another and update all links in the documentation. For example: -``` +```bash docs-builder mv ./old-location/ia.md ./new-location/ia.md ``` @@ -16,7 +16,7 @@ The `docset.yml` and `toc.yml` files are not automatically updated when using th ## `docs-builder mv --help` -``` +```bash Usage: mv [arguments...] [options...] [-h|--help] [--version] Move a file or folder from one location to another and update all links in the documentation @@ -28,4 +28,4 @@ Arguments: Options: --dry-run Dry run the move operation (Default: null) -p|--path Defaults to the`{pwd}` folder (Default: null) -``` \ No newline at end of file +``` diff --git a/docs/syntax/code.md b/docs/syntax/code.md index 07ef99e41..eb88dfad3 100644 --- a/docs/syntax/code.md +++ b/docs/syntax/code.md @@ -1,43 +1,43 @@ -# Code blocks +# Code Code blocks can be used to display multiple lines of code. They preserve formatting and provide syntax highlighting when possible. -## Basic +## Code block -Start and end a code block with a code fence. A code fence is a sequence of at least three consecutive backtick characters (~```~). You can optionally add a language identifier to enable syntax highlighting. +Start and end a code block with a code fence. A code fence is a sequence of at least three consecutive backtick characters `` ``` ``. You can optionally add a language identifier to enable syntax highlighting. ::::{tab-set} -:::{tab-item} Markdown +:::{tab-item} Output -````markdown ```yaml project: title: MyST Markdown github: https://github.com/jupyter-book/mystmd ``` -```` ::: -:::{tab-item} Output +:::{tab-item} Markdown +````markdown ```yaml project: title: MyST Markdown github: https://github.com/jupyter-book/mystmd ``` +```` ::: :::: -## Code callouts +### Code callouts There are two ways to add callouts to a code block. When using callouts, you must use one callout format. You cannot combine explicit and magic callouts. -### Explicit callouts +#### Explicit callouts Add `<\d+>` to the end of a line to explicitly create a code callout. @@ -46,9 +46,8 @@ An ordered list with the same number of items as callouts must follow the code b ::::{tab-set} -:::{tab-item} Markdown +:::{tab-item} Output -````markdown ```yaml project: license: @@ -56,12 +55,13 @@ project: ``` 1. The license -```` ::: -:::{tab-item} Output +:::{tab-item} Markdown + +````markdown ```yaml project: license: @@ -69,71 +69,71 @@ project: ``` 1. The license +```` ::: - :::: -### Magic Callouts +#### Magic Callouts If a code block contains code comments in the form of `//` or `#`, callouts will be magically created 🪄. ::::{tab-set} -:::{tab-item} Markdown +:::{tab-item} Output -````markdown ```csharp var apiKey = new ApiKey(""); // Set up the api key var client = new ElasticsearchClient("", apiKey); ``` -```` ::: -:::{tab-item} Output +:::{tab-item} Markdown +````markdown ```csharp var apiKey = new ApiKey(""); // Set up the api key var client = new ElasticsearchClient("", apiKey); ``` - +```` ::: + :::: Code comments must follow code to be hoisted as a callout. For example: ::::{tab-set} -:::{tab-item} Markdown +:::{tab-item} Output -````markdown ```csharp // THIS IS NOT A CALLOUT var apiKey = new ApiKey(""); // This is a callout var client = new ElasticsearchClient("", apiKey); ``` -```` ::: -:::{tab-item} Output +:::{tab-item} Markdown +````markdown ```csharp // THIS IS NOT A CALLOUT var apiKey = new ApiKey(""); // This is a callout var client = new ElasticsearchClient("", apiKey); ``` +```` ::: :::: -## Console code blocks +### Console code blocks :::{note} This feature is still being developed. @@ -145,9 +145,8 @@ In a console code block, the first line is highlighted as a dev console string a ::::{tab-set} -:::{tab-item} Markdown +:::{tab-item} Output -````markdown ```console GET /mydocuments/_search { @@ -157,13 +156,12 @@ GET /mydocuments/_search } } ``` -```` ::: -:::{tab-item} Output - +:::{tab-item} Markdown +````markdown ```console GET /mydocuments/_search { @@ -173,7 +171,52 @@ GET /mydocuments/_search } } ``` +```` + +::: + +:::: + +## Inline code + +Use backticks to create an inline code span. +Inline code spans are useful for short code snippets or variable names. + + +### Inline code in a paragraph + +::::{tab-set} + +:::{tab-item} Output + +This `code` is inline. + +::: +:::{tab-item} Markdown + +````markdown +This `code` is inline. +```` +::: + +:::: + +### Inline code in a heading + +::::{tab-set} + +:::{tab-item} Output + +## This `code` is in a heading. + +::: + +:::{tab-item} Markdown + +````markdown +## This `code` is in a heading. +```` ::: :::: diff --git a/src/Elastic.Markdown/Assets/copybutton.css b/src/Elastic.Markdown/Assets/copybutton.css new file mode 100644 index 000000000..316c769da --- /dev/null +++ b/src/Elastic.Markdown/Assets/copybutton.css @@ -0,0 +1,98 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + cursor: pointer; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + /*background-color: #f6f8fa;*/ + color: var(--color-gray-400); +} + +button.copybtn.success { + /*border-color: #22863a;*/ + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + /*background-color: rgb(235, 235, 235);*/ +} + +.highlight button.copybtn:active { + /*background-color: rgb(187, 187, 187);*/ +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left.success:after { + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + /*background: grey;*/ + color: var(--color-gray-400); + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/src/Elastic.Markdown/Assets/copybutton.ts b/src/Elastic.Markdown/Assets/copybutton.ts new file mode 100644 index 000000000..35cb8da22 --- /dev/null +++ b/src/Elastic.Markdown/Assets/copybutton.ts @@ -0,0 +1,261 @@ +// Localization support + +import * as ClipboardJS from 'clipboard' + +const DOCUMENTATION_OPTIONS = { + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; + +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 1500; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string[]} excludes CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, excludes) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + excludes.forEach(exclude => { + clone.querySelectorAll(excludes).forEach(node => node.remove()); + }) + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + // get filtered text + let excludes = ['.code-callout', '.linenos', '.language-apiheader']; + let text = filterText(target, excludes); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +export function initCopyButton() { + console.log("initCopyButton"); + runWhenDOMLoaded(addCopyButtonToCodeCells) +} diff --git a/src/Elastic.Markdown/Assets/main.ts b/src/Elastic.Markdown/Assets/main.ts index b3078f6b7..610380ca1 100644 --- a/src/Elastic.Markdown/Assets/main.ts +++ b/src/Elastic.Markdown/Assets/main.ts @@ -2,8 +2,10 @@ import {initNav} from "./pages-nav"; import {initTocNav} from "./toc-nav"; import {initHighlight} from "./hljs"; import {initTabs} from "./tabs"; +import {initCopyButton} from "./copybutton"; initNav(); initTocNav(); initHighlight(); +initCopyButton(); initTabs(); diff --git a/src/Elastic.Markdown/Assets/markdown/code.css b/src/Elastic.Markdown/Assets/markdown/code.css index 02f17d961..9e88def91 100644 --- a/src/Elastic.Markdown/Assets/markdown/code.css +++ b/src/Elastic.Markdown/Assets/markdown/code.css @@ -1,10 +1,21 @@ @layer components { .markdown-content { + + .highlight { + @apply mt-6; + } + pre { - @apply grid mb-6; + @apply grid; code { - @apply text-sm; + @apply text-sm + text-gray-100 + bg-blue-developer + rounded-none + border-0 + p-6! + ; } code:first-child { @apply rounded-t-sm; @@ -17,10 +28,7 @@ } } - pre code .code-callout { - &>.hljs-number { - @apply text-white!; - } + pre code .code-callout .hljs-number { transform: translateY(-1px); user-select: none; } @@ -41,10 +49,10 @@ } } - pre code .code-callout, + pre code .code-callout .hljs-number, ol.code-callouts li::before { @apply text-xs! - text-white + text-white! font-mono bg-blue-elastic rounded-full @@ -54,4 +62,21 @@ items-center ; } + + code { + @apply font-mono + bg-gray-100 + rounded-xs + border-1 + border-gray-200 + inline-block + ; + font-size: 0.875em; + line-height: 1.4em; + padding-left: 0.2em; + padding-right: 0.2em; + letter-spacing: 0.02em; + text-decoration: inherit; + font-weight: inherit; + } } diff --git a/src/Elastic.Markdown/Assets/markdown/list.css b/src/Elastic.Markdown/Assets/markdown/list.css index e993a59df..bdc4e39b3 100644 --- a/src/Elastic.Markdown/Assets/markdown/list.css +++ b/src/Elastic.Markdown/Assets/markdown/list.css @@ -1,7 +1,7 @@ .markdown-content { ol,ul { font-family: "Inter", sans-serif; - @apply text-base text-body mb-6; + @apply text-base text-body mt-6; line-height: 1.5em; letter-spacing: 0; margin-left: 1.5em; @@ -16,7 +16,7 @@ } li { - margin-bottom: calc(var(--spacing) * 3); + @apply first:mt-0 mt-2; p { margin-bottom: 0; diff --git a/src/Elastic.Markdown/Assets/markdown/tabs.css b/src/Elastic.Markdown/Assets/markdown/tabs.css index b35c71c93..751386747 100644 --- a/src/Elastic.Markdown/Assets/markdown/tabs.css +++ b/src/Elastic.Markdown/Assets/markdown/tabs.css @@ -1,6 +1,6 @@ @layer components { .tabs { - @apply flex flex-wrap relative overflow-hidden; + @apply flex flex-wrap relative overflow-hidden mt-6; .tabs-label { @apply cursor-pointer px-6 py-2 z-20 text-ink-light flex items-center; @@ -15,7 +15,7 @@ } .tabs-content { - @apply w-full order-99 border-t-1 border-gray-300 px-6 pt-4 z-0 hidden; + @apply w-full order-99 border-t-1 border-gray-300 px-6 z-0 hidden; transform: translateY(-1px); } diff --git a/src/Elastic.Markdown/Assets/markdown/typography.css b/src/Elastic.Markdown/Assets/markdown/typography.css index 806fc68d4..cd55cae33 100644 --- a/src/Elastic.Markdown/Assets/markdown/typography.css +++ b/src/Elastic.Markdown/Assets/markdown/typography.css @@ -4,42 +4,42 @@ h1 { font-family: "Mier B", "Inter", sans-serif; - @apply text-5xl text-black mb-6 mt-5; + @apply text-4xl text-black font-semibold; line-height: 1.2em; letter-spacing: -0.04em; } h2 { font-family: "Mier B", "Inter", sans-serif; - @apply text-4xl text-black mb-6 mt-8; + @apply text-2xl text-black font-bold mt-10; line-height: 1.2em; - letter-spacing: -0.04em; + letter-spacing: -0.02em; } h3 { font-family: "Mier B", "Inter", sans-serif; - @apply text-2xl text-black mb-6 mt-6; + @apply text-xl text-black font-bold mt-6; line-height: 1.2em; letter-spacing: -0.02em; } h4 { font-family: "Mier B", "Inter", sans-serif; - @apply text-base text-black font-bold mb-5 mt-5; + @apply text-base text-black font-bold mt-4; line-height: 1.2em; letter-spacing: -0.02em; } h5 { font-family: "Mier B", "Inter", sans-serif; - @apply text-sm text-black font-bold mb-4 mt-5; + @apply text-sm text-black font-bold mt-4; line-height: 1.2em; letter-spacing: -0.02em; } h6 { font-family: "Mier B", "Inter", sans-serif; - @apply text-xs text-black font-bold mb-3 mt-3; + @apply text-xs text-black font-bold mt-4; line-height: 1.2em; letter-spacing: -0.02em; } @@ -53,9 +53,9 @@ p { font-family: "Inter", sans-serif; - @apply text-base text-ink text-body mb-6; - line-height: 1.5em; + @apply text-base text-ink mt-4; letter-spacing: 0; + line-height: 1.5em; } a { diff --git a/src/Elastic.Markdown/Assets/styles.css b/src/Elastic.Markdown/Assets/styles.css index 821de7632..4a11e7a5a 100644 --- a/src/Elastic.Markdown/Assets/styles.css +++ b/src/Elastic.Markdown/Assets/styles.css @@ -1,11 +1,12 @@ @import "tailwindcss"; @import "./fonts.css"; @import "./theme.css"; -@import "highlight.js/styles/atom-one-dark.css"; +@import "highlight.js/styles/base16/material-palenight.css"; @import "./markdown/typography.css"; @import "./markdown/list.css"; @import "./markdown/tabs.css"; @import "./markdown/code.css"; +@import "./copybutton.css"; #default-search::-webkit-search-cancel-button { padding-right: calc(var(--spacing) * 2); diff --git a/src/Elastic.Markdown/package-lock.json b/src/Elastic.Markdown/package-lock.json index ba2c40113..cace881b3 100644 --- a/src/Elastic.Markdown/package-lock.json +++ b/src/Elastic.Markdown/package-lock.json @@ -8,6 +8,7 @@ "name": "elastic-markdown", "version": "1.0.0", "dependencies": { + "clipboard": "^2.0.11", "highlight.js": "^11.11.1", "select-dom": "^9.3.0", "tailwindcss": "^4.0.3" @@ -2260,6 +2261,17 @@ "node": ">=6.0" } }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "license": "MIT", + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -2526,6 +2538,12 @@ "optional": true, "peer": true }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "license": "MIT" + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -2723,6 +2741,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "license": "MIT", + "dependencies": { + "delegate": "^3.1.2" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4291,6 +4318,12 @@ } ] }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "license": "MIT" + }, "node_modules/select-dom": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/select-dom/-/select-dom-9.3.0.tgz", @@ -4467,6 +4500,12 @@ "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", "dev": true }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/src/Elastic.Markdown/package.json b/src/Elastic.Markdown/package.json index 4ac66c0d5..e517b0cd4 100644 --- a/src/Elastic.Markdown/package.json +++ b/src/Elastic.Markdown/package.json @@ -33,6 +33,7 @@ "defaults" ], "dependencies": { + "clipboard": "^2.0.11", "highlight.js": "^11.11.1", "select-dom": "^9.3.0", "tailwindcss": "^4.0.3" From f028ab822b53d1871091cf5e90384f990ba404d1 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Sat, 15 Feb 2025 01:46:34 +0100 Subject: [PATCH 03/11] fine-tuning --- .../guide/how-to-set-up-docs-previews.md | 15 +++++++++++---- src/Elastic.Markdown/Assets/markdown/code.css | 5 +++-- src/Elastic.Markdown/Assets/markdown/tabs.css | 2 +- .../Assets/markdown/typography.css | 16 +++++++++------- src/Elastic.Markdown/Assets/styles.css | 2 +- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/docs/migration/guide/how-to-set-up-docs-previews.md b/docs/migration/guide/how-to-set-up-docs-previews.md index 167168eb3..fd5273038 100644 --- a/docs/migration/guide/how-to-set-up-docs-previews.md +++ b/docs/migration/guide/how-to-set-up-docs-previews.md @@ -16,8 +16,9 @@ If the `path-pattern` input does not match any changes in the PR, the workflow w This way you only build and deploy the docs when there are changes to the docs and you can still set it as a required status check. -::::{dropdown} .github/workflows/docs-build.yml -:open: +::::{tab-set} + +:::{tab-item} .github/workflows/docs-build.yml ```yaml --- @@ -45,6 +46,8 @@ jobs: 2. Reusable workflow: [elastic/docs-builder/.github/workflows/preview-build.yml](https://github.com/elastic/docs-builder/blob/main/.github/workflows/preview-build.yml) 3. his should be the path to your docs folder. +::: + :::: @@ -57,8 +60,10 @@ We are aware of the security implications of using `pull_request_target` as desc The workflow never checks out the code and doesn't use any user modifiable inputs (e.g. PR title). ::: -::::{dropdown} .github/workflows/docs-cleanup.yml -:open: +::::{tab-set} + +:::{tab-item} .github/workflows/docs-cleanup.yml + ```yaml --- name: docs-cleanup @@ -80,6 +85,8 @@ jobs: 1. Reusable workflow: [elastic/docs-builder/.github/workflows/preview-cleanup.yml](https://github.com/elastic/docs-builder/blob/main/.github/workflows/preview-cleanup.yml) 2. No permissions to read content +::: + :::: ## Required Status Checks diff --git a/src/Elastic.Markdown/Assets/markdown/code.css b/src/Elastic.Markdown/Assets/markdown/code.css index 9e88def91..c12e4e7c9 100644 --- a/src/Elastic.Markdown/Assets/markdown/code.css +++ b/src/Elastic.Markdown/Assets/markdown/code.css @@ -3,7 +3,7 @@ .highlight { - @apply mt-6; + @apply mt-4; } pre { @@ -11,11 +11,11 @@ code { @apply text-sm text-gray-100 - bg-blue-developer rounded-none border-0 p-6! ; + background-color: #22272e; } code:first-child { @apply rounded-t-sm; @@ -78,5 +78,6 @@ letter-spacing: 0.02em; text-decoration: inherit; font-weight: inherit; + text-wrap: nowrap; } } diff --git a/src/Elastic.Markdown/Assets/markdown/tabs.css b/src/Elastic.Markdown/Assets/markdown/tabs.css index 751386747..8129f013f 100644 --- a/src/Elastic.Markdown/Assets/markdown/tabs.css +++ b/src/Elastic.Markdown/Assets/markdown/tabs.css @@ -1,6 +1,6 @@ @layer components { .tabs { - @apply flex flex-wrap relative overflow-hidden mt-6; + @apply flex flex-wrap relative overflow-hidden mt-4; .tabs-label { @apply cursor-pointer px-6 py-2 z-20 text-ink-light flex items-center; diff --git a/src/Elastic.Markdown/Assets/markdown/typography.css b/src/Elastic.Markdown/Assets/markdown/typography.css index cd55cae33..863ca365c 100644 --- a/src/Elastic.Markdown/Assets/markdown/typography.css +++ b/src/Elastic.Markdown/Assets/markdown/typography.css @@ -4,42 +4,42 @@ h1 { font-family: "Mier B", "Inter", sans-serif; - @apply text-4xl text-black font-semibold; + @apply text-4xl text-ink-dark font-semibold; line-height: 1.2em; letter-spacing: -0.04em; } h2 { font-family: "Mier B", "Inter", sans-serif; - @apply text-2xl text-black font-bold mt-10; + @apply text-2xl text-ink-dark font-bold mt-10; line-height: 1.2em; letter-spacing: -0.02em; } h3 { font-family: "Mier B", "Inter", sans-serif; - @apply text-xl text-black font-bold mt-6; + @apply text-xl text-ink-dark font-bold mt-8; line-height: 1.2em; letter-spacing: -0.02em; } h4 { font-family: "Mier B", "Inter", sans-serif; - @apply text-base text-black font-bold mt-4; + @apply text-base text-ink-dark font-bold mt-8; line-height: 1.2em; letter-spacing: -0.02em; } h5 { font-family: "Mier B", "Inter", sans-serif; - @apply text-sm text-black font-bold mt-4; + @apply text-sm text-ink-dark font-bold mt-8; line-height: 1.2em; letter-spacing: -0.02em; } h6 { font-family: "Mier B", "Inter", sans-serif; - @apply text-xs text-black font-bold mt-4; + @apply text-xs text-ink-dark font-bold mt-8; line-height: 1.2em; letter-spacing: -0.02em; } @@ -47,7 +47,7 @@ h1, h2, h3, h4, h5, h6 { a { font-family: "Mier B", "Inter", sans-serif; - @apply text-black hover:text-black no-underline; + @apply text-ink-dark hover:text-ink-dark no-underline; } } @@ -56,10 +56,12 @@ @apply text-base text-ink mt-4; letter-spacing: 0; line-height: 1.5em; + text-wrap: pretty; } a { font-family: "Inter", sans-serif; + text-wrap: nowrap; @apply text-blue-elastic hover:text-blue-800 underline; } } diff --git a/src/Elastic.Markdown/Assets/styles.css b/src/Elastic.Markdown/Assets/styles.css index 4a11e7a5a..bbe7ed99c 100644 --- a/src/Elastic.Markdown/Assets/styles.css +++ b/src/Elastic.Markdown/Assets/styles.css @@ -1,7 +1,7 @@ @import "tailwindcss"; @import "./fonts.css"; @import "./theme.css"; -@import "highlight.js/styles/base16/material-palenight.css"; +@import "highlight.js/styles/github-dark-dimmed.css"; @import "./markdown/typography.css"; @import "./markdown/list.css"; @import "./markdown/tabs.css"; From a422bff9cdbcc725664d39e39a3774ac3a759f5b Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Sun, 16 Feb 2025 21:23:10 +0100 Subject: [PATCH 04/11] wip --- docs/syntax/admonitions.md | 8 ++- .../Assets/markdown/admonition.css | 59 +++++++++++++++++++ src/Elastic.Markdown/Assets/styles.css | 1 + .../Slices/Directives/Admonition.cshtml | 33 ++++++++++- 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/Elastic.Markdown/Assets/markdown/admonition.css diff --git a/docs/syntax/admonitions.md b/docs/syntax/admonitions.md index 703f43008..289a15583 100644 --- a/docs/syntax/admonitions.md +++ b/docs/syntax/admonitions.md @@ -21,11 +21,17 @@ A relevant piece of information with no serious repercussions if ignored. :::{note} This is a note. It can span multiple lines and supports inline formatting. + +- List item 1 +- List item 2 +- List item 3 + ::: ``` :::{note} -This is a note. +This is a note. +It can span multiple lines and supports inline formatting. ::: ### Warning diff --git a/src/Elastic.Markdown/Assets/markdown/admonition.css b/src/Elastic.Markdown/Assets/markdown/admonition.css new file mode 100644 index 000000000..e0c09b55f --- /dev/null +++ b/src/Elastic.Markdown/Assets/markdown/admonition.css @@ -0,0 +1,59 @@ +@layer components { + .admonition { + @apply mt-4 border-l-4; + + .admonition-title { + @apply px-4 py-2 font-bold flex items-center gap-4 ; + svg { + @apply size-5; + } + } + .admonition-content { + @apply px-4 pb-1; + } + + &.note { + border-color: #61A2FF; + background-color: #E8F1FF; + .admonition-title { + background-color: #BFDBFF; + } + } + + &.tip { + @apply border-teal; + background-color: #E2F9F7; + + .admonition-title { + background-color: #C9F3F0; + } + } + + &.warning { + @apply border-pink; + background-color: #FFEBF5; + + .admonition-title { + background-color: #FDDDE9; + } + } + + &.important { + border-color: #B386F9; + background-color: #F3ECFE; + + .admonition-title { + background-color: #E2D3FE; + } + } + + &.plain { + border-color: #989FAA; + background-color: #F6F9FC; + + .admonition-title { + background-color: #D9DDE3; + } + } + } +} diff --git a/src/Elastic.Markdown/Assets/styles.css b/src/Elastic.Markdown/Assets/styles.css index bbe7ed99c..7c237e978 100644 --- a/src/Elastic.Markdown/Assets/styles.css +++ b/src/Elastic.Markdown/Assets/styles.css @@ -7,6 +7,7 @@ @import "./markdown/tabs.css"; @import "./markdown/code.css"; @import "./copybutton.css"; +@import "./markdown/admonition.css"; #default-search::-webkit-search-cancel-button { padding-right: calc(var(--spacing) * 2); diff --git a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml index ed70357a2..7fab89be2 100644 --- a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml @@ -1,5 +1,34 @@ @inherits RazorSlice
-

@Model.Title

- [CONTENT] +
+ + @switch (Model.Classes) + { + case "tip": + + + + break; + case "warning": + + + + break; + case "note": + + + + break; + + } + + @* *@ + @* *@ + @* *@ + @* *@ + @Model.Title +
+
+ [CONTENT] +
From 225bce520cbc14fa56855b01b2465b2e1e870376 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Sun, 16 Feb 2025 22:24:32 +0100 Subject: [PATCH 05/11] wip --- docs/syntax/admonitions.md | 100 ++++++++++++++---- .../Assets/markdown/admonition.css | 28 ++--- .../Slices/Directives/Admonition.cshtml | 47 ++++---- 3 files changed, 125 insertions(+), 50 deletions(-) diff --git a/docs/syntax/admonitions.md b/docs/syntax/admonitions.md index 289a15583..877c620be 100644 --- a/docs/syntax/admonitions.md +++ b/docs/syntax/admonitions.md @@ -7,88 +7,148 @@ Admonitions allow you to highlight important information with varying levels of Admonitions can span multiple lines and support inline formatting. Available admonition types include: -- Note -- Warning -- Tip -- Important -- Plain +- [Note](#note) +- [Warning](#warning) +- [Tip](#tip) +- [Important](#important) +- [Plain](#plain) ### Note A relevant piece of information with no serious repercussions if ignored. -```markdown + +:::::{tab-set} + +::::{tab-item} Output + :::{note} This is a note. It can span multiple lines and supports inline formatting. +::: -- List item 1 -- List item 2 -- List item 3 +:::: -::: -``` +::::{tab-item} Markdown +```markdown :::{note} -This is a note. +This is a note. It can span multiple lines and supports inline formatting. ::: +``` + +:::: + +::::: ### Warning You could permanently lose data or leak sensitive information. -```markdown +:::::{tab-set} + +::::{tab-item} Output + :::{warning} This is a warning. ::: -``` +:::: + +::::{tab-item} Markdown + +```markdown :::{warning} This is a warning. ::: +``` + +:::: + +::::: ### Tip Advice to help users make better choices when using a feature. -```markdown +You could permanently lose data or leak sensitive information. + +:::::{tab-set} + +::::{tab-item} Output + :::{tip} This is a tip. ::: -``` +:::: + +::::{tab-item} Markdown + +```markdown :::{tip} This is a tip. ::: +``` + +:::: + +::::: ### Important Ignoring this information could impact performance or the stability of your system. -```markdown +:::::{tab-set} + +::::{tab-item} Output + :::{important} This is an important notice. ::: -``` +:::: + +::::{tab-item} Markdown + +```markdown :::{important} This is an important notice. ::: +``` + +:::: + +::::: ### Plain A plain admonition is a callout with no further styling. Useful to create a callout that does not quite fit the mold of the stylized admonitions. -```markdown + + +:::::{tab-set} + +::::{tab-item} Output + :::{admonition} This is my callout It can *span* multiple lines and supports inline formatting. ::: -``` +:::: + +::::{tab-item} Markdown + +```markdown :::{admonition} This is my callout It can *span* multiple lines and supports inline formatting. ::: +``` + +:::: + +::::: ## Collapsible admonitions diff --git a/src/Elastic.Markdown/Assets/markdown/admonition.css b/src/Elastic.Markdown/Assets/markdown/admonition.css index e0c09b55f..62a431760 100644 --- a/src/Elastic.Markdown/Assets/markdown/admonition.css +++ b/src/Elastic.Markdown/Assets/markdown/admonition.css @@ -1,22 +1,23 @@ @layer components { .admonition { - @apply mt-4 border-l-4; + @apply mt-4 pb-4 rounded-sm border-1; .admonition-title { - @apply px-4 py-2 font-bold flex items-center gap-4 ; + @apply px-4 pt-4 font-bold flex items-center gap-2 rounded-t-sm; svg { - @apply size-5; + @apply size-6; } } .admonition-content { - @apply px-4 pb-1; + @apply px-4; } &.note { border-color: #61A2FF; background-color: #E8F1FF; .admonition-title { - background-color: #BFDBFF; + color: #1750BA; + /*background-color: #BFDBFF;*/ } } @@ -25,16 +26,18 @@ background-color: #E2F9F7; .admonition-title { - background-color: #C9F3F0; + @apply text-teal-dark; + /*background-color: #C9F3F0;*/ } } &.warning { - @apply border-pink; - background-color: #FFEBF5; - + border-color: #FACB3D; + background-color: #FDF3D8; + .admonition-title { - background-color: #FDDDE9; + color: #825803; + /*background-color: #FDDDE9;*/ } } @@ -43,7 +46,8 @@ background-color: #F3ECFE; .admonition-title { - background-color: #E2D3FE; + color: #6B3C9F; + /*background-color: #E2D3FE;*/ } } @@ -52,7 +56,7 @@ background-color: #F6F9FC; .admonition-title { - background-color: #D9DDE3; + /*background-color: #D9DDE3;*/ } } } diff --git a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml index 7fab89be2..19e284908 100644 --- a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml @@ -2,24 +2,35 @@
- @switch (Model.Classes) - { - case "tip": - - - - break; - case "warning": - - - - break; - case "note": - - - - break; - + @{ + switch (Model.Directive) + { + case "tip": + + + + break; + case "warning": + + + + break; + case "note": + + + + break; + case "important": + + + + break; + default: + + + + break; + } } @* *@ From c0ac71eeeb4551ca45d190597325ab0454df9f03 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 10:10:30 +0100 Subject: [PATCH 06/11] Fix spacing --- src/Elastic.Markdown/Assets/markdown/admonition.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Elastic.Markdown/Assets/markdown/admonition.css b/src/Elastic.Markdown/Assets/markdown/admonition.css index 62a431760..16a0c0e65 100644 --- a/src/Elastic.Markdown/Assets/markdown/admonition.css +++ b/src/Elastic.Markdown/Assets/markdown/admonition.css @@ -10,6 +10,10 @@ } .admonition-content { @apply px-4; + + & > *:first-child { + @apply mt-3!; + } } &.note { From 045c647b555106347db88ddf3dd802915e9a8cf3 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 10:12:00 +0100 Subject: [PATCH 07/11] Update documentation --- docs/syntax/admonitions.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/syntax/admonitions.md b/docs/syntax/admonitions.md index 877c620be..90438e123 100644 --- a/docs/syntax/admonitions.md +++ b/docs/syntax/admonitions.md @@ -158,7 +158,10 @@ Collapsible admonitions are deprecated. Do not use them. Use [dropdowns](./dropd Use `:open: ` to make an admonition collapsible. -```markdown +:::::{tab-set} + +::::{tab-item} Output + :::{note} :open: @@ -166,8 +169,13 @@ Longer content can be collapsed to take less space. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ::: -``` + +:::: + +::::{tab-item} Markdown + +```markdown :::{note} :open: @@ -175,3 +183,8 @@ Longer content can be collapsed to take less space. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ::: +``` + +:::: + +::::: From 7769ef9f2827af6581ffac110ca94125ed0fe6a0 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 11:47:00 +0100 Subject: [PATCH 08/11] Add colors to theme --- .../Assets/markdown/admonition.css | 32 ++-- src/Elastic.Markdown/Assets/markdown/code.css | 3 +- src/Elastic.Markdown/Assets/theme.css | 146 ++++++++++++++++-- 3 files changed, 141 insertions(+), 40 deletions(-) diff --git a/src/Elastic.Markdown/Assets/markdown/admonition.css b/src/Elastic.Markdown/Assets/markdown/admonition.css index 16a0c0e65..1a9bc5697 100644 --- a/src/Elastic.Markdown/Assets/markdown/admonition.css +++ b/src/Elastic.Markdown/Assets/markdown/admonition.css @@ -3,7 +3,7 @@ @apply mt-4 pb-4 rounded-sm border-1; .admonition-title { - @apply px-4 pt-4 font-bold flex items-center gap-2 rounded-t-sm; + @apply px-4 py-2 font-bold flex items-center gap-2 rounded-t-sm; svg { @apply size-6; } @@ -17,50 +17,40 @@ } &.note { - border-color: #61A2FF; - background-color: #E8F1FF; + @apply border-blue-elastic-40 bg-blue-elastic-10; .admonition-title { - color: #1750BA; - /*background-color: #BFDBFF;*/ + @apply text-blue-elastic-90 bg-blue-elastic-20; } } &.tip { - @apply border-teal; - background-color: #E2F9F7; - + @apply border-teal-40 bg-teal-10; .admonition-title { - @apply text-teal-dark; - /*background-color: #C9F3F0;*/ + @apply text-teal-90 bg-teal-20; } } &.warning { - border-color: #FACB3D; - background-color: #FDF3D8; + @apply border-yellow-40 bg-yellow-10; .admonition-title { - color: #825803; - /*background-color: #FDDDE9;*/ + @apply text-yellow-90 bg-yellow-20; } } &.important { - border-color: #B386F9; - background-color: #F3ECFE; + @apply border-purple-40 bg-purple-10; .admonition-title { - color: #6B3C9F; - /*background-color: #E2D3FE;*/ + @apply text-purple-90 bg-purple-20; } } &.plain { - border-color: #989FAA; - background-color: #F6F9FC; + @apply border-grey-40 bg-grey-10; .admonition-title { - /*background-color: #D9DDE3;*/ + @apply text-grey-90 bg-grey-20; } } } diff --git a/src/Elastic.Markdown/Assets/markdown/code.css b/src/Elastic.Markdown/Assets/markdown/code.css index c12e4e7c9..afa91379a 100644 --- a/src/Elastic.Markdown/Assets/markdown/code.css +++ b/src/Elastic.Markdown/Assets/markdown/code.css @@ -1,7 +1,6 @@ @layer components { .markdown-content { - .highlight { @apply mt-4; } @@ -68,7 +67,7 @@ bg-gray-100 rounded-xs border-1 - border-gray-200 + border-gray-300 inline-block ; font-size: 0.875em; diff --git a/src/Elastic.Markdown/Assets/theme.css b/src/Elastic.Markdown/Assets/theme.css index cce351b2c..5d5c32124 100644 --- a/src/Elastic.Markdown/Assets/theme.css +++ b/src/Elastic.Markdown/Assets/theme.css @@ -16,32 +16,144 @@ --color-gray-light: #F5F7FA; --color-gray-dark: #D4DAE5; - --color-blue-elastic: #0B64DD; --color-blue-sky: #36B9FF; --color-blue-midnight: #20377D; --color-blue-developer: #101C3F; + + + --color-blue-elastic-10: #E8F1FF; + --color-blue-elastic-20: #D9E8FF; + --color-blue-elastic-30: #B8D4FF; + --color-blue-elastic-40: #A3CBFF; + --color-blue-elastic-50: #85B7FF; + --color-blue-elastic-60: #61A2FF; + --color-blue-elastic-70: #3788FF; + --color-blue-elastic-80: #2476F0; + --color-blue-elastic-90: #0B64DD; + --color-blue-elastic-100: #1750BA; + --color-blue-elastic-110: #154399; + --color-blue-elastic-120: #123778; + --color-blue-elastic-130: #0D2F5E; + --color-blue-elastic-140: #0A2342; + --color-blue-elastic: #0B64DD; /* == --color-blue-elastic-90 */ + + --color-pink-10: #FFEBF5; + --color-pink-20: #FDDDE9; + --color-pink-30: #FFC7DB; + --color-pink-40: #FBADCA; + --color-pink-50: #F58EB7; + --color-pink-60: #EE72A6; + --color-pink-70: #E54A91; + --color-pink-80: #D13680; + --color-pink-90: #BD1F70; + --color-pink-100: #A11262; + --color-pink-110: #801A54; + --color-pink-120: #5E1E47; + --color-pink-130: #481B3B; + --color-pink-140: #35172E; + --color-pink: #BD1F70; /* == --color-pink-90 */ + + --color-teal-10: #E2F9F7; + --color-teal-20: #C9F3F0; + --color-teal-30: #A6EDEA; + --color-teal-40: #77E5E0; + --color-teal-50: #51D6D2; + --color-teal-60: #16C5C0; + --color-teal-70: #00B0AA; + --color-teal-80: #009E99; + --color-teal-90: #008C88; + --color-teal-100: #047471; + --color-teal-110: #065B58; + --color-teal-120: #044949; + --color-teal-130: #023436; + --color-teal-140: #03282B; + --color-teal: #008C88; /* == --color-teal-90 */ - --color-red-light: #FB6363; - --color-red-dark: #D93333; - --color-green-light: #3CD278; - --color-green-dark: #148742; + --color-yellow-10: #FDF3D8; + --color-yellow-20: #FDE9B5; + --color-yellow-30: #FCD883; + --color-yellow-40: #FACB3D; + --color-yellow-50: #F5BC00; + --color-yellow-60: #EAAE01; + --color-yellow-70: #CA9601; + --color-yellow-80: #AD7E00; + --color-yellow-90: #966B03; + --color-yellow-100: #825803; + --color-yellow-110: #6A4906; + --color-yellow-120: #513910; + --color-yellow-130: #3D3014; + --color-yellow-140: #2C2721; + --color-yellow: #966B03; /* == --color-yellow-90 */ - --color-teal: #00BFB3; - --color-teal-light: #48EFCF; - --color-teal-dark: #00857F; - --color-poppy: #FA744E; - --color-poppy-light: #FF957D; - --color-poppy-dark: #E2543D; + --color-red-10: #FFE8E5; + --color-red-20: #FDDDD8; + --color-red-30: #FFC9C2; + --color-red-40: #FFB5AD; + --color-red-50: #FC9188; + --color-red-60: #F6726A; + --color-red-70: #EE4C48; + --color-red-80: #DA3737; + --color-red-90: #C61E25; + --color-red-100: #A71627; + --color-red-110: #7F1F27; + --color-red-120: #5E2129; + --color-red-130: #491D27; + --color-red-140: #351721; + --color-red: #C61E25; /* == --color-red-90 */ - --color-pink: #F04E98; - --color-pink-light: #F990C6; - --color-pink-dark: #DD0A73; + --color-green-10: #E2F8F0; + --color-green-20: #C9F3E3; + --color-green-30: #AEE8D2; + --color-green-40: #88E3C3; + --color-green-50: #59CFAA; + --color-green-60: #24C292; + --color-green-70: #04AE7E; + --color-green-80: #00996B; + --color-green-90: #008A5E; + --color-green-100: #09724D; + --color-green-110: #0C5A3F; + --color-green-120: #094837; + --color-green-130: #0D362B; + --color-green-140: #092A26; + --color-green: #008A5E; /* == --color-green-90 */ - --color-yellow: #FEC514; - --color-yellow-light: #FFD836; - --color-yellow-dark: #F9B110; + --color-purple-10: #F3ECFE; + --color-purple-20: #ECE2FE; + --color-purple-30: #E2D3FE; + --color-purple-40: #D1BAFC; + --color-purple-50: #C5A5FA; + --color-purple-60: #B386F9; + --color-purple-70: #A36DEF; + --color-purple-80: #925CDA; + --color-purple-90: #8144CC; + --color-purple-100: #6B3C9F; + --color-purple-110: #52357E; + --color-purple-120: #3E2C63; + --color-purple-130: #322452; + --color-purple-140: #2A1E3E; + --color-purple: #8144CC; /* == --color-purple-90 */ + + + /* TODO: Add these colors also for "gray" (a) and replace current occurrences */ + --color-grey-10: #F6F9FC; + --color-grey-20: #E5E9F0; + --color-grey-30: #D0D4DA; + --color-grey-40: #BDC2CA; + --color-grey-50: #AAB0BA; + --color-grey-60: #989FAA; + --color-grey-70: #868E9A; + --color-grey-80: #767D89; + --color-grey-90: #666D78; + --color-grey-100: #555C67; + --color-grey-110: #464C56; + --color-grey-120: #373D45; + --color-grey-130: #292E34; + --color-grey-140: #1C1F24; + --color-grey: #666D78; /* == --color-grey-90 */ + + --spacing: 4px; } From a34d6718b56ffe33f48757811402bfc31a7cf4b2 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 11:52:04 +0100 Subject: [PATCH 09/11] OK --- .../Slices/Directives/Admonition.cshtml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml index 19e284908..ac69daf7d 100644 --- a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml @@ -7,13 +7,13 @@ { case "tip": - - + + break; case "warning": - - - + + + break; case "note": From 92ea7a39fb528949664ef486af92d9f2d1264615 Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 12:59:41 +0100 Subject: [PATCH 10/11] Move tests to f# tests --- .../Directives/AdmonitionTests.cs | 112 ---------- tests/authoring/Blocks/Admonitions.fs | 200 ++++++++++++++++++ tests/authoring/Blocks/Lists.fs | 1 - tests/authoring/Container/DefinitionLists.fs | 32 ++- tests/authoring/authoring.fsproj | 1 + 5 files changed, 223 insertions(+), 123 deletions(-) create mode 100644 tests/authoring/Blocks/Admonitions.fs diff --git a/tests/Elastic.Markdown.Tests/Directives/AdmonitionTests.cs b/tests/Elastic.Markdown.Tests/Directives/AdmonitionTests.cs index 72a96d544..c1aeb6525 100644 --- a/tests/Elastic.Markdown.Tests/Directives/AdmonitionTests.cs +++ b/tests/Elastic.Markdown.Tests/Directives/AdmonitionTests.cs @@ -98,115 +98,3 @@ A regular paragraph. [Fact] public void SetsDropdownOpen() => Block!.DropdownOpen.Should().BeTrue(); } - - -public class NestedDirectiveWithListTests(ITestOutputHelper output) : DirectiveTest(output, - """ - # heading - - :::::{note} - - - List Item 1 - ::::{note} - Hello, World! - :::: - - ## What - - ::::: - """ -) -{ - [Fact] - public void Render() => Html.Should().Contain(""" -
  • List Item 1 -
    -

    Note

    - Hello, World! -
    -
  • - """); -} - - -public class NestedDirectiveWithListTests2(ITestOutputHelper output) : DirectiveTest(output, - """ - # heading - - :::{note} - - - List Item 1 - :::{note} - Hello, World! - ::: - - ## What - - ::: - """ -) -{ - [Fact] - public void Render() => Html.Should().Contain(""" -
  • List Item 1 -
    -

    Note

    - Hello, World! -
    -
  • - """); -} - -public class NestedDirectiveWithListTests3(ITestOutputHelper output) : DirectiveTest(output, - """ - # heading - - :::{note} - - - List Item 1 - :::::{note} - Hello, World! - ::::: - - ## What - - ::: - """ -) -{ - [Fact] - public void Render() => Html.Should().Contain(""" -
  • List Item 1 -
    -

    Note

    - Hello, World! -
    -
  • - """); -} - - -public class DirectiveInList(ITestOutputHelper output) : DirectiveTest(output, - """ - # heading - - - List Item 1 - :::::{note} - Hello, World! - ::::: - """ -) -{ - [Fact] - public void Type() => Block!.Admonition.Should().Be("note"); - - [Fact] - public void Render() => Html.Should().Contain(""" -
  • List Item 1 -
    -

    Note

    - Hello, World! -
    -
  • - """); -} diff --git a/tests/authoring/Blocks/Admonitions.fs b/tests/authoring/Blocks/Admonitions.fs new file mode 100644 index 000000000..98e752942 --- /dev/null +++ b/tests/authoring/Blocks/Admonitions.fs @@ -0,0 +1,200 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information +module ``block elements``.``admonition elements`` + +open Xunit +open authoring + +type ``admonition in list`` () = + static let markdown = Setup.Markdown """ +- List Item 1 + :::::{note} + Hello, World! + ::::: +""" + + [] + let ``validate HTML`` () = + markdown |> convertsToHtml """ +
      +
    • List Item 1 +
      +
      + + + + Note +
      +
      + Hello, World! +
      +
      +
    • +
    + """ + [] + let ``has no errors`` () = markdown |> hasNoErrors + +type ``nested admonition in list`` () = + static let markdown = Setup.Markdown """ +:::{note} + +- List Item 1 + :::::{note} + Hello, World! + ::::: + +## What + +::: +""" + + [] + let ``validate HTML`` () = + markdown |> convertsToHtml """ +
    +
    + + + + Note +
    +
    +
      +
    • List Item 1 +
      +
      + + + + Note +
      +
      + Hello, World! +
      +
      +
    • +
    +
    +
    +
    +

    What +

    +
    + """ + [] + let ``has no errors`` () = markdown |> hasNoErrors + + +type ``nested admonition in list 2`` () = + static let markdown = Setup.Markdown """ +# heading + +:::{note} + +- List Item 1 + :::{note} + Hello, World! + ::: + +## What + +::: +""" + + [] + let ``validate HTML`` () = + markdown |> convertsToHtml """ +
    +

    heading +

    +
    +
    +
    + + + + Note +
    +
    +
      +
    • List Item 1 +
      +
      + + + + Note +
      +
      + Hello, World! +
      +
      +
    • +
    +
    +
    +
    +

    What +

    +
    + """ + [] + let ``has no errors`` () = markdown |> hasNoErrors + +type ``nested admonition in list 3`` () = + static let markdown = Setup.Markdown """ +# heading + +:::::{note} + +- List Item 1 + ::::{note} + Hello, World! + :::: + +## What + +::::: +""" + + [] + let ``validate HTML`` () = + markdown |> convertsToHtml """ +
    +

    heading +

    +
    +
    +
    + + + + Note +
    +
    +
      +
    • List Item 1 +
      +
      + + + + Note +
      +
      + Hello, World! +
      +
      +
    • +
    +
    +

    What +

    +
    +
    +
    + """ + [] + let ``has no errors`` () = markdown |> hasNoErrors diff --git a/tests/authoring/Blocks/Lists.fs b/tests/authoring/Blocks/Lists.fs index fbb73b663..6aa560e35 100644 --- a/tests/authoring/Blocks/Lists.fs +++ b/tests/authoring/Blocks/Lists.fs @@ -27,4 +27,3 @@ type ``supports loose lists`` () = """ - diff --git a/tests/authoring/Container/DefinitionLists.fs b/tests/authoring/Container/DefinitionLists.fs index c03c06a9a..2b4116301 100644 --- a/tests/authoring/Container/DefinitionLists.fs +++ b/tests/authoring/Container/DefinitionLists.fs @@ -44,16 +44,28 @@ This is my `definition` [] let ``validate HTML 2`` () = markdown |> convertsToHtml """ -
    -
    This is my definition
    -
    -

    And this is the definition body
    - Which may contain multiple lines

    -
    -

    Note

    -

    My note

    -
    -
    +
    +
    This is my + definition +
    +
    +

    And this is the definition + body +
    + Which may contain multiple lines +

    +
    +
    + + + + Note +
    +
    +

    My note

    +
    +
    +
    """ [] diff --git a/tests/authoring/authoring.fsproj b/tests/authoring/authoring.fsproj index 6cfe75fcf..6e05e70db 100644 --- a/tests/authoring/authoring.fsproj +++ b/tests/authoring/authoring.fsproj @@ -57,6 +57,7 @@ + From 7c1dbbef75ac2910dd06ae3472add0dfa15fe9ff Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Mon, 17 Feb 2025 13:03:38 +0100 Subject: [PATCH 11/11] cleanup --- src/Elastic.Markdown/Slices/Directives/Admonition.cshtml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml index ac69daf7d..17c1c6539 100644 --- a/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml +++ b/src/Elastic.Markdown/Slices/Directives/Admonition.cshtml @@ -32,11 +32,6 @@ break; } } - - @* *@ - @* *@ - @* *@ - @* *@ @Model.Title