Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use shared toolbar for code block label + buttons #112

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Any non-code changes should be prefixed with `(docs)`.

See `PUBLISH.md` for instructions on how to publish a new version.
-->
- (minor) Move toolbar inside of code-label, show code-label when no label is provided
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved


## v1.13.0 - 6056063
Expand Down
12 changes: 12 additions & 0 deletions fixtures/full-output.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,47 +129,58 @@ <h2 id="step-1-basic-markdown"><a class="hash-anchor" href="#step-1-basic-markdo
<span class="token punctuation">}</span>
</code></pre>
<p>Examples can have line numbers, and every code block has a ‘Copy’ button to copy just the code:</p>
<div class="code-label" title=""></div>
<pre class="prefixed line_numbers language-javascript"><code><ol><li data-prefix="1"><span class="token keyword">const</span> test <span class="token operator">=</span> <span class="token string">&apos;hello&apos;</span><span class="token punctuation">;</span>
</li><li data-prefix="2"><span class="token keyword">const</span> other <span class="token operator">=</span> <span class="token string">&apos;world&apos;</span><span class="token punctuation">;</span>
</li><li data-prefix="3">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>test<span class="token punctuation">,</span> other<span class="token punctuation">)</span><span class="token punctuation">;</span>
</li></ol>
</code></pre>
<p>Here’s output from a command with a secondary label:</p>
<div class="code-label" title=""></div>
<pre><code><div class="secondary-code-label" title="Output">Output</div>Could not connect to Redis at 127.0.0.1:6379: Connection refused
</code></pre>
<p>This is a non-root user command example:</p>
<div class="code-label" title=""></div>
<pre class="prefixed command language-bash"><code><ol><li data-prefix="&#x24;"><span class="token function">sudo</span> <span class="token function">apt-get</span> update
</li><li data-prefix="&#x24;"><span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> python3
</li></ol>
</code></pre>
<p>This is a root command example:</p>
<div class="code-label" title=""></div>
<pre class="prefixed super_user language-bash"><code><ol><li data-prefix="#">adduser sammy
</li><li data-prefix="#"><span class="token function">shutdown</span>
</li></ol>
</code></pre>
<p>This is a custom prefix command example:</p>
<div class="code-label" title=""></div>
<pre class="prefixed custom_prefix language-bash"><code><ol><li data-prefix="mysql&gt;">FLUSH PRIVILEGES<span class="token punctuation">;</span>
</li><li data-prefix="mysql&gt;">SELECT * FROM articles<span class="token punctuation">;</span>
</li></ol>
</code></pre>
<p>A custom prefix can contain a space by using <code>\s</code>:</p>
<div class="code-label" title=""></div>
<pre class="prefixed custom_prefix language-bash"><code><ol><li data-prefix="(my-server) mysql&gt;">FLUSH PRIVILEGES<span class="token punctuation">;</span>
</li><li data-prefix="(my-server) mysql&gt;">SELECT * FROM articles<span class="token punctuation">;</span>
</li></ol>
</code></pre>
<p>Indicate where commands are being run with environments:</p>
<div class="code-label" title=""></div>
<pre class="prefixed command environment-local language-bash"><code><ol><li data-prefix="&#x24;"><span class="token function">ssh</span> root@server_ip
</li></ol>
</code></pre>
<div class="code-label" title=""></div>
<pre class="prefixed command environment-second language-bash"><code><ol><li data-prefix="&#x24;"><span class="token builtin class-name">echo</span> <span class="token string">&quot;Secondary server&quot;</span>
</li></ol>
</code></pre>
<div class="code-label" title=""></div>
<pre class="prefixed command environment-third language-bash"><code><ol><li data-prefix="&#x24;"><span class="token builtin class-name">echo</span> <span class="token string">&quot;Tertiary server&quot;</span>
</li></ol>
</code></pre>
<div class="code-label" title=""></div>
<pre class="prefixed command environment-fourth language-bash"><code><ol><li data-prefix="&#x24;"><span class="token builtin class-name">echo</span> <span class="token string">&quot;Quaternary server&quot;</span>
</li></ol>
</code></pre>
<div class="code-label" title=""></div>
<pre class="prefixed command environment-fifth language-bash"><code><ol><li data-prefix="&#x24;"><span class="token builtin class-name">echo</span> <span class="token string">&quot;Quinary server&quot;</span>
</li></ol>
</code></pre>
Expand Down Expand Up @@ -225,6 +236,7 @@ <h2 id="step-4-layout"><a class="hash-anchor" href="#step-4-layout" aria-hidden=
<summary>Content can be hidden using <code>details</code>.</summary>
<p>Inside the details block you can use any block or inline syntax.</p>
<p>You could hide the solution to a problem:</p>
<div class="code-label" title=""></div>
<pre class="language-javascript"><code><span class="token comment">// Write a message to console</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&apos;Hello, world!&apos;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre>
Expand Down
7 changes: 2 additions & 5 deletions modifiers/fence_label.js
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,8 @@ module.exports = (md, options) => {
const match = token.content.match(/^((?:\[.+\]\n)*?)\[label (.+)\]\n/);
const name = (match && (match[2] || '').trim()) || null;

// If no name, just return original
if (!name) return original(tokens, idx, opts, env, self);

// Remove the label line
token.content = token.content.replace(match[0], match[1]);
if (match && name) token.content = token.content.replace(match[0], match[1]);

// Get the rendered content
const content = original(tokens, idx, opts, env, self);
Expand All @@ -78,7 +75,7 @@ module.exports = (md, options) => {
const className = optsObj.className || 'code-label';

// Inject label and return
return `<div class="${md.utils.escapeHtml(className)}" title="${md.utils.escapeHtml(name)}">${md.utils.escapeHtml(name)}</div>
return `<div class="${md.utils.escapeHtml(className)}" title="${md.utils.escapeHtml(name) || ''}">${md.utils.escapeHtml(name) || ''}</div>
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
${content}`;
};

Expand Down
6 changes: 4 additions & 2 deletions modifiers/fence_label.test.js
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ world
});

it('handles a code block with no label', () => {
expect(md.render('```\nhello\nworld\n```')).toBe(`<pre><code>hello
expect(md.render('```\nhello\nworld\n```')).toBe(`<div class="code-label" title=""></div>
<pre><code>hello
world
</code></pre>
`);
});

it('handles a code block with an empty label', () => {
expect(md.render('```\n[label ]\nhello\nworld\n```')).toBe(`<pre><code>[label ]
expect(md.render('```\n[label ]\nhello\nworld\n```')).toBe(`<div class="code-label" title=""></div>
<pre><code>[label ]
hello
world
</code></pre>
Expand Down
27 changes: 18 additions & 9 deletions modifiers/prismjs.test.js
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -133,49 +133,57 @@ describe('HTML preservation', () => {
.use(require('./prismjs'));

it('handles a token at the start of the code block', () => {
expect(mdHtml.render('```js\nreturn;\n```')).toBe(`<pre class="language-javascript"><code class="language-js"><span class="token keyword">return</span><span class="token punctuation">;</span>
expect(mdHtml.render('```js\nreturn;\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-javascript"><code class="language-js"><span class="token keyword">return</span><span class="token punctuation">;</span>
</code></pre>
`);
});

it('handles plain-text at the start of the code block', () => {
expect(mdHtml.render('```js\nconsole.log;\n```')).toBe(`<pre class="language-javascript"><code class="language-js">console<span class="token punctuation">.</span>log<span class="token punctuation">;</span>
expect(mdHtml.render('```js\nconsole.log;\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-javascript"><code class="language-js">console<span class="token punctuation">.</span>log<span class="token punctuation">;</span>
</code></pre>
`);
});

it('handles nested tokens in the code block', () => {
expect(mdHtml.render('```nginx\nserver {}\n```')).toBe(`<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
expect(mdHtml.render('```nginx\nserver {}\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</code></pre>
`);
});

it('handles nested markup languages in the code block', () => {
expect(mdHtml.render('```php\na <?php b\n```')).toBe(`<pre class="language-php"><code class="language-php">a <span class="token php language-php"><span class="token delimiter important">&lt;?php</span> b
expect(mdHtml.render('```php\na <?php b\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-php"><code class="language-php">a <span class="token php language-php"><span class="token delimiter important">&lt;?php</span> b
</span></code></pre>
`);
});

it('handles HTML inside a token in the code block', () => {
expect(mdHtml.render('```js\nreturn \'hello <^>world<^>\';\n```')).toBe(`<pre class="language-javascript"><code class="language-js"><span class="token keyword">return</span> <span class="token string">&apos;hello <mark>world</mark>&apos;</span><span class="token punctuation">;</span>
expect(mdHtml.render('```js\nreturn \'hello <^>world<^>\';\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-javascript"><code class="language-js"><span class="token keyword">return</span> <span class="token string">&apos;hello <mark>world</mark>&apos;</span><span class="token punctuation">;</span>
</code></pre>
`);
});

it('handles HTML inside nested tokens in the code block', () => {
expect(mdHtml.render('```nginx\nserver { listen 80 <^>default_server<^>; }\n```')).toBe(`<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span> <span class="token directive"><span class="token keyword">listen</span> <span class="token number">80</span> <mark>default_server</mark></span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
expect(mdHtml.render('```nginx\nserver { listen 80 <^>default_server<^>; }\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span> <span class="token directive"><span class="token keyword">listen</span> <span class="token number">80</span> <mark>default_server</mark></span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</code></pre>
`);
});

it('handles HTML spanning tokens in the code block', () => {
expect(mdHtml.render('```nginx\nserver { li<^>sten 80 default_server<^>; }\n```')).toBe(`<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span> <span class="token directive"><span class="token keyword">li</span><mark><span class="token keyword">sten</span> <span class="token number">80</span> default_server</mark></span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
expect(mdHtml.render('```nginx\nserver { li<^>sten 80 default_server<^>; }\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-nginx"><code class="language-nginx"><span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span> <span class="token directive"><span class="token keyword">li</span><mark><span class="token keyword">sten</span> <span class="token number">80</span> default_server</mark></span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
</code></pre>
`);
});

it('handles HTML spanning multi-line tokens in the code block', () => {
expect(mdHtml.render('```go\n<^>data := `<^>\n <^>test<^>\n<^>`<^>\n```')).toBe(`<pre class="language-go"><code class="language-go"><mark>data <span class="token operator">:=</span> <span class="token string">\`</span></mark><span class="token string">
expect(mdHtml.render('```go\n<^>data := `<^>\n <^>test<^>\n<^>`<^>\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-go"><code class="language-go"><mark>data <span class="token operator">:=</span> <span class="token string">\`</span></mark><span class="token string">
<mark>test</mark>
<mark>\`</mark></span>
</code></pre>
Expand All @@ -190,7 +198,8 @@ describe('HTML preservation', () => {
});

it('handles HTML wrapping each line', () => {
expect(mdHtml.render('```javascript,line_numbers\nconst test = \'hello\';\nconst other = \'world\';\nconsole.log(test, other);\n```')).toBe(`<pre class="language-javascript"><code class="prefixed line_numbers language-javascript"><ol><li data-prefix="1"><span class="token keyword">const</span> test <span class="token operator">=</span> <span class="token string">&apos;hello&apos;</span><span class="token punctuation">;</span>
expect(mdHtml.render('```javascript,line_numbers\nconst test = \'hello\';\nconst other = \'world\';\nconsole.log(test, other);\n```')).toBe(`<div class="code-label" title=""></div>
<pre class="language-javascript"><code class="prefixed line_numbers language-javascript"><ol><li data-prefix="1"><span class="token keyword">const</span> test <span class="token operator">=</span> <span class="token string">&apos;hello&apos;</span><span class="token punctuation">;</span>
</li><li data-prefix="2"><span class="token keyword">const</span> other <span class="token operator">=</span> <span class="token string">&apos;world&apos;</span><span class="token punctuation">;</span>
</li><li data-prefix="3">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>test<span class="token punctuation">,</span> other<span class="token punctuation">)</span><span class="token punctuation">;</span>
</li></ol>
Expand Down
22 changes: 12 additions & 10 deletions styles/_code_label.scss
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ limitations under the License.
$code-label-class: "code-label" !default;

// Code labels
.#{$code-label-class} {
background-color: $gray7;
border-radius: 16px 16px 0 0;
color: $gray3;
display: block;
.#{$code-label-class}:has(+ .code-toolbar),
.#{$code-label-class}:not([title=""]) {
background-color: $code-highlight-dark;
border-radius: 1em 1em 0 0;
color: $white;
display: flex;
padding: 0.75em 1.5em;
justify-content: space-between;
align-items: center;
font-size: 16px;
margin: 1em 0 0;
padding: 12px;
position: relative;
text-align: center;
min-height: 3.25em;
z-index: 2;

+ pre {
border-radius: 0 0 16px 16px;
border-radius: 0 0 1em 1em;
margin: 0 0 1em;
}

Expand All @@ -41,7 +43,7 @@ $code-label-class: "code-label" !default;
margin: 0 0 1em;

pre {
border-radius: 0 0 16px 16px;
border-radius: 0 0 1em 1em;
}
}
}
5 changes: 3 additions & 2 deletions styles/_code_prism.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ pre {

> .toolbar {
position: absolute;
right: calc(1.5em - 0.5em);
top: calc(1.5em - 0.375em);
right: 1.5em;
top: -2.4em;
z-index: 3;

> .toolbar-item {
display: inline-block;
Expand Down
7 changes: 7 additions & 0 deletions styles/digitalocean/_code_environments.scss
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ limitations under the License.
@import "../theme";
@import "../mixins";

$code-label-class: "code-label" !default;

.#{$code-label-class}:has(+ .code-toolbar > pre[class*="environment-"]) {
background: $gray9;
color: $gray4;
}
dbadea-heits marked this conversation as resolved.
Show resolved Hide resolved

// DigitalOcean-usage-specific code environment styling
pre {
// Environments use light-mode base
Expand Down