Skip to content

Commit

Permalink
feat: use <details> tag for cuts ( (#4)
Browse files Browse the repository at this point in the history
* refactor: use <details> tag for cuts

Replace div tags to <details> and <summary> tags.

Delete CSS selector for closed cuts state because there
is no need to write 2 separate selectors for cuts state
(open/closed) after using <details> tag.

Add "list-style" and "::-webkit-details-marker" to
delete default toggle marker.

Add color for focus outline because <details> tag
allows to use keyboard navigation for cuts.

* test: change tests for cuts

Change tests due to replacing <div> tags
to <details> and <summary> tags in cuts.
  • Loading branch information
Pavel-Tyan authored Aug 7, 2024
1 parent db90e7c commit 980c5e0
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 52 deletions.
8 changes: 4 additions & 4 deletions src/plugin/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ export const cutPlugin: MarkdownIt.PluginSimple = (md) => {
continue;
}

const newOpenToken = new state.Token(TokenType.CutOpen, 'div', 1);
const newOpenToken = new state.Token(TokenType.CutOpen, 'details', 1);
newOpenToken.attrSet('class', ClassNames.Cut);
newOpenToken.map = tokens[i].map;

const titleOpen = new state.Token(TokenType.TitleOpen, 'div', 1);
const titleOpen = new state.Token(TokenType.TitleOpen, 'summary', 1);
titleOpen.attrSet('class', ClassNames.Title);

const titleInline = state.md.parseInline(
match[1] === undefined ? 'ad' : match[1],
state.env,
)[0];

const titleClose = new state.Token(TokenType.TitleClose, 'div', -1);
const titleClose = new state.Token(TokenType.TitleClose, 'summary', -1);

const contentOpen = new state.Token(TokenType.ContentOpen, 'div', 1);
contentOpen.attrSet('class', ClassNames.Content);
Expand All @@ -46,7 +46,7 @@ export const cutPlugin: MarkdownIt.PluginSimple = (md) => {

const contentClose = new state.Token(TokenType.ContentClose, 'div', -1);

const newCloseToken = new state.Token(TokenType.CutClose, 'div', -1);
const newCloseToken = new state.Token(TokenType.CutClose, 'details', -1);
newCloseToken.map = tokens[closeTokenIdx].map;

const insideTokens = [
Expand Down
18 changes: 10 additions & 8 deletions src/runtime/styles/cut.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@
margin-bottom: 15px;

&-title {
list-style: none;
cursor: pointer;
position: relative;
user-select: none;
padding: 5px 0 5px 30px;

&::-webkit-details-marker {
display: none;
}

&:focus {
outline-color: $accentColor;
}

&:before {
content: '';
z-index: 1;
Expand All @@ -24,17 +33,10 @@
}

&-content {
display: none;
overflow: hidden;
transition: height 0.3s ease-in-out;
padding: 5px 0 15px 30px;
}

&.open {
> #{$class}-content {
display: revert;
padding: 5px 0 15px 30px;
}

> #{$class}-title:before {
transform: translateY(-50%);
}
Expand Down
97 changes: 57 additions & 40 deletions tests/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import transform from '@diplodoc/transform';
import * as cutExtension from '../src/plugin';

const transformYfm = (text: string, opts?: cutExtension.TransformOptions) => {
const {
result,
} = transform(text, {
const {result} = transform(text, {
plugins: [cutExtension.transform({bundle: false, ...opts})],
});
return result;
Expand All @@ -18,9 +16,10 @@ describe('Cut extension - plugin', () => {
'{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<div class="yfm-cut"><div class="yfm-cut-title">Cut title</div>' +
'<div class="yfm-cut-content"><p>Cut content</p>' +
'</div></div>',
'<details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut title</summary>' +
'<div class="yfm-cut-content"><p>Cut content</p></div>' +
'</details>',
);
});

Expand All @@ -36,9 +35,12 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<div class="yfm-cut"><div class="yfm-cut-title">Cut title</div>' +
'<div class="yfm-cut-content"><pre><code>Code</code></pre>' +
'</div></div>',
'<details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut title</summary>' +
'<div class="yfm-cut-content">' +
'<pre><code>Code</code></pre>' +
'</div>' +
'</details>',
);
});

Expand All @@ -58,12 +60,15 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<div class="yfm-cut"><div class="yfm-cut-title">Cut title 1</div>' +
'<div class="yfm-cut-content"><p>Cut content 1</p></div>' +
'</div>' +
'<div class="yfm-cut"><div class="yfm-cut-title">Cut title 2</div>' +
'<div class="yfm-cut-content"><p>Cut content 2</p></div>' +
'</div>',
'<details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut title 1</summary>' +
'<div class="yfm-cut-content"><p>Cut content 1</p>' +
'</div></details>' +
'<details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut title 2</summary>' +
'<div class="yfm-cut-content">' +
'<p>Cut content 2</p>' +
'</div></details>',
);
});

Expand All @@ -83,11 +88,12 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<div class="yfm-cut"><div class="yfm-cut-title">Outer title</div>' +
'<div class="yfm-cut-content"><p>Outer content</p>' +
'<div class="yfm-cut"><div class="yfm-cut-title">Inner title</div>' +
'<div class="yfm-cut-content"><p>Inner content</p></div>' +
'</div></div></div>',
'<details class="yfm-cut"><summary class="yfm-cut-title">' +
'Outer title</summary><div class="yfm-cut-content">' +
'<p>Outer content</p><details class="yfm-cut">' +
'<summary class="yfm-cut-title">Inner title</summary>' +
'<div class="yfm-cut-content"><p>Inner content</p>' +
'</div></details></div></details>',
);
});

Expand All @@ -101,10 +107,11 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<div class="yfm-cut">' +
'<div class="yfm-cut-title"><strong>Strong cut title</strong></div>' +
'<div class="yfm-cut-content"><p>Content we want to hide</p></div>' +
'</div>',
'<details class="yfm-cut"><summary class="yfm-cut-title">' +
'<strong>Strong cut title</strong>' +
'</summary><div class="yfm-cut-content">' +
'<p>Content we want to hide</p>' +
'</div></details>',
);
});

Expand All @@ -120,8 +127,11 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<ul><li><div class="yfm-cut"><div class="yfm-cut-title">Cut 1</div>' +
'<div class="yfm-cut-content"><p>Some text</p><p>Some text</p></div></div></li></ul>',
'<ul><li>' +
'<details class="yfm-cut"><summary class="yfm-cut-title">Cut 1</summary>' +
'<div class="yfm-cut-content"><p>Some text</p>' +
'<p>Some text</p>' +
'</div></details></li></ul>',
);
});

Expand All @@ -147,12 +157,16 @@ describe('Cut extension - plugin', () => {
'{% endcut %}',
).html.replace(/(\r\n|\n|\r)/gm, ''),
).toBe(
'<ul><li><div class="yfm-cut"><div class="yfm-cut-title">Cut 1</div>' +
'<div class="yfm-cut-content"><p>Some text</p></div></div></li>' +
'<li><div class="yfm-cut"><div class="yfm-cut-title">Cut 2</div>' +
'<div class="yfm-cut-content"><p>Some text</p></div></div></li>' +
'<li><div class="yfm-cut"><div class="yfm-cut-title">Cut 3</div>' +
'<div class="yfm-cut-content"><p>Some text</p></div></div></li></ul>',
'<ul><li>' +
'<details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut 1</summary>' +
'<div class="yfm-cut-content"><p>Some text</p></div>' +
'</details></li>' +
'<li><details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut 2</summary><div class="yfm-cut-content">' +
'<p>Some text</p></div></details></li><li><details class="yfm-cut">' +
'<summary class="yfm-cut-title">Cut 3</summary>' +
'<div class="yfm-cut-content"><p>Some text</p></div></details></li></ul>',
);
});

Expand All @@ -163,22 +177,25 @@ describe('Cut extension - plugin', () => {

it('should add default assets to meta', () => {
const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}';
expect(
transformYfm(markup).meta
).toStrictEqual({ script: ['_assets/cut-extension.js'], style: ['_assets/cut-extension.css'] });
expect(transformYfm(markup).meta).toStrictEqual({
script: ['_assets/cut-extension.js'],
style: ['_assets/cut-extension.css'],
});
});

it('should add custom assets to meta', () => {
const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}';
expect(
transformYfm(markup, {runtime: 'yfm-cut'}).meta
).toStrictEqual({ script: ['yfm-cut'], style: ['yfm-cut'] });
expect(transformYfm(markup, {runtime: 'yfm-cut'}).meta).toStrictEqual({
script: ['yfm-cut'],
style: ['yfm-cut'],
});
});

it('should add custom assets to meta 2', () => {
const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}';
expect(
transformYfm(markup, {runtime: {script: 'yfm-cut.script', style: 'yfm-cut.style'}}).meta
).toStrictEqual({ script: ['yfm-cut.script'], style: ['yfm-cut.style'] });
transformYfm(markup, {runtime: {script: 'yfm-cut.script', style: 'yfm-cut.style'}})
.meta,
).toStrictEqual({script: ['yfm-cut.script'], style: ['yfm-cut.style']});
});
});

0 comments on commit 980c5e0

Please sign in to comment.