Skip to content

Commit 0ae82a5

Browse files
committed
Support rendering of <details> blocks
Signed-off-by: Michael Haeuslmann <michael.haeuslmann@gmail.com>
1 parent 9176569 commit 0ae82a5

File tree

3 files changed

+91
-2
lines changed

3 files changed

+91
-2
lines changed

CHANGELOG.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [0.14.0] - 2021-03-05
10+
### Added
11+
- Support for rendering `<details>` blocks [as Confluence expand macros](https://confluence.atlassian.com/doc/expand-macro-223222352.html)
12+
13+
## [0.13.3] - 2021-02-10
914
## [0.13.2] - 2021-02-10
1015
### Fixed
1116
- Upgrade dependencies in order to fix vulnerabilities
@@ -71,7 +76,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7176
### Changed
7277
- Add backward compatibility for node 8 (`fs.mkdir`)
7378

74-
[Unreleased]: https://github.com/mihaeu/cosmere/compare/0.13.1...HEAD
79+
[Unreleased]: https://github.com/mihaeu/cosmere/compare/0.14.0...HEAD
80+
[0.14.0]: https://github.com/mihaeu/cosmere/compare/0.13.3...0.14.0
81+
[0.13.3]: https://github.com/mihaeu/cosmere/compare/0.13.2...0.13.3
82+
[0.13.2]: https://github.com/mihaeu/cosmere/compare/0.13.1...0.13.2
7583
[0.13.1]: https://github.com/mihaeu/cosmere/compare/0.13.0...0.13.1
7684
[0.13.0]: https://github.com/mihaeu/cosmere/compare/0.12.3...0.13.0
7785
[0.12.3]: https://github.com/mihaeu/cosmere/compare/0.12.2...0.12.3

src/ConfluenceRenderer.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Renderer } from "marked";
1+
import marked, { Renderer } from "marked";
22

33
export default class ConfluenceRenderer extends Renderer {
44
private readonly langMap = [
@@ -32,6 +32,35 @@ export default class ConfluenceRenderer extends Renderer {
3232
"html/xml",
3333
];
3434

35+
private static hasDetailsBlock(html: string): boolean {
36+
return !!html.match(/<details>([\s\S]*)<\/details>/);
37+
}
38+
39+
private static renderDetailsBlock(html: string): string {
40+
const summary = html.match(/<summary>([\s\S]*)<\/summary>/)?.[1] ?? 'Click here to expand ...'
41+
const contentWithoutSummaryTags = html
42+
.replace(/<summary>([\s\S]*)<\/summary>/, '')
43+
.replace(/<\/?details>/g, '');
44+
const content =
45+
marked(
46+
contentWithoutSummaryTags, {
47+
renderer: new ConfluenceRenderer(),
48+
xhtml: true,
49+
});
50+
51+
return '<ac:structured-macro ac:name="expand">'
52+
+ '<ac:parameter ac:name="title">' + summary + '</ac:parameter>'
53+
+ '<ac:rich-text-body>' + content + '</ac:rich-text-body>'
54+
+ '</ac:structured-macro>';
55+
}
56+
57+
html(html: string): string {
58+
if (ConfluenceRenderer.hasDetailsBlock(html)) {
59+
return ConfluenceRenderer.renderDetailsBlock(html);
60+
}
61+
return super.html(html);
62+
}
63+
3564
image(href: string, title: string, text: string) {
3665
if (href.startsWith("http")) {
3766
return `<ac:image><ri:url ri:value="${href}" /></ac:image>`;

tests/ConfluenceRenderer.test.ts

+52
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,56 @@ describe("ConfluenceRenderer", () => {
3636
+ '</ac:structured-macro>'
3737
+ "\n");
3838
});
39+
40+
it("converts <details> tags to Confluence expand macro", () => {
41+
const input = `<details>
42+
<summary>Short Summary</summary>
43+
More elaborate text ` + '`with other things like monospace`' + `
44+
</details>`;
45+
expect(new ConfluenceRenderer().html(input))
46+
.toBe('<ac:structured-macro ac:name="expand">'
47+
+ '<ac:parameter ac:name="title">'
48+
+ 'Short Summary'
49+
+ '</ac:parameter>'
50+
+ '<ac:rich-text-body>'
51+
+ '<ac:structured-macro ac:name="code" ac:schema-version="1">'
52+
+ '<ac:parameter ac:name="&quot;language">'
53+
+ 'none'
54+
+ '</ac:parameter>'
55+
+ '<ac:parameter ac:name="theme">'
56+
+ 'RDark'
57+
+ '</ac:parameter>'
58+
+ '<ac:parameter ac:name="borderStyle">'
59+
+ 'solid'
60+
+ '</ac:parameter>'
61+
+ '<ac:parameter ac:name="linenumbers">'
62+
+ 'true'
63+
+ '</ac:parameter>'
64+
+ '<ac:parameter ac:name="collapse">'
65+
+ 'false'
66+
+ '</ac:parameter>'
67+
+ '<ac:plain-text-body>'
68+
+ '<![CDATA[ More elaborate text `with other things like monospace`]]>'
69+
+ '</ac:plain-text-body>'
70+
+ '</ac:structured-macro>'
71+
+ "\n"
72+
+ '</ac:rich-text-body>'
73+
+ '</ac:structured-macro>');
74+
})
75+
76+
it("converts <details> tags without summary to Confluence expand macro", () => {
77+
const input = `<details>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci aliquam beatae culpa debitis deserunt dolor ea, exercitationem ipsa, magni maxime molestias nemo nostrum possimus quibusdam quo repudiandae sint veritatis voluptatibus.</details>`;
78+
expect(new ConfluenceRenderer().html(input))
79+
.toBe('<ac:structured-macro ac:name="expand">'
80+
+ '<ac:parameter ac:name="title">'
81+
+ 'Click here to expand ...'
82+
+ '</ac:parameter>'
83+
+ '<ac:rich-text-body>'
84+
+ '<p>'
85+
+ 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci aliquam beatae culpa debitis deserunt dolor ea, exercitationem ipsa, magni maxime molestias nemo nostrum possimus quibusdam quo repudiandae sint veritatis voluptatibus.'
86+
+ '</p>'
87+
+ "\n"
88+
+ '</ac:rich-text-body>'
89+
+ '</ac:structured-macro>');
90+
})
3991
});

0 commit comments

Comments
 (0)