mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-06-03 08:28:54 -04:00
fix(deps): replace flexsearch-ts with orama
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
931ce68a32
commit
07162b7807
25 changed files with 266 additions and 215 deletions
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
import { CategoryAccordion } from './category-accordion'
|
||||
import { CheatsheetEntryPane } from './cheatsheet-entry-pane'
|
||||
import type { CheatsheetSingleEntry, CheatsheetExtension } from './cheatsheet-extension'
|
||||
import { hasCheatsheetTopics } from './cheatsheet-extension'
|
||||
import type { CheatsheetExtension, CheatsheetEntry } from './cheatsheet-extension'
|
||||
import { isCheatsheetMultiEntry } from './cheatsheet-extension'
|
||||
import { CheatsheetSearch } from './cheatsheet-search'
|
||||
import styles from './cheatsheet.module.scss'
|
||||
import { TopicSelection } from './topic-selection'
|
||||
|
@ -20,11 +20,11 @@ import { Trans } from 'react-i18next'
|
|||
export const CheatsheetContent: React.FC = () => {
|
||||
const [visibleExtensions, setVisibleExtensions] = useState<CheatsheetExtension[]>([])
|
||||
const [selectedExtension, setSelectedExtension] = useState<CheatsheetExtension>()
|
||||
const [selectedEntry, setSelectedEntry] = useState<CheatsheetSingleEntry>()
|
||||
const [selectedEntry, setSelectedEntry] = useState<CheatsheetEntry>()
|
||||
|
||||
const changeExtension = useCallback((value: CheatsheetExtension) => {
|
||||
setSelectedExtension(value)
|
||||
setSelectedEntry(hasCheatsheetTopics(value) ? value.topics[0] : value)
|
||||
setSelectedEntry(isCheatsheetMultiEntry(value) ? value.topics[0] : value)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
@ -44,10 +44,10 @@ export const CheatsheetContent: React.FC = () => {
|
|||
selectedEntry={selectedEntry}
|
||||
setSelectedEntry={setSelectedEntry}
|
||||
/>
|
||||
{selectedEntry !== undefined ? (
|
||||
{selectedEntry !== undefined && selectedExtension !== undefined ? (
|
||||
<CheatsheetEntryPane
|
||||
rootI18nKey={hasCheatsheetTopics(selectedExtension) ? selectedExtension.i18nKey : undefined}
|
||||
extension={selectedEntry}
|
||||
i18nKeyPrefix={isCheatsheetMultiEntry(selectedExtension) ? selectedExtension.i18nKey : undefined}
|
||||
entry={selectedEntry}
|
||||
/>
|
||||
) : (
|
||||
<span>
|
||||
|
|
|
@ -9,7 +9,7 @@ import { RendererIframe } from '../common/renderer-iframe/renderer-iframe'
|
|||
import { EditorToRendererCommunicatorContextProvider } from '../editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||
import { ExtensionEventEmitterProvider } from '../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import { RendererType } from '../render-page/window-post-message-communicator/rendering-message'
|
||||
import type { CheatsheetSingleEntry } from './cheatsheet-extension'
|
||||
import type { CheatsheetEntry } from './cheatsheet-extension'
|
||||
import { ReadMoreLinkItem } from './read-more-link-item'
|
||||
import { useComponentsFromAppExtensions } from './use-components-from-app-extensions'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
@ -18,8 +18,8 @@ import { ListGroupItem } from 'react-bootstrap'
|
|||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
||||
interface CheatsheetRendererProps {
|
||||
rootI18nKey?: string
|
||||
extension: CheatsheetSingleEntry
|
||||
i18nKeyPrefix?: string
|
||||
entry: CheatsheetEntry
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,7 @@ interface CheatsheetRendererProps {
|
|||
* @param extension The extension to render
|
||||
* @param rootI18nKey An additional i18n namespace
|
||||
*/
|
||||
export const CheatsheetEntryPane: React.FC<CheatsheetRendererProps> = ({ extension, rootI18nKey }) => {
|
||||
export const CheatsheetEntryPane: React.FC<CheatsheetRendererProps> = ({ entry, i18nKeyPrefix }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const [content, setContent] = useState('')
|
||||
|
@ -36,13 +36,13 @@ export const CheatsheetEntryPane: React.FC<CheatsheetRendererProps> = ({ extensi
|
|||
const lines = useMemo(() => content.split('\n'), [content])
|
||||
|
||||
const i18nPrefix = useMemo(
|
||||
() => `cheatsheet.${rootI18nKey ? `${rootI18nKey}.` : ''}${extension.i18nKey}.`,
|
||||
[extension.i18nKey, rootI18nKey]
|
||||
() => `cheatsheet.${i18nKeyPrefix !== undefined ? i18nKeyPrefix + '.' : ''}${entry.i18nKey}.`,
|
||||
[entry.i18nKey, i18nKeyPrefix]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setContent(t(`${i18nPrefix}example`) ?? '')
|
||||
}, [extension, i18nPrefix, t])
|
||||
}, [entry, i18nPrefix, t])
|
||||
|
||||
const cheatsheetExtensionComponents = useComponentsFromAppExtensions(setContent)
|
||||
|
||||
|
@ -62,7 +62,7 @@ export const CheatsheetEntryPane: React.FC<CheatsheetRendererProps> = ({ extensi
|
|||
</h4>
|
||||
{descriptionElements}
|
||||
</ListGroupItem>
|
||||
<ReadMoreLinkItem url={extension.readMoreUrl}></ReadMoreLinkItem>
|
||||
<ReadMoreLinkItem url={entry.readMoreUrl}></ReadMoreLinkItem>
|
||||
<ListGroupItem>
|
||||
<h4>
|
||||
<Trans i18nKey={'cheatsheet.modal.headlines.exampleInput'} />
|
||||
|
|
|
@ -9,29 +9,28 @@ export interface CheatsheetExtensionComponentProps {
|
|||
setContent: (dispatcher: string | ((prevState: string) => string)) => void
|
||||
}
|
||||
|
||||
export type CheatsheetExtension = CheatsheetSingleEntry | CheatsheetEntryWithTopics
|
||||
export type CheatsheetExtension = CheatsheetSingleEntry | CheatsheetMultiEntry
|
||||
|
||||
/**
|
||||
* Determine if a given {@link CheatsheetExtension} is a {@link CheatsheetEntryWithTopics} or just a {@link CheatsheetSingleEntry}.
|
||||
* Determine if a given {@link CheatsheetExtension} is a {@link CheatsheetSingleEntry} or a {@link CheatsheetMultiEntry}.
|
||||
*
|
||||
* @param extension The extension in question
|
||||
* @return boolean
|
||||
*/
|
||||
export const hasCheatsheetTopics = (
|
||||
export const isCheatsheetMultiEntry = (
|
||||
extension: CheatsheetExtension | undefined
|
||||
): extension is CheatsheetEntryWithTopics => {
|
||||
return (extension as CheatsheetEntryWithTopics)?.topics !== undefined
|
||||
): extension is CheatsheetMultiEntry => {
|
||||
return extension !== undefined && typeof (extension as CheatsheetMultiEntry).topics === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an entry with just a name and a bunch of different topics to discuss.
|
||||
*
|
||||
* e.g 'basics.headlines' with the topics 'hashtag' and 'equal'
|
||||
*/
|
||||
export interface CheatsheetEntryWithTopics {
|
||||
export interface CheatsheetMultiEntry {
|
||||
i18nKey: string
|
||||
categoryI18nKey?: string
|
||||
topics: CheatsheetSingleEntry[]
|
||||
categoryI18nKey: string
|
||||
topics: CheatsheetEntry[]
|
||||
}
|
||||
|
||||
export interface CheatsheetSingleEntry extends CheatsheetEntry {
|
||||
categoryI18nKey: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,10 +41,8 @@ export interface CheatsheetEntryWithTopics {
|
|||
*
|
||||
* e.g 'basics.basicFormatting'
|
||||
*/
|
||||
export interface CheatsheetSingleEntry {
|
||||
export interface CheatsheetEntry {
|
||||
i18nKey: string
|
||||
categoryI18nKey?: string
|
||||
cheatsheetExtensionComponent?: React.FC<CheatsheetExtensionComponentProps>
|
||||
|
||||
readMoreUrl?: URL
|
||||
}
|
||||
|
|
|
@ -4,33 +4,18 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { allAppExtensions } from '../../extensions/all-app-extensions'
|
||||
import type { SearchIndexEntry } from '../../hooks/common/use-document-search'
|
||||
import { useDocumentSearch } from '../../hooks/common/use-document-search'
|
||||
import { useCheatsheetSearch } from '../../hooks/common/use-cheatsheet-search'
|
||||
import { useOnInputChange } from '../../hooks/common/use-on-input-change'
|
||||
import { useTranslatedText } from '../../hooks/common/use-translated-text'
|
||||
import { UiIcon } from '../common/icons/ui-icon'
|
||||
import type { CheatsheetSingleEntry, CheatsheetExtension } from './cheatsheet-extension'
|
||||
import { hasCheatsheetTopics } from './cheatsheet-extension'
|
||||
import type { CheatsheetExtension } from './cheatsheet-extension'
|
||||
import { isCheatsheetMultiEntry } from './cheatsheet-extension'
|
||||
import styles from './cheatsheet.module.scss'
|
||||
import type { IndexOptionsForDocumentSearch, StoreOption } from 'flexsearch-ts'
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { FormControl, InputGroup } from 'react-bootstrap'
|
||||
import { X } from 'react-bootstrap-icons'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
interface CheatsheetSearchIndexEntry extends SearchIndexEntry {
|
||||
title: string
|
||||
description: string
|
||||
example: string
|
||||
}
|
||||
|
||||
const searchOptions: IndexOptionsForDocumentSearch<CheatsheetSearchIndexEntry, StoreOption> = {
|
||||
document: {
|
||||
id: 'id',
|
||||
field: ['title', 'description', 'example']
|
||||
}
|
||||
}
|
||||
|
||||
export interface CheatsheetSearchProps {
|
||||
setVisibleExtensions: React.Dispatch<React.SetStateAction<CheatsheetExtension[]>>
|
||||
}
|
||||
|
@ -48,38 +33,43 @@ export const CheatsheetSearch: React.FC<CheatsheetSearchProps> = ({ setVisibleEx
|
|||
() => allAppExtensions.flatMap((extension) => extension.buildCheatsheetExtensions()),
|
||||
[]
|
||||
)
|
||||
const buildSearchIndexEntry = useCallback(
|
||||
(entry: CheatsheetSingleEntry, rootI18nKey: string | undefined = undefined): CheatsheetSearchIndexEntry => {
|
||||
const rootI18nKeyWithDot = rootI18nKey ? `${rootI18nKey}.` : ''
|
||||
const placeholderText = useTranslatedText('cheatsheet.search')
|
||||
|
||||
const buildEntry = useCallback(
|
||||
(i18nKey: string, extensionId: string) => {
|
||||
return {
|
||||
id: rootI18nKey ? rootI18nKey : entry.i18nKey,
|
||||
title: t(`cheatsheet.${rootI18nKeyWithDot}${entry.i18nKey}.title`),
|
||||
description: t(`cheatsheet.${rootI18nKeyWithDot}${entry.i18nKey}.description`),
|
||||
example: t(`cheatsheet.${rootI18nKeyWithDot}${entry.i18nKey}.example`)
|
||||
id: i18nKey,
|
||||
extensionId: extensionId,
|
||||
title: t(`cheatsheet.${i18nKey}.title`),
|
||||
description: t(`cheatsheet.${i18nKey}.description`),
|
||||
example: t(`cheatsheet.${i18nKey}.example`)
|
||||
}
|
||||
},
|
||||
[t]
|
||||
)
|
||||
const placeholderText = useTranslatedText('cheatsheet.search')
|
||||
|
||||
const cheatsheetSearchIndexEntries = useMemo(
|
||||
() =>
|
||||
allCheatsheetExtensions.flatMap((entry) => {
|
||||
if (hasCheatsheetTopics(entry)) {
|
||||
return entry.topics.map((innerEntry) => buildSearchIndexEntry(innerEntry, entry.i18nKey))
|
||||
allCheatsheetExtensions.flatMap((extension) => {
|
||||
if (isCheatsheetMultiEntry(extension)) {
|
||||
return extension.topics.map((entry) => {
|
||||
return buildEntry(extension.i18nKey + '.' + entry.i18nKey, extension.i18nKey)
|
||||
})
|
||||
} else {
|
||||
return buildEntry(extension.i18nKey, extension.i18nKey)
|
||||
}
|
||||
return buildSearchIndexEntry(entry)
|
||||
}),
|
||||
[buildSearchIndexEntry, allCheatsheetExtensions]
|
||||
[allCheatsheetExtensions, buildEntry]
|
||||
)
|
||||
const searchResults = useDocumentSearch(cheatsheetSearchIndexEntries, searchOptions, searchTerm)
|
||||
|
||||
const searchResults = useCheatsheetSearch(cheatsheetSearchIndexEntries, searchTerm)
|
||||
useEffect(() => {
|
||||
if (searchTerm.trim() === '') {
|
||||
setVisibleExtensions(allCheatsheetExtensions)
|
||||
return
|
||||
}
|
||||
const mappedResults = searchResults.flatMap((result) => result.result)
|
||||
const extensionResults = allCheatsheetExtensions.filter((extension) => {
|
||||
return mappedResults.includes(extension.i18nKey)
|
||||
return (
|
||||
searchResults.find((result) => {
|
||||
return result.extensionId === extension.i18nKey
|
||||
}) !== undefined
|
||||
)
|
||||
})
|
||||
setVisibleExtensions(extensionResults)
|
||||
}, [allCheatsheetExtensions, searchResults, searchTerm, setVisibleExtensions])
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { CheatsheetSingleEntry, CheatsheetExtension } from './cheatsheet-extension'
|
||||
import { hasCheatsheetTopics } from './cheatsheet-extension'
|
||||
import type { CheatsheetExtension, CheatsheetEntry } from './cheatsheet-extension'
|
||||
import { isCheatsheetMultiEntry } from './cheatsheet-extension'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Button, ButtonGroup, ListGroupItem } from 'react-bootstrap'
|
||||
import { Trans } from 'react-i18next'
|
||||
|
||||
interface EntrySelectionProps {
|
||||
extension: CheatsheetExtension | undefined
|
||||
selectedEntry: CheatsheetSingleEntry | undefined
|
||||
setSelectedEntry: (value: CheatsheetSingleEntry) => void
|
||||
selectedEntry: CheatsheetEntry | undefined
|
||||
setSelectedEntry: (value: CheatsheetEntry) => void
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ interface EntrySelectionProps {
|
|||
*/
|
||||
export const TopicSelection: React.FC<EntrySelectionProps> = ({ extension, selectedEntry, setSelectedEntry }) => {
|
||||
const listItems = useMemo(() => {
|
||||
if (!hasCheatsheetTopics(extension)) {
|
||||
if (!isCheatsheetMultiEntry(extension)) {
|
||||
return null
|
||||
}
|
||||
return extension.topics.map((entry) => (
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { allAppExtensions } from '../../extensions/all-app-extensions'
|
||||
import type { CheatsheetExtensionComponentProps } from './cheatsheet-extension'
|
||||
import { hasCheatsheetTopics } from './cheatsheet-extension'
|
||||
import { isCheatsheetMultiEntry } from './cheatsheet-extension'
|
||||
import type { ReactElement } from 'react'
|
||||
import React, { Fragment, useMemo } from 'react'
|
||||
|
||||
|
@ -20,7 +20,7 @@ export const useComponentsFromAppExtensions = (
|
|||
<Fragment key={'app-extensions'}>
|
||||
{allAppExtensions
|
||||
.flatMap((extension) => extension.buildCheatsheetExtensions())
|
||||
.flatMap((extension) => (hasCheatsheetTopics(extension) ? extension.topics : extension))
|
||||
.flatMap((extension) => (isCheatsheetMultiEntry(extension) ? extension.topics : extension))
|
||||
.map((extension) => {
|
||||
if (extension.cheatsheetExtensionComponent) {
|
||||
return React.createElement(extension.cheatsheetExtensionComponent, { key: extension.i18nKey, setContent })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue