1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-17 18:44:45 +02:00
joplin/ElectronClient/gui/NoteContentPropertiesDialog.tsx
Laurent Cozic 3d8577a689 Plugins: Added support for content scripts
- For now, supports Markdown-it plugins
- Also fixed slow rendering of notes in some cases
- Simplified how Markdown-It plugins are created and cleaned MdToHtml code

commit 89576de2896c99134f25f2a2db25008514cb1315
Merge: c75aa21f 5292fc14
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:23:00 2020 +0100

    Merge branch 'release-1.3' into plugin_content_scripts

commit c75aa21ffdc42764d71dc9deadba7a7ef4233995
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:19:52 2020 +0100

    Fixed tests

commit 075187729d11a16d385b651cbf1ebb89f14935e0
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:11:53 2020 +0100

    Fixed tests

commit 14696b8c651e7afdaf71269bcdbadf0d58d3ef8a
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 23:27:58 2020 +0100

    Fixed slow rendering of note

commit 61c09f5bf856481f91b00cfe87ff05596c63d4bc
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 22:35:21 2020 +0100

    Clean up

commit 9f7ea7d865a990b3a21cc8c59093390d9db61653
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 20:05:31 2020 +0100

    Updated doc

commit 98bf3bde8d6663f2f91ff965304b4aac00bdd98b
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 19:56:34 2020 +0100

    Finished converting plugins

commit fe90d92e01427bd2b38200393713ea28763507a9
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 17:52:02 2020 +0100

    Simplified how Markdown-It plugins are created

commit 47c7b864cbb864d5df79849f27625aecf312df4b
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 16:40:11 2020 +0100

    Clean up rules

commit d927a238bb635a4be45f9216d776f7d07cb0a584
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 14:29:40 2020 +0100

    Fixed tests

commit 388a56c5dde4c382e3ee0035791137150adaba1b
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 14:00:47 2020 +0100

    Add support for content scripts
2020-10-21 00:23:55 +01:00

175 lines
5.2 KiB
TypeScript

import * as React from 'react';
import { useState, useEffect } from 'react';
import { _ } from 'lib/locale';
const { themeStyle } = require('lib/theme');
const DialogButtonRow = require('./DialogButtonRow.min');
const Countable = require('countable');
const markupLanguageUtils = require('lib/markupLanguageUtils').default;
interface NoteContentPropertiesDialogProps {
themeId: number,
text: string,
markupLanguage: number,
onClose: Function,
}
interface TextPropertiesMap {
[key: string]: number;
}
interface KeyToLabelMap {
[key: string]: string;
}
let markupToHtml_:any = null;
function markupToHtml() {
if (markupToHtml_) return markupToHtml_;
markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
return markupToHtml_;
}
function countElements(text:string, wordSetter:Function, characterSetter:Function, characterNoSpaceSetter:Function, lineSetter:Function) {
Countable.count(text, (counter:any) => {
wordSetter(counter.words);
characterSetter(counter.all);
characterNoSpaceSetter(counter.characters);
});
text === '' ? lineSetter(0) : lineSetter(text.split('\n').length);
}
function formatReadTime(readTimeMinutes: number) {
if (readTimeMinutes < 1) {
return '< 1';
}
return Math.ceil(readTimeMinutes).toString();
}
export default function NoteContentPropertiesDialog(props:NoteContentPropertiesDialogProps) {
const theme = themeStyle(props.themeId);
const tableBodyComps: JSX.Element[] = [];
// For the source Markdown
const [lines, setLines] = useState<number>(0);
const [words, setWords] = useState<number>(0);
const [characters, setCharacters] = useState<number>(0);
const [charactersNoSpace, setCharactersNoSpace] = useState<number>(0);
// For source with Markdown syntax stripped out
const [strippedLines, setStrippedLines] = useState<number>(0);
const [strippedWords, setStrippedWords] = useState<number>(0);
const [strippedCharacters, setStrippedCharacters] = useState<number>(0);
const [strippedCharactersNoSpace, setStrippedCharactersNoSpace] = useState<number>(0);
const [strippedReadTime, setStrippedReadTime] = useState<number>(0);
// This amount based on the following paper:
// https://www.researchgate.net/publication/332380784_How_many_words_do_we_read_per_minute_A_review_and_meta-analysis_of_reading_rate
const wordsPerMinute = 250;
useEffect(() => {
countElements(props.text, setWords, setCharacters, setCharactersNoSpace, setLines);
}, [props.text]);
useEffect(() => {
const strippedText: string = markupToHtml().stripMarkup(props.markupLanguage, props.text);
countElements(strippedText, setStrippedWords, setStrippedCharacters, setStrippedCharactersNoSpace, setStrippedLines);
}, [props.text]);
useEffect(() => {
const readTimeMinutes: number = strippedWords / wordsPerMinute;
setStrippedReadTime(readTimeMinutes);
}, [strippedWords]);
const textProperties: TextPropertiesMap = {
lines: lines,
words: words,
characters: characters,
charactersNoSpace: charactersNoSpace,
};
const strippedTextProperties: TextPropertiesMap = {
// The function stripMarkup() currently removes all new lines so we can't use the
// strippedLines property. Instead we simply use the lines property which should
// be a good approximation anyway.
// Also dummy check to silence TypeScript warning
lines: strippedLines === -5000 ? strippedLines : lines,
words: strippedWords,
characters: strippedCharacters,
charactersNoSpace: strippedCharactersNoSpace,
};
const keyToLabel: KeyToLabelMap = {
words: _('Words'),
characters: _('Characters'),
charactersNoSpace: _('Characters excluding spaces'),
lines: _('Lines'),
};
const buttonRow_click = () => {
props.onClose();
};
const labelCompStyle = {
...theme.textStyle,
fontWeight: 'bold',
width: '10em',
};
const controlCompStyle = {
...theme.textStyle,
textAlign: 'center',
};
const createTableBodyRow = (key: string, value: number, strippedValue: number) => {
const labelComp = <td style={labelCompStyle}>{keyToLabel[key]}</td>;
const controlComp = <td style={controlCompStyle}>{value}</td>;
const strippedControlComp = <td style={controlCompStyle}>{strippedValue}</td>;
return (
<tr key={key}>{labelComp}{controlComp}{strippedControlComp}</tr>
);
};
const tableHeaderStyle = {
...theme.textStyle,
textAlign: 'center',
};
const tableHeader = (
<tr>
<th style={tableHeaderStyle}></th>
<th style={tableHeaderStyle}>{_('Editor')}</th>
<th style={tableHeaderStyle}>{_('Viewer')}</th>
</tr>
);
for (const key in textProperties) {
const comp = createTableBodyRow(key, textProperties[key], strippedTextProperties[key]);
tableBodyComps.push(comp);
}
const dialogBoxHeadingStyle = {
...theme.dialogTitle,
textAlign: 'center',
};
const readTimeLabel = _('Read time: %s min', formatReadTime(strippedReadTime));
return (
<div style={theme.dialogModalLayer}>
<div style={theme.dialogBox}>
<div style={dialogBoxHeadingStyle}>{_('Statistics')}</div>
<table>
<thead>
{tableHeader}
</thead>
<tbody>
{tableBodyComps}
</tbody>
</table>
<div style={{ ...labelCompStyle, marginTop: 10 }}>
{readTimeLabel}
</div>
<DialogButtonRow themeId={props.themeId} onClick={buttonRow_click} okButtonShow={false} cancelButtonLabel={_('Close')}/>
</div>
</div>
);
}