From c1e6ae947adf7ba4a5f6c1f59d14d1a0dc39230c Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Fri, 14 Feb 2025 18:14:13 +0100 Subject: [PATCH 1/4] 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 2/4] 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 3/4] 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 40b950344a1012c33746a81900ad837861faf15d Mon Sep 17 00:00:00 2001 From: Jan Calanog Date: Sun, 16 Feb 2025 22:35:53 +0100 Subject: [PATCH 4/4] Fix code --- src/Elastic.Markdown/Assets/markdown/code.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Elastic.Markdown/Assets/markdown/code.css b/src/Elastic.Markdown/Assets/markdown/code.css index c12e4e7c9..14d9eed48 100644 --- a/src/Elastic.Markdown/Assets/markdown/code.css +++ b/src/Elastic.Markdown/Assets/markdown/code.css @@ -10,9 +10,10 @@ @apply grid; code { @apply text-sm - text-gray-100 + text-gray-300 rounded-none border-0 + overflow-x-auto p-6! ; background-color: #22272e; @@ -70,6 +71,7 @@ border-1 border-gray-200 inline-block + text-nowrap ; font-size: 0.875em; line-height: 1.4em; @@ -78,6 +80,5 @@ letter-spacing: 0.02em; text-decoration: inherit; font-weight: inherit; - text-wrap: nowrap; } }