Improve documentation support with markdown

Rework documentation URLs as inline markdown.

Redesign documentations with markdown text.

Redesign way to document scripts/categories and present the
documentation.

Documentation is showed in an expandable box instead of tooltip. This is
to allow writing longer documentation (tooltips are meant to be used for
short text) and have better experience on mobile.

If a node (script/category) has documentation it's now shown with single
information icon (ℹ) aligned to right.

Add support for rendering documentation as markdown. It automatically
converts plain URLs to URLs with display names (e.g.
https://docs.microsoft.com/..) will be rendered automatically like
"docs.microsoft.com - Windows 11 Privacy...".
This commit is contained in:
undergroundwires
2022-09-25 23:25:43 +02:00
parent 924b326244
commit 6067bdb24e
41 changed files with 973 additions and 265 deletions

View File

@@ -0,0 +1,69 @@
import 'mocha';
import { expect } from 'chai';
import { createRenderer } from '@/presentation/components/Scripts/View/ScriptsTree/SelectableTree/Node/Documentation/MarkdownRenderer';
describe('MarkdownRenderer', () => {
describe('createRenderer', () => {
it('can create', () => {
// arrange & act
const renderer = createRenderer();
// assert
expect(renderer !== undefined);
});
it('opens URLs in new tab', () => {
// arrange
const renderer = createRenderer();
const markdown = '[undergroundwires.dev](https://undergroundwires.dev)';
// act
const htmlString = renderer.render(markdown);
// assert
const html = parseHtml(htmlString);
const aElement = html.getElementsByTagName('a')[0];
const href = aElement.getAttribute('target');
expect(href).to.equal('_blank');
});
it('does not convert single linebreak to <br>', () => {
// arrange
const renderer = createRenderer();
const markdown = 'Text with\nSingle\nLinebreaks';
// act
const htmlString = renderer.render(markdown);
// assert
const html = parseHtml(htmlString);
const totalBrElements = html.getElementsByTagName('br').length;
expect(totalBrElements).to.equal(0);
});
it('creates links for plain URL', () => {
// arrange
const renderer = createRenderer();
const expectedUrl = 'https://privacy.sexy/';
const markdown = `Visit ${expectedUrl} now!`;
// act
const htmlString = renderer.render(markdown);
// assert
const html = parseHtml(htmlString);
const aElement = html.getElementsByTagName('a')[0];
const href = aElement.getAttribute('href');
expect(href).to.equal(expectedUrl);
});
it('it generates beautiful labels for auto-linkified URL', () => {
// arrange
const renderer = createRenderer();
const url = 'https://privacy.sexy';
const expectedText = 'privacy.sexy';
const markdown = `Visit ${url} now!`;
// act
const htmlString = renderer.render(markdown);
// assert
const html = parseHtml(htmlString);
const aElement = html.getElementsByTagName('a')[0];
expect(aElement.text).to.equal(expectedText);
});
});
});
function parseHtml(htmlString: string): Document {
const parser = new window.DOMParser();
const htmlDoc = parser.parseFromString(htmlString, 'text/html');
return htmlDoc;
}

View File

@@ -39,7 +39,7 @@ describe('ReverterFactory', () => {
id: nodeId,
text: 'text',
isReversible: false,
documentationUrls: [],
docs: [],
children: [],
type,
};