fix(deps): replace flexsearch-ts with orama

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2024-01-15 22:35:55 +01:00 committed by David Mehren
parent 931ce68a32
commit 07162b7807
25 changed files with 266 additions and 215 deletions

View file

@ -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>

View file

@ -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'} />

View file

@ -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
}

View file

@ -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])

View file

@ -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) => (

View file

@ -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 })