mirror of https://github.com/laurent22/joplin.git
pull/9550/head
parent
858205a72b
commit
5f6b2f1a63
|
@ -42,15 +42,12 @@ describe('createEditor', () => {
|
||||||
|
|
||||||
const headerLine = document.body.querySelector('.cm-headerLine')!;
|
const headerLine = document.body.querySelector('.cm-headerLine')!;
|
||||||
expect(headerLine.textContent).toBe(headerLineText);
|
expect(headerLine.textContent).toBe(headerLineText);
|
||||||
|
expect(getComputedStyle(headerLine).fontSize).toBe('1.6em');
|
||||||
|
|
||||||
// CodeMirror nests the tag that styles the header within .cm-headerLine:
|
// CodeMirror nests the tag that styles the header within .cm-headerLine:
|
||||||
// <div class='cm-headerLine'><span class='someclass'>Testing...</span></div>
|
// <div class='cm-headerLine'><span class='someclass'>Testing...</span></div>
|
||||||
const headerLineContent = document.body.querySelectorAll('.cm-headerLine > span');
|
const headerLineContent = document.body.querySelectorAll('.cm-headerLine > span');
|
||||||
expect(headerLineContent.length).toBeGreaterThanOrEqual(1);
|
expect(headerLineContent.length).toBeGreaterThanOrEqual(1);
|
||||||
for (const part of headerLineContent) {
|
|
||||||
const style = getComputedStyle(part);
|
|
||||||
expect(style.fontSize).toBe('1.6em');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
editor.remove();
|
editor.remove();
|
||||||
|
|
|
@ -48,8 +48,28 @@ const blockQuoteDecoration = Decoration.line({
|
||||||
attributes: { class: 'cm-blockQuote' },
|
attributes: { class: 'cm-blockQuote' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const headerLineDecoration = Decoration.line({
|
const header1LineDecoration = Decoration.line({
|
||||||
attributes: { class: 'cm-headerLine' },
|
attributes: { class: 'cm-h1 cm-headerLine' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const header2LineDecoration = Decoration.line({
|
||||||
|
attributes: { class: 'cm-h2 cm-headerLine' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const header3LineDecoration = Decoration.line({
|
||||||
|
attributes: { class: 'cm-h3 cm-headerLine' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const header4LineDecoration = Decoration.line({
|
||||||
|
attributes: { class: 'cm-h4 cm-headerLine' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const header5LineDecoration = Decoration.line({
|
||||||
|
attributes: { class: 'cm-h5 cm-headerLine' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const header6LineDecoration = Decoration.line({
|
||||||
|
attributes: { class: 'cm-h6 cm-headerLine' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const tableHeaderDecoration = Decoration.line({
|
const tableHeaderDecoration = Decoration.line({
|
||||||
|
@ -72,6 +92,37 @@ const taskMarkerDecoration = Decoration.mark({
|
||||||
attributes: { class: 'cm-taskMarker' },
|
attributes: { class: 'cm-taskMarker' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const nodeNameToLineDecoration: Record<string, Decoration> = {
|
||||||
|
'FencedCode': codeBlockDecoration,
|
||||||
|
'CodeBlock': codeBlockDecoration,
|
||||||
|
'BlockMath': mathBlockDecoration,
|
||||||
|
'Blockquote': blockQuoteDecoration,
|
||||||
|
|
||||||
|
'SetextHeading1': header1LineDecoration,
|
||||||
|
'ATXHeading1': header1LineDecoration,
|
||||||
|
'SetextHeading2': header2LineDecoration,
|
||||||
|
'ATXHeading2': header2LineDecoration,
|
||||||
|
'ATXHeading3': header3LineDecoration,
|
||||||
|
'ATXHeading4': header4LineDecoration,
|
||||||
|
'ATXHeading5': header5LineDecoration,
|
||||||
|
'ATXHeading6': header6LineDecoration,
|
||||||
|
|
||||||
|
'TableHeader': tableHeaderDecoration,
|
||||||
|
'TableDelimiter': tableDelimiterDecoration,
|
||||||
|
'TableRow': tableBodyDecoration,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nodeNameToMarkDecoration: Record<string, Decoration> = {
|
||||||
|
'InlineCode': inlineCodeDecoration,
|
||||||
|
'URL': urlDecoration,
|
||||||
|
'InlineMath': inlineMathDecoration,
|
||||||
|
'HTMLTag': htmlTagNameDecoration,
|
||||||
|
'TagName': htmlTagNameDecoration,
|
||||||
|
'HorizontalRule': horizontalRuleDecoration,
|
||||||
|
'TaskMarker': taskMarkerDecoration,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
type DecorationDescription = { pos: number; length?: number; decoration: Decoration };
|
type DecorationDescription = { pos: number; length?: number; decoration: Decoration };
|
||||||
|
|
||||||
// Returns a set of [Decoration]s, associated with block syntax groups that require
|
// Returns a set of [Decoration]s, associated with block syntax groups that require
|
||||||
|
@ -116,58 +167,15 @@ const computeDecorations = (view: EditorView) => {
|
||||||
const viewFrom = Math.max(from, node.from);
|
const viewFrom = Math.max(from, node.from);
|
||||||
const viewTo = Math.min(to, node.to);
|
const viewTo = Math.min(to, node.to);
|
||||||
|
|
||||||
switch (node.name) {
|
if (nodeNameToLineDecoration.hasOwnProperty(node.name)) {
|
||||||
case 'FencedCode':
|
const decoration = nodeNameToLineDecoration[node.name];
|
||||||
case 'CodeBlock':
|
addDecorationToLines(viewFrom, viewTo, decoration);
|
||||||
addDecorationToLines(viewFrom, viewTo, codeBlockDecoration);
|
|
||||||
blockDecorated = true;
|
blockDecorated = true;
|
||||||
break;
|
}
|
||||||
case 'BlockMath':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, mathBlockDecoration);
|
if (nodeNameToMarkDecoration.hasOwnProperty(node.name)) {
|
||||||
blockDecorated = true;
|
const decoration = nodeNameToMarkDecoration[node.name];
|
||||||
break;
|
addDecorationToRange(viewFrom, viewTo, decoration);
|
||||||
case 'Blockquote':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, blockQuoteDecoration);
|
|
||||||
blockDecorated = true;
|
|
||||||
break;
|
|
||||||
case 'InlineMath':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, inlineMathDecoration);
|
|
||||||
break;
|
|
||||||
case 'InlineCode':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, inlineCodeDecoration);
|
|
||||||
break;
|
|
||||||
case 'URL':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, urlDecoration);
|
|
||||||
break;
|
|
||||||
case 'SetextHeading1':
|
|
||||||
case 'SetextHeading2':
|
|
||||||
case 'ATXHeading1':
|
|
||||||
case 'ATXHeading2':
|
|
||||||
case 'ATXHeading3':
|
|
||||||
case 'ATXHeading4':
|
|
||||||
case 'ATXHeading5':
|
|
||||||
case 'ATXHeading6':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, headerLineDecoration);
|
|
||||||
break;
|
|
||||||
case 'HTMLTag':
|
|
||||||
case 'TagName':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, htmlTagNameDecoration);
|
|
||||||
break;
|
|
||||||
case 'TableHeader':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, tableHeaderDecoration);
|
|
||||||
break;
|
|
||||||
case 'TableDelimiter':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, tableDelimiterDecoration);
|
|
||||||
break;
|
|
||||||
case 'TableRow':
|
|
||||||
addDecorationToLines(viewFrom, viewTo, tableBodyDecoration);
|
|
||||||
break;
|
|
||||||
case 'HorizontalRule':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, horizontalRuleDecoration);
|
|
||||||
break;
|
|
||||||
case 'TaskMarker':
|
|
||||||
addDecorationToRange(viewFrom, viewTo, taskMarkerDecoration);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only block decorations will have differing first and last lines
|
// Only block decorations will have differing first and last lines
|
||||||
|
|
|
@ -78,6 +78,11 @@ const createTheme = (theme: any): Extension[] => {
|
||||||
// be at least this specific.
|
// be at least this specific.
|
||||||
const selectionBackgroundSelector = '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground';
|
const selectionBackgroundSelector = '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground';
|
||||||
|
|
||||||
|
const baseHeadingStyle = {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontFamily: theme.fontFamily,
|
||||||
|
};
|
||||||
|
|
||||||
const codeMirrorTheme = EditorView.theme({
|
const codeMirrorTheme = EditorView.theme({
|
||||||
'&': baseGlobalStyle,
|
'&': baseGlobalStyle,
|
||||||
|
|
||||||
|
@ -145,7 +150,7 @@ const createTheme = (theme: any): Extension[] => {
|
||||||
// span with a larger font-size, the .cm-inlineCode's bounding box won't
|
// span with a larger font-size, the .cm-inlineCode's bounding box won't
|
||||||
// be big enough for its content.
|
// be big enough for its content.
|
||||||
// As such, we need to style whichever element directly wraps its content.
|
// As such, we need to style whichever element directly wraps its content.
|
||||||
'& .cm-headerLine > .cm-inlineCode > *, & :not(.cm-headerLine) > .cm-inlineCode': {
|
'& .cm-inlineCode': {
|
||||||
borderWidth: '1px',
|
borderWidth: '1px',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderColor: isDarkTheme ? 'rgba(200, 200, 200, 0.5)' : 'rgba(100, 100, 100, 0.5)',
|
borderColor: isDarkTheme ? 'rgba(200, 200, 200, 0.5)' : 'rgba(100, 100, 100, 0.5)',
|
||||||
|
@ -166,6 +171,34 @@ const createTheme = (theme: any): Extension[] => {
|
||||||
opacity: theme.isDesktop ? 0.6 : 1,
|
opacity: theme.isDesktop ? 0.6 : 1,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Applying font size changes with CSS rather than the theme below works
|
||||||
|
// around an issue where the border for code blocks in headings was too
|
||||||
|
// small.
|
||||||
|
'& .cm-h1': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.6em',
|
||||||
|
},
|
||||||
|
'& .cm-h2': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.4em',
|
||||||
|
},
|
||||||
|
'& .cm-h3': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.3em',
|
||||||
|
},
|
||||||
|
'& .cm-h4': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.2em',
|
||||||
|
},
|
||||||
|
'& .cm-h5': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.1em',
|
||||||
|
},
|
||||||
|
'& .cm-h6': {
|
||||||
|
...baseHeadingStyle,
|
||||||
|
fontSize: '1.0em',
|
||||||
|
},
|
||||||
|
|
||||||
// Style the search widget. Use ':root' to increase the selector's precedence
|
// Style the search widget. Use ':root' to increase the selector's precedence
|
||||||
// (override the existing preset styles).
|
// (override the existing preset styles).
|
||||||
':root & .cm-panel.cm-search': {
|
':root & .cm-panel.cm-search': {
|
||||||
|
@ -176,11 +209,6 @@ const createTheme = (theme: any): Extension[] => {
|
||||||
},
|
},
|
||||||
}, { dark: isDarkTheme });
|
}, { dark: isDarkTheme });
|
||||||
|
|
||||||
const baseHeadingStyle = {
|
|
||||||
fontWeight: 'bold',
|
|
||||||
fontFamily: theme.fontFamily,
|
|
||||||
};
|
|
||||||
|
|
||||||
const highlightingStyle = HighlightStyle.define([
|
const highlightingStyle = HighlightStyle.define([
|
||||||
{
|
{
|
||||||
tag: tags.strong,
|
tag: tags.strong,
|
||||||
|
@ -190,36 +218,6 @@ const createTheme = (theme: any): Extension[] => {
|
||||||
tag: tags.emphasis,
|
tag: tags.emphasis,
|
||||||
fontStyle: 'italic',
|
fontStyle: 'italic',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading1,
|
|
||||||
fontSize: '1.6em',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading2,
|
|
||||||
fontSize: '1.4em',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading3,
|
|
||||||
fontSize: '1.3em',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading4,
|
|
||||||
fontSize: '1.2em',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading5,
|
|
||||||
fontSize: '1.1em',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...baseHeadingStyle,
|
|
||||||
tag: tags.heading6,
|
|
||||||
fontSize: '1.0em',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
tag: tags.list,
|
tag: tags.list,
|
||||||
fontFamily: theme.fontFamily,
|
fontFamily: theme.fontFamily,
|
||||||
|
|
Loading…
Reference in New Issue