mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-12-27 07:03:48 +00:00
added a spoiler container (#947)
changed toolbar to insert the new spoiler container changed tests accordingly References: https://github.com/markdown-it/markdown-it-container Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
9330adf564
commit
7be64bc582
9 changed files with 60 additions and 18 deletions
|
@ -63,7 +63,7 @@ describe('Autocompletion', () => {
|
|||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span')
|
||||
.should('have.text', ':::success')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span')
|
||||
.should('have.text', ':::')
|
||||
.should('have.text', '::: ')
|
||||
cy.get('.markdown-body > div.alert')
|
||||
.should('exist')
|
||||
})
|
||||
|
@ -78,7 +78,7 @@ describe('Autocompletion', () => {
|
|||
cy.get('.CodeMirror-code > div:nth-of-type(1) > .CodeMirror-line > span > span')
|
||||
.should('have.text', ':::success')
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(3) > .CodeMirror-line > span span')
|
||||
.should('have.text', ':::')
|
||||
.should('have.text', '::: ')
|
||||
cy.get('.markdown-body > div.alert')
|
||||
.should('exist')
|
||||
})
|
||||
|
|
|
@ -322,7 +322,7 @@ describe('Toolbar', () => {
|
|||
cy.get('.fa-caret-square-o-down')
|
||||
.click()
|
||||
cy.get('.CodeMirror-code > div:nth-of-type(2) > .CodeMirror-line > span span')
|
||||
.should('have.text', '<details>')
|
||||
.should('have.text', ':::spoiler Toggle label')
|
||||
})
|
||||
|
||||
it('comment', () => {
|
||||
|
|
|
@ -5,12 +5,20 @@
|
|||
*/
|
||||
|
||||
import { Editor, Hint, Hints, Pos } from 'codemirror'
|
||||
import { validAlertLevels } from '../../../markdown-renderer/markdown-it-plugins/alert-container'
|
||||
import { findWordAtCursor, Hinter } from './index'
|
||||
|
||||
const wordRegExp = /^:::((\w|-|_|\+)*)$/
|
||||
const allSupportedConatiner = ['success', 'info', 'warning', 'danger']
|
||||
const spoilerSuggestion: Hint = {
|
||||
text: ':::spoiler Toggle label\nToggled content\n::: \n',
|
||||
displayText: 'spoiler'
|
||||
}
|
||||
const suggestions = validAlertLevels.map((suggestion: string): Hint => ({
|
||||
text: ':::' + suggestion + '\n\n::: \n',
|
||||
displayText: suggestion
|
||||
})).concat(spoilerSuggestion)
|
||||
|
||||
const containerHint = (editor: Editor): Promise< Hints| null > => {
|
||||
const containerHint = (editor: Editor): Promise<Hints | null> => {
|
||||
return new Promise((resolve) => {
|
||||
const searchTerm = findWordAtCursor(editor)
|
||||
const searchResult = wordRegExp.exec(searchTerm.text)
|
||||
|
@ -18,16 +26,12 @@ const containerHint = (editor: Editor): Promise< Hints| null > => {
|
|||
resolve(null)
|
||||
return
|
||||
}
|
||||
const suggestions = allSupportedConatiner
|
||||
const cursor = editor.getCursor()
|
||||
if (!suggestions) {
|
||||
resolve(null)
|
||||
} else {
|
||||
resolve({
|
||||
list: suggestions.map((suggestion: string): Hint => ({
|
||||
text: ':::' + suggestion + '\n\n:::\n',
|
||||
displayText: suggestion
|
||||
})),
|
||||
list: suggestions.filter((suggestion) => suggestion.displayText?.startsWith(searchResult[1])),
|
||||
from: Pos(cursor.line, searchTerm.start),
|
||||
to: Pos(cursor.line, searchTerm.end)
|
||||
})
|
||||
|
|
|
@ -64,5 +64,5 @@ export const allHinters: Hinter[] = [
|
|||
ImageHinter,
|
||||
LinkAndExtraTagHinter,
|
||||
PDFHinter,
|
||||
CollapsableBlockHinter
|
||||
CollapsableBlockHinter,
|
||||
]
|
||||
|
|
|
@ -929,7 +929,7 @@ describe('test collapsable block', () => {
|
|||
listSelections: mockListSelections(cursor, true),
|
||||
getLine: (): string => (textFirstLine),
|
||||
replaceRange: (replacement: string | string[]) => {
|
||||
expect(replacement).toEqual(`${textFirstLine}\n<details>\n <summary>Toggle label</summary>\n Toggled content\n</details>`)
|
||||
expect(replacement).toEqual(`${textFirstLine}\n:::spoiler Toggle label\n Toggled content\n:::`)
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
@ -941,7 +941,7 @@ describe('test collapsable block', () => {
|
|||
getCursor: () => cursor.from,
|
||||
listSelections: mockListSelections(firstLine, false),
|
||||
getLine: (): string => (textFirstLine),
|
||||
replaceRange: expectFromToReplacement(firstLine, `${textFirstLine}\n<details>\n <summary>Toggle label</summary>\n Toggled content\n</details>`, done)
|
||||
replaceRange: expectFromToReplacement(firstLine, `${textFirstLine}\n:::spoiler Toggle label\n Toggled content\n:::`, done)
|
||||
})
|
||||
addCollapsableBlock(editor)
|
||||
})
|
||||
|
@ -952,7 +952,7 @@ describe('test collapsable block', () => {
|
|||
listSelections: mockListSelections(multiline, false),
|
||||
getLine: (): string => '2nd line',
|
||||
replaceRange: (replacement: string | string[]) => {
|
||||
expect(replacement).toEqual('2nd line\n<details>\n <summary>Toggle label</summary>\n Toggled content\n</details>')
|
||||
expect(replacement).toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
@ -965,7 +965,7 @@ describe('test collapsable block', () => {
|
|||
listSelections: mockListSelections(multilineOffset, false),
|
||||
getLine: (): string => '2nd line',
|
||||
replaceRange: (replacement: string | string[]) => {
|
||||
expect(replacement).toEqual('2nd line\n<details>\n <summary>Toggle label</summary>\n Toggled content\n</details>')
|
||||
expect(replacement).toEqual('2nd line\n:::spoiler Toggle label\n Toggled content\n:::')
|
||||
done()
|
||||
}
|
||||
})
|
||||
|
|
|
@ -28,7 +28,7 @@ export const addTaskList = (editor: Editor): void => createList(editor, () => '-
|
|||
export const addImage = (editor: Editor): void => addLink(editor, '!')
|
||||
|
||||
export const addLine = (editor: Editor): void => changeLines(editor, line => `${line}\n----`)
|
||||
export const addCollapsableBlock = (editor: Editor): void => changeLines(editor, line => `${line}\n<details>\n <summary>Toggle label</summary>\n Toggled content\n</details>`)
|
||||
export const addCollapsableBlock = (editor: Editor): void => changeLines(editor, line => `${line}\n:::spoiler Toggle label\n Toggled content\n:::`)
|
||||
export const addComment = (editor: Editor): void => changeLines(editor, line => `${line}\n> []`)
|
||||
export const addTable = (editor: Editor, rows: number, columns: number): void => {
|
||||
const rowArray = createNumberRangeArray(rows)
|
||||
|
|
|
@ -16,6 +16,7 @@ import superscript from 'markdown-it-sup'
|
|||
import { alertContainer } from '../markdown-it-plugins/alert-container'
|
||||
import { linkifyExtra } from '../markdown-it-plugins/linkify-extra'
|
||||
import { MarkdownItParserDebugger } from '../markdown-it-plugins/parser-debugger'
|
||||
import { spoilerContainer } from '../markdown-it-plugins/spoiler-container'
|
||||
import { tasksLists } from '../markdown-it-plugins/tasks-lists'
|
||||
import { twitterEmojis } from '../markdown-it-plugins/twitter-emojis'
|
||||
import { MarkdownItConfigurator } from './MarkdownItConfigurator'
|
||||
|
@ -33,7 +34,8 @@ export class BasicMarkdownItConfigurator extends MarkdownItConfigurator {
|
|||
footnote,
|
||||
imsize,
|
||||
tasksLists,
|
||||
alertContainer
|
||||
alertContainer,
|
||||
spoilerContainer
|
||||
)
|
||||
this.postConfigurations.push(
|
||||
linkifyExtra,
|
||||
|
|
|
@ -10,7 +10,7 @@ import Renderer from 'markdown-it/lib/renderer'
|
|||
import Token from 'markdown-it/lib/token'
|
||||
import { MarkdownItPlugin } from '../replace-components/ComponentReplacer'
|
||||
|
||||
type RenderContainerReturn = (tokens: Token[], index: number, options: MarkdownIt.Options, env: unknown, self: Renderer) => void;
|
||||
export type RenderContainerReturn = (tokens: Token[], index: number, options: MarkdownIt.Options, env: unknown, self: Renderer) => string;
|
||||
type ValidAlertLevels = ('warning' | 'danger' | 'success' | 'info')
|
||||
export const validAlertLevels: ValidAlertLevels[] = ['success', 'danger', 'info', 'warning']
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { escapeHtml } from 'markdown-it/lib/common/utils'
|
||||
import markdownItContainer from 'markdown-it-container'
|
||||
import Token from 'markdown-it/lib/token'
|
||||
import { MarkdownItPlugin } from '../replace-components/ComponentReplacer'
|
||||
import { RenderContainerReturn } from './alert-container'
|
||||
|
||||
export const spoilerRegEx = /^spoiler\s+(.*)$/;
|
||||
|
||||
const createSpoilerContainer = (): RenderContainerReturn => {
|
||||
return (tokens: Token[], index: number) => {
|
||||
const matches = spoilerRegEx.exec(tokens[index].info.trim())
|
||||
|
||||
if (tokens[index].nesting === 1 && matches && matches[1]) {
|
||||
// opening tag
|
||||
return `<details><summary>${escapeHtml(matches[1])}</summary>`
|
||||
|
||||
} else {
|
||||
// closing tag
|
||||
return '</details>\n'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const spoilerContainer: MarkdownItPlugin = (markdownIt: MarkdownIt) => {
|
||||
markdownItContainer(markdownIt, 'spoiler', {
|
||||
validate: (params: string) => spoilerRegEx.test(params),
|
||||
render: createSpoilerContainer()
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue