mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-28 05:54:43 -04:00
Move frontmatter extraction from renderer to redux (#1413)
This commit is contained in:
parent
7fb7c55877
commit
04e16d8880
34 changed files with 680 additions and 589 deletions
45
src/redux/note-details/initial-state.ts
Normal file
45
src/redux/note-details/initial-state.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { NoteDetails } from './types'
|
||||
import { DateTime } from 'luxon'
|
||||
import { NoteTextDirection, NoteType } from '../../components/common/note-frontmatter/types'
|
||||
|
||||
export const initialState: NoteDetails = {
|
||||
documentContent: '',
|
||||
markdownContent: '',
|
||||
rawFrontmatter: '',
|
||||
frontmatterRendererInfo: {
|
||||
frontmatterInvalid: false,
|
||||
deprecatedSyntax: false,
|
||||
offsetLines: 0
|
||||
},
|
||||
id: '',
|
||||
createTime: DateTime.fromSeconds(0),
|
||||
lastChange: {
|
||||
timestamp: DateTime.fromSeconds(0),
|
||||
userName: ''
|
||||
},
|
||||
alias: '',
|
||||
viewCount: 0,
|
||||
authorship: [],
|
||||
noteTitle: '',
|
||||
firstHeading: '',
|
||||
frontmatter: {
|
||||
title: '',
|
||||
description: '',
|
||||
tags: [],
|
||||
deprecatedTagsSyntax: false,
|
||||
robots: '',
|
||||
lang: 'en',
|
||||
dir: NoteTextDirection.LTR,
|
||||
breaks: true,
|
||||
GA: '',
|
||||
disqus: '',
|
||||
type: NoteType.DOCUMENT,
|
||||
opengraph: new Map<string, string>()
|
||||
}
|
||||
}
|
|
@ -6,31 +6,40 @@
|
|||
|
||||
import { store } from '..'
|
||||
import { NoteDto } from '../../api/notes/types'
|
||||
import { NoteFrontmatter } from '../../components/editor-page/note-frontmatter/note-frontmatter'
|
||||
import { initialState } from './reducers'
|
||||
import {
|
||||
NoteDetailsActionType,
|
||||
SetCheckboxInMarkdownContentAction,
|
||||
SetNoteDetailsAction,
|
||||
SetNoteDetailsFromServerAction,
|
||||
SetNoteFrontmatterFromRenderingAction,
|
||||
UpdateNoteTitleByFirstHeadingAction
|
||||
SetNoteDocumentContentAction,
|
||||
UpdateNoteTitleByFirstHeadingAction,
|
||||
UpdateTaskListCheckboxAction
|
||||
} from './types'
|
||||
|
||||
export const setNoteMarkdownContent = (content: string): void => {
|
||||
/**
|
||||
* Sets the content of the current note, extracts and parses the frontmatter and extracts the markdown content part.
|
||||
* @param content The note content as it is written inside the editor pane.
|
||||
*/
|
||||
export const setNoteContent = (content: string): void => {
|
||||
store.dispatch({
|
||||
type: NoteDetailsActionType.SET_DOCUMENT_CONTENT,
|
||||
content
|
||||
} as SetNoteDetailsAction)
|
||||
content: content
|
||||
} as SetNoteDocumentContentAction)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the note metadata for the current note from an API response DTO to the redux.
|
||||
* @param apiResponse The NoteDTO received from the API to store into redux.
|
||||
*/
|
||||
export const setNoteDataFromServer = (apiResponse: NoteDto): void => {
|
||||
store.dispatch({
|
||||
type: NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER,
|
||||
note: apiResponse
|
||||
dto: apiResponse
|
||||
} as SetNoteDetailsFromServerAction)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the note title in the redux by the first heading found in the markdown content.
|
||||
* @param firstHeading The content of the first heading found in the markdown content.
|
||||
*/
|
||||
export const updateNoteTitleByFirstHeading = (firstHeading?: string): void => {
|
||||
store.dispatch({
|
||||
type: NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING,
|
||||
|
@ -38,20 +47,15 @@ export const updateNoteTitleByFirstHeading = (firstHeading?: string): void => {
|
|||
} as UpdateNoteTitleByFirstHeadingAction)
|
||||
}
|
||||
|
||||
export const setNoteFrontmatter = (frontmatter: NoteFrontmatter | undefined): void => {
|
||||
if (!frontmatter) {
|
||||
frontmatter = initialState.frontmatter
|
||||
}
|
||||
/**
|
||||
* Changes a checkbox state in the note document content. Triggered when a checkbox in the rendering is clicked.
|
||||
* @param lineInDocumentContent The line in the document content to change.
|
||||
* @param checked true if the checkbox is checked, false otherwise.
|
||||
*/
|
||||
export const setCheckboxInMarkdownContent = (lineInDocumentContent: number, checked: boolean): void => {
|
||||
store.dispatch({
|
||||
type: NoteDetailsActionType.SET_NOTE_FRONTMATTER,
|
||||
frontmatter: frontmatter
|
||||
} as SetNoteFrontmatterFromRenderingAction)
|
||||
}
|
||||
|
||||
export const setCheckboxInMarkdownContent = (lineInMarkdown: number, checked: boolean): void => {
|
||||
store.dispatch({
|
||||
type: NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT,
|
||||
checked: checked,
|
||||
lineInMarkdown: lineInMarkdown
|
||||
} as SetCheckboxInMarkdownContentAction)
|
||||
type: NoteDetailsActionType.UPDATE_TASK_LIST_CHECKBOX,
|
||||
checkboxChecked: checked,
|
||||
changedLine: lineInDocumentContent
|
||||
} as UpdateTaskListCheckboxAction)
|
||||
}
|
||||
|
|
194
src/redux/note-details/reducer.ts
Normal file
194
src/redux/note-details/reducer.ts
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Reducer } from 'redux'
|
||||
import { PresentFrontmatterExtractionResult } from '../../components/common/note-frontmatter/types'
|
||||
import { NoteFrontmatter } from '../../components/common/note-frontmatter/note-frontmatter'
|
||||
import { NoteDetails, NoteDetailsActions, NoteDetailsActionType } from './types'
|
||||
import { extractFrontmatter } from '../../components/common/note-frontmatter/extract-frontmatter'
|
||||
import { NoteDto } from '../../api/notes/types'
|
||||
import { initialState } from './initial-state'
|
||||
import { DateTime } from 'luxon'
|
||||
|
||||
export const NoteDetailsReducer: Reducer<NoteDetails, NoteDetailsActions> = (
|
||||
state: NoteDetails = initialState,
|
||||
action: NoteDetailsActions
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case NoteDetailsActionType.SET_DOCUMENT_CONTENT:
|
||||
return buildStateFromDocumentContentUpdate(state, action.content)
|
||||
case NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING:
|
||||
return buildStateFromFirstHeadingUpdate(state, action.firstHeading)
|
||||
case NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER:
|
||||
return buildStateFromServerDto(action.dto)
|
||||
case NoteDetailsActionType.UPDATE_TASK_LIST_CHECKBOX:
|
||||
return buildStateFromTaskListUpdate(state, action.changedLine, action.checkboxChecked)
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const TASK_REGEX = /(\s*(?:[-*+]|\d+[.)]) )(\[[ xX]])( .*)/
|
||||
|
||||
/**
|
||||
* Builds a {@link NoteDetails} redux state from a DTO received as an API response.
|
||||
* @param dto The first DTO received from the API containing the relevant information about the note.
|
||||
* @return An updated {@link NoteDetails} redux state.
|
||||
*/
|
||||
const buildStateFromServerDto = (dto: NoteDto): NoteDetails => {
|
||||
const newState = convertNoteDtoToNoteDetails(dto)
|
||||
return buildStateFromDocumentContentUpdate(newState, newState.documentContent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link NoteDetails} redux state where a checkbox in the markdown content either gets checked or unchecked.
|
||||
* @param state The previous redux state.
|
||||
* @param changedLine The number of the line in which the checkbox should be updated.
|
||||
* @param checkboxChecked true if the checkbox should be checked, false otherwise.
|
||||
* @return An updated {@link NoteDetails} redux state.
|
||||
*/
|
||||
const buildStateFromTaskListUpdate = (
|
||||
state: NoteDetails,
|
||||
changedLine: number,
|
||||
checkboxChecked: boolean
|
||||
): NoteDetails => {
|
||||
const lines = state.documentContent.split('\n')
|
||||
const results = TASK_REGEX.exec(lines[changedLine])
|
||||
if (results) {
|
||||
const before = results[1]
|
||||
const after = results[3]
|
||||
lines[changedLine] = `${before}[${checkboxChecked ? 'x' : ' '}]${after}`
|
||||
return buildStateFromDocumentContentUpdate(state, lines.join('\n'))
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link NoteDetails} redux state from a fresh document content.
|
||||
* @param state The previous redux state.
|
||||
* @param documentContent The fresh document content consisting of the frontmatter and markdown part.
|
||||
* @return An updated {@link NoteDetails} redux state.
|
||||
*/
|
||||
const buildStateFromDocumentContentUpdate = (state: NoteDetails, documentContent: string): NoteDetails => {
|
||||
const frontmatterExtraction = extractFrontmatter(documentContent)
|
||||
if (!frontmatterExtraction.frontmatterPresent) {
|
||||
return {
|
||||
...state,
|
||||
documentContent: documentContent,
|
||||
markdownContent: documentContent,
|
||||
rawFrontmatter: '',
|
||||
frontmatter: initialState.frontmatter,
|
||||
frontmatterRendererInfo: initialState.frontmatterRendererInfo
|
||||
}
|
||||
}
|
||||
return buildStateFromFrontmatterUpdate(
|
||||
{
|
||||
...state,
|
||||
documentContent: documentContent,
|
||||
markdownContent: documentContent.split('\n').slice(frontmatterExtraction.frontmatterLines).join('\n')
|
||||
},
|
||||
frontmatterExtraction
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link NoteDetails} redux state from extracted frontmatter data.
|
||||
* @param state The previous redux state.
|
||||
* @param frontmatterExtraction The result of the frontmatter extraction containing the raw data and the line offset.
|
||||
* @return An updated {@link NoteDetails} redux state.
|
||||
*/
|
||||
const buildStateFromFrontmatterUpdate = (
|
||||
state: NoteDetails,
|
||||
frontmatterExtraction: PresentFrontmatterExtractionResult
|
||||
): NoteDetails => {
|
||||
if (frontmatterExtraction.rawFrontmatterText === state.rawFrontmatter) {
|
||||
return state
|
||||
}
|
||||
try {
|
||||
const frontmatter = NoteFrontmatter.createFromYaml(frontmatterExtraction.rawFrontmatterText)
|
||||
return {
|
||||
...state,
|
||||
rawFrontmatter: frontmatterExtraction.rawFrontmatterText,
|
||||
frontmatter: frontmatter,
|
||||
noteTitle: generateNoteTitle(frontmatter),
|
||||
frontmatterRendererInfo: {
|
||||
offsetLines: frontmatterExtraction.frontmatterLines,
|
||||
deprecatedSyntax: frontmatter.deprecatedTagsSyntax,
|
||||
frontmatterInvalid: false
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
...state,
|
||||
rawFrontmatter: frontmatterExtraction.rawFrontmatterText,
|
||||
frontmatter: initialState.frontmatter,
|
||||
frontmatterRendererInfo: {
|
||||
offsetLines: frontmatterExtraction.frontmatterLines,
|
||||
deprecatedSyntax: false,
|
||||
frontmatterInvalid: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link NoteDetails} redux state with an updated note title from frontmatter data and the first heading.
|
||||
* @param state The previous redux state.
|
||||
* @param firstHeading The first heading of the document. Should be {@code undefined} if there is no such heading.
|
||||
* @return An updated {@link NoteDetails} redux state.
|
||||
*/
|
||||
const buildStateFromFirstHeadingUpdate = (state: NoteDetails, firstHeading?: string): NoteDetails => {
|
||||
return {
|
||||
...state,
|
||||
firstHeading: firstHeading,
|
||||
noteTitle: generateNoteTitle(state.frontmatter, firstHeading)
|
||||
}
|
||||
}
|
||||
|
||||
const generateNoteTitle = (frontmatter: NoteFrontmatter, firstHeading?: string) => {
|
||||
if (frontmatter?.title && frontmatter?.title !== '') {
|
||||
return frontmatter.title.trim()
|
||||
} else if (
|
||||
frontmatter?.opengraph &&
|
||||
frontmatter?.opengraph.get('title') &&
|
||||
frontmatter?.opengraph.get('title') !== ''
|
||||
) {
|
||||
return (frontmatter?.opengraph.get('title') ?? firstHeading ?? '').trim()
|
||||
} else {
|
||||
return (firstHeading ?? firstHeading ?? '').trim()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a note DTO from the HTTP API to a {@link NoteDetails} object.
|
||||
* Note that the documentContent will be set but the markdownContent and rawFrontmatterContent are yet to be processed.
|
||||
* @param note The NoteDTO as defined in the backend.
|
||||
* @return The NoteDetails object corresponding to the DTO.
|
||||
*/
|
||||
const convertNoteDtoToNoteDetails = (note: NoteDto): NoteDetails => {
|
||||
return {
|
||||
documentContent: note.content,
|
||||
markdownContent: '',
|
||||
rawFrontmatter: '',
|
||||
frontmatterRendererInfo: {
|
||||
frontmatterInvalid: false,
|
||||
deprecatedSyntax: false,
|
||||
offsetLines: 0
|
||||
},
|
||||
frontmatter: initialState.frontmatter,
|
||||
id: note.metadata.id,
|
||||
noteTitle: initialState.noteTitle,
|
||||
createTime: DateTime.fromISO(note.metadata.createTime),
|
||||
lastChange: {
|
||||
userName: note.metadata.updateUser.userName,
|
||||
timestamp: DateTime.fromISO(note.metadata.updateTime)
|
||||
},
|
||||
firstHeading: initialState.firstHeading,
|
||||
viewCount: note.metadata.viewCount,
|
||||
alias: note.metadata.alias,
|
||||
authorship: note.metadata.editedBy
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { DateTime } from 'luxon'
|
||||
import { Reducer } from 'redux'
|
||||
import {
|
||||
NoteFrontmatter,
|
||||
NoteTextDirection,
|
||||
NoteType
|
||||
} from '../../components/editor-page/note-frontmatter/note-frontmatter'
|
||||
import { NoteDetails, NoteDetailsActions, NoteDetailsActionType } from './types'
|
||||
import { noteDtoToNoteDetails } from '../../api/notes/dto-methods'
|
||||
|
||||
export const initialState: NoteDetails = {
|
||||
markdownContent: '',
|
||||
id: '',
|
||||
createTime: DateTime.fromSeconds(0),
|
||||
lastChange: {
|
||||
timestamp: DateTime.fromSeconds(0),
|
||||
userName: ''
|
||||
},
|
||||
alias: '',
|
||||
viewCount: 0,
|
||||
authorship: [],
|
||||
noteTitle: '',
|
||||
firstHeading: '',
|
||||
frontmatter: {
|
||||
title: '',
|
||||
description: '',
|
||||
tags: [],
|
||||
deprecatedTagsSyntax: false,
|
||||
robots: '',
|
||||
lang: 'en',
|
||||
dir: NoteTextDirection.LTR,
|
||||
breaks: true,
|
||||
GA: '',
|
||||
disqus: '',
|
||||
type: NoteType.DOCUMENT,
|
||||
opengraph: new Map<string, string>()
|
||||
}
|
||||
}
|
||||
|
||||
export const NoteDetailsReducer: Reducer<NoteDetails, NoteDetailsActions> = (
|
||||
state: NoteDetails = initialState,
|
||||
action: NoteDetailsActions
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case NoteDetailsActionType.SET_DOCUMENT_CONTENT:
|
||||
return {
|
||||
...state,
|
||||
markdownContent: action.content
|
||||
}
|
||||
case NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING:
|
||||
return {
|
||||
...state,
|
||||
firstHeading: action.firstHeading,
|
||||
noteTitle: generateNoteTitle(state.frontmatter, action.firstHeading)
|
||||
}
|
||||
case NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER:
|
||||
return noteDtoToNoteDetails(action.note)
|
||||
case NoteDetailsActionType.SET_NOTE_FRONTMATTER:
|
||||
return {
|
||||
...state,
|
||||
frontmatter: action.frontmatter,
|
||||
noteTitle: generateNoteTitle(action.frontmatter, state.firstHeading)
|
||||
}
|
||||
case NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT:
|
||||
return {
|
||||
...state,
|
||||
markdownContent: setCheckboxInMarkdownContent(state.markdownContent, action.lineInMarkdown, action.checked)
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const TASK_REGEX = /(\s*(?:[-*+]|\d+[.)]) )(\[[ xX]])( .*)/
|
||||
const setCheckboxInMarkdownContent = (markdownContent: string, lineInMarkdown: number, checked: boolean): string => {
|
||||
const lines = markdownContent.split('\n')
|
||||
const results = TASK_REGEX.exec(lines[lineInMarkdown])
|
||||
if (results) {
|
||||
const before = results[1]
|
||||
const after = results[3]
|
||||
lines[lineInMarkdown] = `${before}[${checked ? 'x' : ' '}]${after}`
|
||||
return lines.join('\n')
|
||||
}
|
||||
return markdownContent
|
||||
}
|
||||
|
||||
const generateNoteTitle = (frontmatter: NoteFrontmatter, firstHeading?: string) => {
|
||||
if (frontmatter?.title && frontmatter?.title !== '') {
|
||||
return frontmatter.title.trim()
|
||||
} else if (
|
||||
frontmatter?.opengraph &&
|
||||
frontmatter?.opengraph.get('title') &&
|
||||
frontmatter?.opengraph.get('title') !== ''
|
||||
) {
|
||||
return (frontmatter?.opengraph.get('title') ?? firstHeading ?? '').trim()
|
||||
} else {
|
||||
return (firstHeading ?? firstHeading ?? '').trim()
|
||||
}
|
||||
}
|
|
@ -6,24 +6,30 @@
|
|||
|
||||
import { DateTime } from 'luxon'
|
||||
import { Action } from 'redux'
|
||||
import { NoteFrontmatter } from '../../components/editor-page/note-frontmatter/note-frontmatter'
|
||||
import { NoteFrontmatter } from '../../components/common/note-frontmatter/note-frontmatter'
|
||||
import { NoteDto } from '../../api/notes/types'
|
||||
import { RendererFrontmatterInfo } from '../../components/common/note-frontmatter/types'
|
||||
|
||||
export enum NoteDetailsActionType {
|
||||
SET_DOCUMENT_CONTENT = 'note-details/set',
|
||||
SET_DOCUMENT_CONTENT = 'note-details/content/set',
|
||||
SET_NOTE_DATA_FROM_SERVER = 'note-details/data/server/set',
|
||||
SET_NOTE_FRONTMATTER = 'note-details/frontmatter/set',
|
||||
UPDATE_NOTE_TITLE_BY_FIRST_HEADING = 'note-details/update-note-title-by-first-heading',
|
||||
SET_CHECKBOX_IN_MARKDOWN_CONTENT = 'note-details/toggle-checkbox-in-markdown-content'
|
||||
UPDATE_TASK_LIST_CHECKBOX = 'note-details/update-task-list-checkbox'
|
||||
}
|
||||
|
||||
interface LastChange {
|
||||
userName: string
|
||||
timestamp: DateTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Redux state containing the currently loaded note with its content and metadata.
|
||||
*/
|
||||
export interface NoteDetails {
|
||||
documentContent: string
|
||||
markdownContent: string
|
||||
rawFrontmatter: string
|
||||
frontmatter: NoteFrontmatter
|
||||
frontmatterRendererInfo: RendererFrontmatterInfo
|
||||
id: string
|
||||
createTime: DateTime
|
||||
lastChange: LastChange
|
||||
|
@ -32,38 +38,43 @@ export interface NoteDetails {
|
|||
authorship: string[]
|
||||
noteTitle: string
|
||||
firstHeading?: string
|
||||
frontmatter: NoteFrontmatter
|
||||
}
|
||||
|
||||
export type NoteDetailsActions =
|
||||
| SetNoteDetailsAction
|
||||
| SetNoteDocumentContentAction
|
||||
| SetNoteDetailsFromServerAction
|
||||
| UpdateNoteTitleByFirstHeadingAction
|
||||
| SetNoteFrontmatterFromRenderingAction
|
||||
| SetCheckboxInMarkdownContentAction
|
||||
| UpdateTaskListCheckboxAction
|
||||
|
||||
export interface SetNoteDetailsAction extends Action<NoteDetailsActionType> {
|
||||
/**
|
||||
* Action for updating the document content of the currently loaded note.
|
||||
*/
|
||||
export interface SetNoteDocumentContentAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.SET_DOCUMENT_CONTENT
|
||||
content: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for overwriting the current state with the data received from the API.
|
||||
*/
|
||||
export interface SetNoteDetailsFromServerAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER
|
||||
note: NoteDto
|
||||
dto: NoteDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for updating the note title of the currently loaded note by using frontmatter data or the first heading.
|
||||
*/
|
||||
export interface UpdateNoteTitleByFirstHeadingAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING
|
||||
firstHeading?: string
|
||||
}
|
||||
|
||||
export interface SetNoteFrontmatterFromRenderingAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.SET_NOTE_FRONTMATTER
|
||||
frontmatter: NoteFrontmatter
|
||||
}
|
||||
|
||||
export interface SetCheckboxInMarkdownContentAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.SET_CHECKBOX_IN_MARKDOWN_CONTENT
|
||||
lineInMarkdown: number
|
||||
checked: boolean
|
||||
/**
|
||||
* Action for manipulating the document content of the currently loaded note by changing the checked state of a task list checkbox.
|
||||
*/
|
||||
export interface UpdateTaskListCheckboxAction extends Action<NoteDetailsActionType> {
|
||||
type: NoteDetailsActionType.UPDATE_TASK_LIST_CHECKBOX
|
||||
changedLine: number
|
||||
checkboxChecked: boolean
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue