From 7344d274a62eacf3e0a5df275b5bd1465f623320 Mon Sep 17 00:00:00 2001 From: samueljd Date: Thu, 29 Aug 2024 19:15:16 +0530 Subject: [PATCH] Lexical Scribe editor integration. fix for usfm error handling fix scroll issue, disabled non available books. --- .gitignore | 2 + package.json | 8 +- .../Navigation/reference/SelectBook.js | 2 + .../TextEditor/BibleNavigationX.jsx | 251 -- .../TextEditor/BibleNavigationX/SelectBook.js | 166 ++ .../BibleNavigationX/SelectChapter.js | 87 + .../SelectReference.module.css | 14 + .../TextEditor/BibleNavigationX/index.js | 198 ++ .../EditorPage/TextEditor/Buttons.jsx | 120 - .../EditorPage/TextEditor/Editor.jsx | 184 -- .../EditorPage/TextEditor/EditorMenuBar.jsx | 23 +- .../EditorPage/TextEditor/EmptyScreen.jsx | 37 + .../EditorPage/TextEditor/InsertMenu.jsx | 35 - .../EditorPage/TextEditor/LexicalEditor.jsx | 85 + .../TextEditor/NotesEditorHeader.jsx | 27 + .../EditorPage/TextEditor/Popup.jsx | 116 - .../EditorPage/TextEditor/RecursiveBlock.jsx | 137 - .../EditorPage/TextEditor/cacheUtils.js | 129 + .../EditorPage/TextEditor/conversionUtils.js | 45 + .../EditorPage/TextEditor/hooks/saveToFile.js | 6 +- .../TextEditor/hooks/useReadUsfmFile.js | 47 +- .../EditorPage/TextEditor/index.jsx | 174 +- .../EditorPage/TextEditor/updateAndSave.js | 15 + .../TextEditor/utils/IntersectionObserver.js | 36 - .../TextEditor/utils/getReferences.js | 64 - .../TextEditor/utils/insertFunctionMap.js | 18 - .../src/components/hooks/scribex/htmlmap.js | 55 - .../src/components/hooks/scribex/htmlmap.json | 44 - .../components/hooks/scribex/saveToFile.js | 42 - .../src/components/hooks/scribex/usePerf.js | 123 - .../hooks/scribex/useReadUsfmFile.js | 57 - .../src/layouts/editor/SectionContainer.js | 14 + .../modules/editorsidebar/EditorSideBar.js | 23 +- styles/globals.css | 2443 ++++++++++++++++- yarn.lock | 580 +++- 35 files changed, 3953 insertions(+), 1454 deletions(-) delete mode 100644 renderer/src/components/EditorPage/TextEditor/BibleNavigationX.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectBook.js create mode 100644 renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectChapter.js create mode 100644 renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectReference.module.css create mode 100644 renderer/src/components/EditorPage/TextEditor/BibleNavigationX/index.js delete mode 100644 renderer/src/components/EditorPage/TextEditor/Buttons.jsx delete mode 100644 renderer/src/components/EditorPage/TextEditor/Editor.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/EmptyScreen.jsx delete mode 100644 renderer/src/components/EditorPage/TextEditor/InsertMenu.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/NotesEditorHeader.jsx delete mode 100644 renderer/src/components/EditorPage/TextEditor/Popup.jsx delete mode 100644 renderer/src/components/EditorPage/TextEditor/RecursiveBlock.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/cacheUtils.js create mode 100644 renderer/src/components/EditorPage/TextEditor/conversionUtils.js create mode 100644 renderer/src/components/EditorPage/TextEditor/updateAndSave.js delete mode 100644 renderer/src/components/EditorPage/TextEditor/utils/IntersectionObserver.js delete mode 100644 renderer/src/components/EditorPage/TextEditor/utils/getReferences.js delete mode 100644 renderer/src/components/EditorPage/TextEditor/utils/insertFunctionMap.js delete mode 100644 renderer/src/components/hooks/scribex/htmlmap.js delete mode 100644 renderer/src/components/hooks/scribex/htmlmap.json delete mode 100644 renderer/src/components/hooks/scribex/saveToFile.js delete mode 100644 renderer/src/components/hooks/scribex/usePerf.js delete mode 100644 renderer/src/components/hooks/scribex/useReadUsfmFile.js diff --git a/.gitignore b/.gitignore index a0f608045..7c1e5ffa6 100755 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,8 @@ Autogrpha-DB/ /app/**/*.map /.next .next +.yalc +yalc.lock # testing /coverage diff --git a/package.json b/package.json index 8152c91ed..2be57c813 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "@babel/eslint-parser": "^7.5.4", "@babel/preset-env": "^7.25.4", "@babel/preset-react": "^7.17.12", + "@capacitor/cli": "5.4.2", "@mui/icons-material": "^5.8.4", "@netlify/plugin-nextjs": "^4.8.0", "@playwright/test": "^1.36.2", @@ -127,6 +128,8 @@ "@mui/icons-material": "^5.x" }, "dependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@biblionexus-foundation/scribe-editor": "0.1.2-scribe-v1", "@capacitor/app": "5.0.6", "@capacitor/core": "5.4.2", "@capacitor/haptics": "5.0.6", @@ -222,6 +225,7 @@ "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "5.0.1", + "sj-usfm-grammar": "^3.0.3", "styled-components": "^5.3.6", "tc-ui-toolkit": "5.3.3", "terser-webpack-plugin": "^5.3.10", @@ -230,9 +234,9 @@ "typescript": "^4.9.5", "use-deep-compare": "^1.1.0", "usfm-editor": "0.8.7", - "usfm-grammar": "^2.3.0", + "usfm-grammar": "^2.3.1", "uuid": "^9.0.1", - "wavesurfer.js": "^6.6.2", + "wavesurfer.js": "^6.6.4", "webpack-node-externals": "^3.0.0", "winston": "^3.7.2", "word-aligner": "1.0.0", diff --git a/renderer/src/components/EditorPage/Navigation/reference/SelectBook.js b/renderer/src/components/EditorPage/Navigation/reference/SelectBook.js index 2256f55f7..cb28054e0 100644 --- a/renderer/src/components/EditorPage/Navigation/reference/SelectBook.js +++ b/renderer/src/components/EditorPage/Navigation/reference/SelectBook.js @@ -14,6 +14,7 @@ export default function SelectBook({ selectedBooks, setSelectedBooks, scope, + setBook, existingScope = [], disableScope = {}, call = '', @@ -37,6 +38,7 @@ export default function SelectBook({ function bookSelect(e, bookId) { e.preventDefault(); onChangeBook(bookId, selectedBooks[0]); + setBook(bookId); if (multiSelectBook === false) { selectBook(); } } diff --git a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX.jsx b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX.jsx deleted file mode 100644 index 4be5cb2b0..000000000 --- a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX.jsx +++ /dev/null @@ -1,251 +0,0 @@ -import PropTypes from 'prop-types'; -import { Dialog, Transition } from '@headlessui/react'; -import React, { - Fragment, useContext, useEffect, useRef, useState, -} from 'react'; -import { XMarkIcon, ChevronDownIcon } from '@heroicons/react/24/solid'; -import * as localforage from 'localforage'; -import SelectBook from '@/components/EditorPage/Navigation/reference/SelectBook'; -import SelectVerse from '@/components/EditorPage/Navigation/reference/SelectVerse'; - -import { ReferenceContext } from '@/components/context/ReferenceContext'; - -export default function BibleNavigationX(props) { - const { - showVerse, chapterNumber, setChapterNumber, verseNumber, setVerseNumber, - } = props; - const supportedBooks = null; // if empty array or null then all books available - - const { - state: { - bookId, - bookList, - bookName, - chapter, - verse, - chapterList, - verseList, - languageId, - // closeNavigation, - }, actions: { - onChangeBook, - onChangeChapter, - onChangeVerse, - applyBooksFilter, - setCloseNavigation, - }, - } = useContext(ReferenceContext); - - useEffect(() => { - applyBooksFilter(supportedBooks); - }, [applyBooksFilter, supportedBooks]); - - const [openBook, setOpenBook] = useState(false); - const [openVerse, setOpenVerse] = useState(false); - const cancelButtonRef = useRef(null); - - const [multiSelectVerse] = useState(false); - const [multiSelectBook] = useState(false); - const [selectedVerses, setSelectedVerses] = useState([]); - const [selectedBooks, setSelectedBooks] = useState([]); - const [verselectActive, setVerseSelectActive] = useState(false); - - function closeBooks() { - setOpenBook(false); - } - - function openBooks() { - setSelectedBooks([(bookId.toUpperCase())]); - setOpenBook(true); - } - - function closeVerses() { - setOpenVerse(false); - if (multiSelectVerse) { setVerseSelectActive(true); } - } - - function selectBook() { - setOpenBook(false); - setOpenVerse(true); - if (multiSelectVerse) { setSelectedVerses([]); } - } - - useEffect(() => { - const getSupportedBooks = async () => { - const refs = await localforage.getItem('refBibleBurrito'); - refs?.forEach((ref) => { - if (languageId !== null) { - if (ref.value.languages[0].tag === languageId) { - const supportedBooks = []; - Object.entries((ref.value.type.flavorType.currentScope)).forEach( - ([key]) => { - supportedBooks.push(key.toLowerCase()); - }, - ); - applyBooksFilter(supportedBooks); - } - } - }); - }; - getSupportedBooks(); - }, [languageId, applyBooksFilter]); - - useEffect(() => { - async function setReference() { - await localforage.setItem('navigationHistory', [bookId, chapter, verse]); - } - setReference(); - }, [bookId, chapter, verse]); - - useEffect(() => { - if (openBook === false && openVerse === false) { - setCloseNavigation(true); - } - if (openBook || openVerse) { - setCloseNavigation(false); - } - }, [openVerse, openBook, setCloseNavigation]); - - return ( - <> -
-
- {bookName} - - - {chapterNumber} - - - {verseNumber} - {showVerse - && ( - - {multiSelectVerse - ? selectedVerses.join() - : verse} - - )} -
-
- - - -
-
- - - -
-
- -
-
- - - - - -
- -
- - - -
-
- -
-
- - ); -} - -BibleNavigationX.propTypes = { - showVerse: PropTypes.bool, -}; diff --git a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectBook.js b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectBook.js new file mode 100644 index 000000000..1a430edeb --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectBook.js @@ -0,0 +1,166 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import { Disclosure, Transition } from '@headlessui/react'; +import { useTranslation } from 'react-i18next'; +import styles from './SelectReference.module.css'; + +export default function SelectBook({ + children, + bookList, + selectBook, + onChangeBook, + multiSelectBook, + selectedBooks, + scope, + setBook, + booksInProject, +}) { + const [openNT, setOpenNT] = useState(true); + const [openOT, setOpenOT] = useState(true); + + function toggleNT() { + setOpenNT(true); + setOpenOT(false); + } + + function toggleOT() { + setOpenOT(true); + setOpenNT(false); + } + + function toggle() { + setOpenNT(true); + setOpenOT(true); + } + + function bookSelect(e, bookId) { + e.preventDefault(); + if (booksInProject.includes(bookId.toLowerCase())) { + onChangeBook(bookId, selectedBooks[0]); + setBook(bookId); + if (multiSelectBook === false) { selectBook(); } + } + } + useEffect(() => { + if (scope === 'Old Testament (OT)') { + toggleOT(); + } else if (scope === 'New Testament (NT)') { + toggleNT(); + } else { + toggle(); + } + }, [scope]); + const { t } = useTranslation(); + + const getBookClassName = (book) => { + let className = styles.bookSelect; + + if (!booksInProject.includes(book.key.toLowerCase())) { + return styles.disabled; + } + + if (selectedBooks.includes(book.key.toUpperCase())) { + className += ` ${styles.active}`; + } + + return className; + }; + return ( + <> +
+
+
{t('btn-all')}
+
{t('btn-ot')}
+
{t('btn-nt')}
+
+
+ {children} +
+
+ + + {openOT && ( + <> +
+ {t('label-old-testament')} +
+ + +
+ {bookList.map((book, index) => ( + index <= 38 && ( +
(bookSelect(e, book.key, book.name))} + className={getBookClassName(book)} + > + {book.name} +
+ ) + ))} +
+
+
+ + )} +
+ + {openNT && ( + <> +
+ {t('label-new-testament')} +
+ + +
+ {bookList.map((book, index) => (index > 38 && ( +
(bookSelect(e, book.key, book.name))} + className={getBookClassName(book)} + > + {book.name} +
+ ) + ))} +
+
+
+ + )} +
+ + ); +} + +SelectBook.propTypes = { + children: PropTypes.any, + selectBook: PropTypes.func, + onChangeBook: PropTypes.func, + bookList: PropTypes.array, + selectedBooks: PropTypes.array, + multiSelectBook: PropTypes.bool, + scope: PropTypes.string, + setBook: PropTypes.func, + booksInProject: PropTypes.array, +}; diff --git a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectChapter.js b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectChapter.js new file mode 100644 index 000000000..b0442bd64 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectChapter.js @@ -0,0 +1,87 @@ +import PropTypes from 'prop-types'; +import { Disclosure, Transition } from '@headlessui/react'; +import { useTranslation } from 'react-i18next'; +import styles from './SelectReference.module.css'; + +export default function SelectChapter({ + children, + bookName, + chapter, + chapterList, + onChangeChapter, + closeBooks, + closeChapters, + setChapterNumber, + loading, +}) { + const { t } = useTranslation(); + + const onChapterSelect = (e, chapterNum) => { + e.preventDefault(); + onChangeChapter(chapterNum, chapter); + closeBooks(); + closeChapters(); + + if (chapterNum && setChapterNumber) { + setChapterNumber(chapterNum); + } + }; + + return ( + <> +
+
+
+ {bookName} +
+
+ {t('label-chapter')} + : + {chapter} +
+
+
+ {children} +
+
+ + + + + {!loading && chapterList.map((chapter) => ( + + ))} + + + + + ); +} + +SelectChapter.propTypes = { + children: PropTypes.any, + bookName: PropTypes.string, + chapter: PropTypes.string, + chapterList: PropTypes.array, + onChangeChapter: PropTypes.func, + closeBooks: PropTypes.func, + closeChapters: PropTypes.func, + setChapterNumber: PropTypes.func, + loading: PropTypes.bool, +}; diff --git a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectReference.module.css b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectReference.module.css new file mode 100644 index 000000000..e1c09f06f --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/SelectReference.module.css @@ -0,0 +1,14 @@ +.select { + @apply py-1 px-2 hover:bg-primary hover:text-white cursor-pointer rounded hover:w-auto; +} +.bookSelect { + @apply py-1 mt-1 px-2 hover:bg-primary hover:text-white cursor-pointer rounded lg:w-5/12 sm:w-10/12; +} + +.active { + @apply py-1 px-2 bg-primary text-white cursor-pointer rounded sm:w-10/12 lg:w-5/12; +} + +.disabled { + @apply py-1 px-2 text-slate-400 rounded; +} \ No newline at end of file diff --git a/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/index.js b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/index.js new file mode 100644 index 000000000..38540a6c2 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/BibleNavigationX/index.js @@ -0,0 +1,198 @@ +import PropTypes from 'prop-types'; +import { Dialog, Transition } from '@headlessui/react'; +import React, { + Fragment, useContext, useEffect, useRef, useState, +} from 'react'; +import { XMarkIcon, ChevronDownIcon } from '@heroicons/react/24/solid'; +import * as localforage from 'localforage'; +import { ReferenceContext } from '@/components/context/ReferenceContext'; +import SelectBook from './SelectBook'; +import SelectChapter from './SelectChapter'; + +export default function BibleNavigationX(props) { + const { + chapterNumber, setChapterNumber, setBook, loading, bookAvailable, booksInProject, + } = props; + + const { + state: { + bookId, + bookList, + bookName, + chapter, + chapterList, + }, actions: { + onChangeBook, + onChangeChapter, + setCloseNavigation, + }, + } = useContext(ReferenceContext); + + const [openBook, setOpenBook] = useState(false); + const [openChapter, setOpenChapter] = useState(false); + const cancelButtonRef = useRef(null); + + const [multiSelectBook] = useState(false); + const [selectedBooks, setSelectedBooks] = useState([]); + + function closeBooks() { + setOpenBook(false); + } + + function openBooks() { + setSelectedBooks([(bookId.toUpperCase())]); + setOpenBook(true); + } + + function closeChapters() { + setOpenChapter(false); + } + + function selectBook() { + setOpenBook(false); + setOpenChapter(true); + } + + useEffect(() => { + async function setReference() { + await localforage.setItem('navigationHistory', [bookId, chapter]); + } + setReference(); + }, [bookId, chapter]); + + useEffect(() => { + if (openBook === false && openChapter === false) { + setCloseNavigation(true); + } + if (openBook || openChapter) { + setCloseNavigation(false); + } + }, [openChapter, openBook, setCloseNavigation]); + + return ( + <> +
+
+ {bookName} + + + {chapterNumber} + + +
+
+ <> + + + +
+
+ + + +
+
+
+
+ + + + +
+
+ + + +
+
+
+
+ + + ); +} + +BibleNavigationX.propTypes = { + chapterNumber: PropTypes.number, + setChapterNumber: PropTypes.func, + setBook: PropTypes.func, + loading: PropTypes.bool, + bookAvailable: PropTypes.bool, +}; diff --git a/renderer/src/components/EditorPage/TextEditor/Buttons.jsx b/renderer/src/components/EditorPage/TextEditor/Buttons.jsx deleted file mode 100644 index e2fe18eb0..000000000 --- a/renderer/src/components/EditorPage/TextEditor/Buttons.jsx +++ /dev/null @@ -1,120 +0,0 @@ -/* eslint-disable no-unused-vars */ -import React, { useState } from 'react'; - -import RectangleStackIcon from '@/icons/Xelah/RectangleStack.svg'; -import ArrowDownOnSquareIcon from '@/icons/Xelah/ArrowDownOnSquare.svg'; -import Bars2Icon from '@/icons/Xelah/Bars2.svg'; -import Bars4Icon from '@/icons/Xelah/Bars4.svg'; -import ArrowUturnLeftIcon from '@/icons/Xelah/ArrowUturnLeft.svg'; -import ArrowUturnRightIcon from '@/icons/Xelah/ArrowUturnRight.svg'; -import PencilIcon from '@/icons/Common/Pencil.svg'; -import Copy from '@/icons/Xelah/Copy.svg'; -import Paste from '@/icons/Xelah/Paste.svg'; - -export const classNames = (...classes) => classes.filter(Boolean).join(' '); - -export default function Buttons(props) { - const [sectionable, setSectionableState] = useState(false); - const [blockable, setBlockableState] = useState(true); - const [editable, setEditableState] = useState(true); - const [preview, setPreviewState] = useState(false); - const { - bookCode, - canUndo, - canRedo, - undo, - redo, - setSectionable, - setBlockable, - setEditable, - setPreview, - exportUsfm, - } = props; - - const onSectionable = () => { - setSectionableState(!sectionable); - setSectionable(!sectionable); - }; - const onBlockable = () => { - setBlockableState(!blockable); - setBlockable(!blockable); - }; - const onEditable = () => { - setEditableState(!editable); - setEditable(!editable); - }; - const onPreview = () => { - setPreviewState(!preview); - setPreview(!preview); - }; - - return ( - <> - - - - {blockable ? ( - - ) - : ( - - )} - - - - - exportUsfm(bookCode)} - title="Save" - /> - - ); -} diff --git a/renderer/src/components/EditorPage/TextEditor/Editor.jsx b/renderer/src/components/EditorPage/TextEditor/Editor.jsx deleted file mode 100644 index aed580380..000000000 --- a/renderer/src/components/EditorPage/TextEditor/Editor.jsx +++ /dev/null @@ -1,184 +0,0 @@ -import React, { - useContext, useEffect, useLayoutEffect, useRef, -} from 'react'; -import { HtmlPerfEditor } from '@xelah/type-perf-html'; - -import LoadingScreen from '@/components/Loading/LoadingScreen'; -import { ReferenceContext } from '@/components/context/ReferenceContext'; -import { ProjectContext } from '@/components/context/ProjectContext'; -import { ScribexContext } from '@/components/context/ScribexContext'; -import EmptyScreen from '@/components/Loading/EmptySrceen'; -// eslint-disable-next-line import/no-unresolved, import/extensions -import { functionMapping } from './utils/insertFunctionMap'; - -import RecursiveBlock from './RecursiveBlock'; -// eslint-disable-next-line import/no-unresolved, import/extensions -import { useAutoSaveIndication } from '@/hooks2/useAutoSaveIndication'; -import { onIntersection, scrollReference } from './utils/IntersectionObserver'; - -export default function Editor(props) { - const { - sequenceIds, - isSaving, - htmlPerf, - sectionable, - blockable, - editable, - preview, - verbose, - bookChange, - setBookChange, - addSequenceId, - saveHtmlPerf, - setGraftSequenceId, - bookAvailable, - setChapterNumber, - setVerseNumber, - triggerVerseInsert, - } = props; - - const { - state: { - chapter, selectedFont, editorFontSize, projectScriptureDir, - }, - } = useContext(ReferenceContext); - - const { - states: { openSideBar, scrollLock }, - actions: { setOpenSideBar, setSideBarTab }, - } = useContext(ProjectContext); - - const { - state: { - caretPosition, insertType, selectedText, numberToInsert, textToInsert, - }, - actions: { - setCaretPosition, setSelectedText, setNumberToInsert, setTextToInsert, setInsertType, - }, - } = useContext(ScribexContext); - - const sequenceId = sequenceIds.at(-1); - const style = isSaving ? { cursor: 'progress' } : {}; - - const handlers = { - onBlockClick: ({ element }) => { - const _sequenceId = element.dataset.target; - const { tagName } = element; - if (_sequenceId) { - if (tagName === 'SPAN' && element.dataset.subtype === 'footnote') { - setGraftSequenceId(_sequenceId); - setOpenSideBar(!openSideBar); - setSideBarTab('footnotes'); - } - if (tagName === 'SPAN' && element.dataset.subtype === 'xref') { - setGraftSequenceId(_sequenceId); - setOpenSideBar(!openSideBar); - setSideBarTab('xref'); - } - } else { - setSideBarTab(''); - setGraftSequenceId(null); - } - }, - }; - useEffect(() => { - setBookChange(false); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [htmlPerf]); - - useEffect(() => { // temp fix to trigger rerender to cause onblcok trigger to save to file. Need to find a better way. - if (insertType !== '') { - insertType === 'insertVerseNumber' || insertType === 'insertChapterNumber' - ? functionMapping[insertType].function({ caretPosition, numberToInsert }) - : functionMapping[insertType].function({ caretPosition, textToInsert, selectedText }); - setNumberToInsert(''); - setTextToInsert(''); - setInsertType(''); - setSelectedText(null); - setCaretPosition(0); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [triggerVerseInsert]); - - const isScrolling = useRef(false); - useLayoutEffect(() => { - const handleScroll = () => { - isScrolling.current = true; - }; - const handleScrollEnd = () => { - isScrolling.current = false; - }; - const editorDiv = document.getElementById('fulleditor'); - // Adding scroll and click event listeners - editorDiv.addEventListener('scroll', handleScroll); - editorDiv.addEventListener('click', handleScrollEnd); - return () => { - editorDiv.removeEventListener('scroll', handleScroll); - editorDiv.removeEventListener('click', handleScrollEnd); - }; - }, []); - - useAutoSaveIndication(isSaving); - - function onReferenceSelected({ chapter, verse }) { - chapter && setChapterNumber(chapter); - verse && setVerseNumber(verse); - !scrollLock && scrollReference(chapter, verse); - } - - const observer = new IntersectionObserver((entries) => onIntersection({ - scroll: isScrolling.current, setChapterNumber, scrollLock, entries, setVerseNumber, - }), { - root: document.querySelector('editor'), - threshold: 0, - rootMargin: '0% 0% -60% 0%', - }); - - const watchNodes = document.querySelectorAll('.editor .chapter'); - const watchArr = Array.from(watchNodes); - const reverseArray = watchArr.length > 0 ? watchArr.slice().reverse() : []; - reverseArray.forEach((chapter) => { observer.observe(chapter); }); - - const _props = { - htmlPerf, - onHtmlPerf: saveHtmlPerf, - chapterIndex: chapter, - sequenceIds, - addSequenceId, - components: { - block: (__props) => RecursiveBlock({ - htmlPerf, onHtmlPerf: saveHtmlPerf, sequenceIds, addSequenceId, onReferenceSelected, setCaretPosition, setSelectedText, scrollLock, ...__props, - }), - }, - options: { - sectionable, - blockable, - editable, - preview, - }, - decorators: {}, - verbose, - handlers, - }; - - return ( -
1.3) ? 1.5 : '', - direction: `${projectScriptureDir === 'RTL' ? 'rtl' : 'auto'}`, - }} - className="border-l-2 border-r-2 border-secondary pb-16 overflow-auto h-full scrollbars-width leading-8" - > -
- {!bookAvailable && } - {bookAvailable && (!sequenceId || bookChange) && } - {bookAvailable && sequenceId && !bookChange && ( - - )} -
-
- ); -} diff --git a/renderer/src/components/EditorPage/TextEditor/EditorMenuBar.jsx b/renderer/src/components/EditorPage/TextEditor/EditorMenuBar.jsx index 9e48eda78..2302e3757 100644 --- a/renderer/src/components/EditorPage/TextEditor/EditorMenuBar.jsx +++ b/renderer/src/components/EditorPage/TextEditor/EditorMenuBar.jsx @@ -6,8 +6,6 @@ import { LockClosedIcon, BookmarkIcon, LockOpenIcon } from '@heroicons/react/24/ // import BibleNavigationX from '@/components/EditorPage/TextEditor/BibleNavigationX'; import { useTranslation } from 'react-i18next'; import BibleNavigationX from './BibleNavigationX'; -import Buttons from './Buttons'; -import InsertMenu from './InsertMenu'; export default function EditorMenuBar(props) { const { @@ -17,9 +15,13 @@ export default function EditorMenuBar(props) { verseNumber, setVerseNumber, handleSelectedFont, - setTriggerVerseInsert, handleEditorFontSize, editorFontSize, + book, + setBook, + loading, + bookAvailable, + booksInProject, } = props; const { t } = useTranslation(); @@ -39,13 +41,18 @@ export default function EditorMenuBar(props) { }; return ( -
+
-
-
-
-
- -
-
-
diff --git a/renderer/src/components/EditorPage/TextEditor/EmptyScreen.jsx b/renderer/src/components/EditorPage/TextEditor/EmptyScreen.jsx new file mode 100644 index 000000000..204624a1b --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/EmptyScreen.jsx @@ -0,0 +1,37 @@ +/* eslint-disable no-tabs */ +import { t } from 'i18next'; +import React from 'react'; + +export default function EmptyScreen() { + return ( +
+
+
+
+
+ + + + + + + + + +
+

{t('label-no-content-available')}

+
+
+
+
+ ); +} diff --git a/renderer/src/components/EditorPage/TextEditor/InsertMenu.jsx b/renderer/src/components/EditorPage/TextEditor/InsertMenu.jsx deleted file mode 100644 index d19c9ae03..000000000 --- a/renderer/src/components/EditorPage/TextEditor/InsertMenu.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { PopupContextProvider } from '../../Popup/PopupContext'; -import Popup from './Popup'; - -export default function InsertMenu({ setTriggerVerseInsert }) { - return ( -
- - - - - - - - - - - - -
- ); -} diff --git a/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx b/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx new file mode 100644 index 000000000..68597dd9c --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx @@ -0,0 +1,85 @@ +import React, { + useEffect, useState, useRef, useMemo, +} from 'react'; +import { + Editor, getViewOptions, DEFAULT_VIEW_MODE, immutableNoteCallerNodeName, NoteEditor, +} from '@biblionexus-foundation/scribe-editor'; + +import NotesEditorHeader from './NotesEditorHeader'; + +export default function LexicalEditor({ + usjInput, onUsjChange, setNavRef, selectedFont, fontSize, textDirection, scrRef, setScrRef, +}) { + const [usj, setUsj] = useState(); + const editorRef = useRef(null); + const [isNoteEditorOpen, setIsNoteEditorOpen] = useState(false); + const [selectedNoteId, setSelectedNoteId] = useState(''); + + const [viewMode] = useState(DEFAULT_VIEW_MODE); + const viewOptions = useMemo(() => getViewOptions(viewMode), [viewMode]); + + const nodeOptions = { + [immutableNoteCallerNodeName]: { + onClick: (e) => { + setIsNoteEditorOpen(true); + setSelectedNoteId(e.currentTarget.getAttribute('data-caller-id')); + }, + }, + }; + + const onChange = async (updatedUsj) => { + editorRef.current?.setUsj(updatedUsj); + onUsjChange(updatedUsj); + }; + useEffect(() => { + if (usjInput) { + setUsj(usjInput); + } + }, [usjInput]); + useEffect(() => { + const timeoutId = setTimeout(() => { + if (usj && editorRef.current) { + editorRef.current.setUsj(usj); + } + }, 1000); + return () => clearTimeout(timeoutId); + }, [usj]); + + useEffect(() => { + setNavRef(scrRef); + }, [scrRef, setNavRef]); + + return ( +
+
+ +
+ + {isNoteEditorOpen && ( +
+ setIsNoteEditorOpen(false)} + /> + +
+ )} +
+ ); +} diff --git a/renderer/src/components/EditorPage/TextEditor/NotesEditorHeader.jsx b/renderer/src/components/EditorPage/TextEditor/NotesEditorHeader.jsx new file mode 100644 index 000000000..63d921138 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/NotesEditorHeader.jsx @@ -0,0 +1,27 @@ +import React from 'react'; + +const NotesEditorHeader = ({ onClose }) => ( +
+
+
+
Notes Editor
+
+ +
+
+
+); + +export default NotesEditorHeader; diff --git a/renderer/src/components/EditorPage/TextEditor/Popup.jsx b/renderer/src/components/EditorPage/TextEditor/Popup.jsx deleted file mode 100644 index 18698f9d4..000000000 --- a/renderer/src/components/EditorPage/TextEditor/Popup.jsx +++ /dev/null @@ -1,116 +0,0 @@ -import React, { useContext } from 'react'; -import PropTypes from 'prop-types'; -import { ScribexContext } from '@/components/context/ScribexContext'; - -import XMarkIcon from '@/icons/Xelah/XMark.svg'; -import { usePopup } from '../../Popup/PopupContext'; -import PopUpTemplate from '../../Popup'; -import { functionMapping } from './utils/insertFunctionMap'; - -const Popup = ({ action, setTriggerVerseInsert }) => { - const { - state: { - textToInsert, numberToInsert, selectedText, - }, - actions: { - setTextToInsert, - setNumberToInsert, - setInsertType, - setSelectedText, - }, - } = useContext(ScribexContext); - const { setIsOpen } = usePopup(); - - const handleInputChange = (event) => { - setTextToInsert(event.target.value); - }; - - const handleNumberInputChange = (e) => { - setNumberToInsert(e.target.value.replace(/[^0-9]/g, '')); - }; - const handleSubmit = () => { - setInsertType(action); - setTriggerVerseInsert((prev) => !prev); - - // calling funciton here does not trigger the perf check to safe. Hence the trigger to re-render. and the code is commented out. - // action === 'insertVerseNumber' || action === 'insertChapterNumber' - // ? functionMapping[action].function({ caretPosition, numberToInsert }) - // : functionMapping[action].function({ caretPosition, textToInsert, selectedText }); - setIsOpen(false); - setSelectedText(''); - }; - - const handleClose = () => { - setIsOpen(false); - setSelectedText(''); - }; - - return ( - -
-

{functionMapping[action].title}

- -
-
-
- {selectedText && selectedText.length > 0 - && ( -
- Selected Text : - {' '} - {selectedText} - {' '} -
- )} - -
-
- {action === 'insertVerseNumber' || action === 'insertChapterNumber' - ? ( - e.stopPropagation()} - /> - ) : ( - e.stopPropagation()} - /> - )} - -
-
- -
-
-
- ); -}; - -Popup.propTypes = { - action: PropTypes.string.isRequired, - // handleButtonClick: PropTypes.func.isRequired, -}; - -export default Popup; diff --git a/renderer/src/components/EditorPage/TextEditor/RecursiveBlock.jsx b/renderer/src/components/EditorPage/TextEditor/RecursiveBlock.jsx deleted file mode 100644 index 0a4e59afa..000000000 --- a/renderer/src/components/EditorPage/TextEditor/RecursiveBlock.jsx +++ /dev/null @@ -1,137 +0,0 @@ -/* eslint-disable react/prop-types */ -/* eslint-disable no-unused-vars */ -import React, { useEffect, useState } from 'react'; -import { HtmlPerfEditor } from '@xelah/type-perf-html'; -import { getCurrentCursorPosition, pasteTextAtCursorPosition } from '@/util/cursorUtils'; -import { - getCurrentVerse, getCurrentChapter, -} from '@/components/EditorPage/TextEditor/utils/getReferences'; - -const getTarget = ({ content }) => { - const div = document.createElement('div'); - div.innerHTML = content; - - const { target } = div.firstChild?.dataset || {}; - - return target; -}; - -export default function RecursiveBlock({ - htmlPerf, - onHtmlPerf, - sequenceIds, - addSequenceId, - options, - content, - style, - contentEditable, - index, - verbose, - setFootNote, - bookId, - onReferenceSelected, - setCaretPosition, - setSelectedText, - scrollLock, - ...props -}) { - const [currentVerse, setCurrentVerse] = useState(null); - - const updateCursorPosition = () => { - const cursorPosition = getCurrentCursorPosition('editor'); - setCaretPosition(cursorPosition); - }; - - function handleSelection() { - let selectedText = ''; - if (window.getSelection) { - selectedText = window.getSelection().toString(); - } else if (document.selection && document.selection.type !== 'Control') { - selectedText = document.selection.createRange().text; - } - if (selectedText) { - setSelectedText(selectedText); - } - } - const checkCurrentVerse = () => { - if (document.getSelection().rangeCount >= 1 && onReferenceSelected) { - const range = document.getSelection().getRangeAt(0); - const selectedNode = range.startContainer; - const { verse } = getCurrentVerse(selectedNode); - const chapter = getCurrentChapter(selectedNode); - onReferenceSelected({ bookId, chapter, verse }); - // !scrollLock && hightlightRefVerse(chapter, verse); - } - updateCursorPosition(); - handleSelection(); - }; - - const keyStrokeHandler = (event) => { - const activeTextArea = document.activeElement; - // Replace line break with space - if (event.key === 'Enter') { - if (activeTextArea.children.length > 1) { - const lineBreak = activeTextArea.children[1]?.outerHTML; - activeTextArea.children[1].outerHTML = lineBreak.replace(//gi, ' '); - } - } - // Disable backspace if the previous node is not the same verse - if (event.keyCode === 8) { - const range = document.getSelection().getRangeAt(0); - const selectedNode = range.startContainer; - const prevNode = selectedNode.previousSibling; - if (prevNode && prevNode.dataset.attsNumber !== currentVerse) { - event.preventDefault(); - } - prevNode ? setCurrentVerse(prevNode.dataset.attsNumber) : {}; - } - if ([37, 38, 39, 40].includes(event.keyCode)) { - checkCurrentVerse(); - updateCursorPosition(); - } - }; - - function onPasteHandler(event) { - const cursorPosition = getCurrentCursorPosition('editor'); - const paste = (event.clipboardData || window.clipboardData).getData('text'); - pasteTextAtCursorPosition({ cursorPosition, textToInsert: paste }); - } - - let component; - - const editable = !!content.match(/data-type="paragraph"/); - - if (editable) { - component = ( - // eslint-disable-next-line jsx-a11y/no-static-element-interactions -
{ event.preventDefault(); onPasteHandler(event); }} - {...props} - /> - ); - } - if (!editable) { - const sequenceId = getTarget({ content }); - - if (sequenceId && !options.preview) { - const _props = { - sequenceIds: [...sequenceIds, sequenceId], - addSequenceId, - htmlPerf, - onHtmlPerf, - onInput: props?.onInput, - options, - }; - component = ; - } - component ||=
; - } - - // eslint-disable-next-line react/jsx-no-useless-fragment - return <>{component}; -} diff --git a/renderer/src/components/EditorPage/TextEditor/cacheUtils.js b/renderer/src/components/EditorPage/TextEditor/cacheUtils.js new file mode 100644 index 000000000..4a8dd4331 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/cacheUtils.js @@ -0,0 +1,129 @@ +import * as path from 'path'; +import * as crypto from 'crypto'; +import { convertUsfmToUsj } from './conversionUtils'; + +let fs; + +function initFS() { + if (typeof window !== 'undefined' && window.require) { + fs = window.require('fs'); + } +} +initFS(); + +export function getMd5Hash(content) { + return crypto.createHash('md5').update(content).digest('hex'); +} + +export function getCacheFilePath(hash, projectCachePath) { + return path.join(projectCachePath, `${hash}.json`); +} + +export function isCacheValid(hash, projectCachePath) { + if (!fs) { return false; } + const cacheFilePath = getCacheFilePath(hash, projectCachePath); + return fs.existsSync(cacheFilePath); +} + +export function readCache(hash, projectCachePath) { + if (!fs) { throw new Error('File system not available'); } + const cacheFilePath = path.join(projectCachePath, `${hash}.json`); + return JSON.parse(fs.readFileSync(cacheFilePath, 'utf8')); +} + +export function writeCache(hash, data, projectCachePath) { + if (!fs) { + // eslint-disable-next-line no-console + console.error('File system not available'); + return; + } + const cacheFilePath = getCacheFilePath(hash, projectCachePath); + fs.writeFileSync(cacheFilePath, JSON.stringify(data), 'utf8'); +} + +export function deleteOldCacheFile(hash, projectCachePath) { + const cacheFilePath = getCacheFilePath(hash, projectCachePath); + if (fs.existsSync(cacheFilePath)) { + fs.unlinkSync(cacheFilePath); + } +} + +export function getCacheMapFromFile(fileCacheMapPath) { + if (fileCacheMapPath) { + try { + if (fs.existsSync(fileCacheMapPath)) { + const fileContent = fs.readFileSync(fileCacheMapPath, 'utf-8'); + return JSON.parse(fileContent); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error reading cache file:', error); + } + } + + return {}; +} + +export function updateCacheMapToFile(fileCacheMapPath, filePath, hash) { + if (fileCacheMapPath) { + const cacheMap = getCacheMapFromFile(fileCacheMapPath); + cacheMap[filePath] = hash; + try { + fs.mkdirSync(path.dirname(fileCacheMapPath), { recursive: true }); + fs.writeFileSync(fileCacheMapPath, JSON.stringify(cacheMap)); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error writing cache file:', error); + } + } +} + +export async function handleCache(filePath, usfmContent, projectCachePath, fileCacheMapPath) { + const newHash = getMd5Hash(usfmContent); + const fileCacheMap = getCacheMapFromFile(fileCacheMapPath); + const oldHash = fileCacheMap[filePath]; + + async function processAndCacheUSJ() { + const { usj, error } = await convertUsfmToUsj(usfmContent); + if (error) { + // eslint-disable-next-line no-console + console.error('Error parsing USFM', error); + return { error }; + } + writeCache(newHash, usj, projectCachePath); + updateCacheMapToFile(fileCacheMapPath, filePath, newHash); + return { usj }; + } + + if (!oldHash) { + // eslint-disable-next-line no-console + console.log('No existing hash found. Creating new cache entry.'); + return processAndCacheUSJ(); + } + + if (isCacheValid(oldHash, projectCachePath) && oldHash === newHash) { + // eslint-disable-next-line no-console + console.log('Cache hit'); + return { usj: await readCache(oldHash, projectCachePath) }; + } + // eslint-disable-next-line no-console + console.log('Cache miss or content changed'); + deleteOldCacheFile(oldHash, projectCachePath); + return processAndCacheUSJ(); +} + +export async function updateCache(filePath, usj, usfm, fileCacheMapPath, projectCachePath) { + const newHash = getMd5Hash(usfm); + const fileCacheMap = getCacheMapFromFile(fileCacheMapPath); + const oldHash = fileCacheMap[filePath]; + + if (oldHash && isCacheValid(oldHash, projectCachePath) && oldHash === newHash) { + writeCache(oldHash, usj, projectCachePath); + } else { + if (oldHash) { + deleteOldCacheFile(oldHash, projectCachePath); + } + writeCache(newHash, usj, projectCachePath); + updateCacheMapToFile(fileCacheMapPath, filePath, newHash); + } +} diff --git a/renderer/src/components/EditorPage/TextEditor/conversionUtils.js b/renderer/src/components/EditorPage/TextEditor/conversionUtils.js new file mode 100644 index 000000000..c9c57bbaa --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/conversionUtils.js @@ -0,0 +1,45 @@ +import USFMParser from 'sj-usfm-grammar'; + +let usfmParserInstance; +let usfmParserInitialized; + +export async function initializeParser() { + if (!usfmParserInstance) { + if (!usfmParserInitialized) { + usfmParserInitialized = await USFMParser.init(); + } + await usfmParserInitialized; + usfmParserInstance = new USFMParser(); + } + return usfmParserInstance; +} + +export async function convertUsfmToUsj(usfm) { + if (!usfmParserInstance) { + usfmParserInstance = await initializeParser(); + } + try { + const usj = usfmParserInstance.usfmToUsj(usfm); + return { usj }; + } catch (e) { + return { usj: { content: [] }, error: e }; + } +} + +export async function convertUsjToUsfm(usj) { + if (!usfmParserInstance) { + usfmParserInstance = await initializeParser(); + } + const usfm = usfmParserInstance.usjToUsfm(usj); + return usfm; +} + +initializeParser() + .then(() => { + // eslint-disable-next-line no-console + console.log('USFM Parser initialized successfully'); + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error('Error initializing USFM Parser:', err); + }); diff --git a/renderer/src/components/EditorPage/TextEditor/hooks/saveToFile.js b/renderer/src/components/EditorPage/TextEditor/hooks/saveToFile.js index b5ef6c340..a4923347d 100644 --- a/renderer/src/components/EditorPage/TextEditor/hooks/saveToFile.js +++ b/renderer/src/components/EditorPage/TextEditor/hooks/saveToFile.js @@ -1,10 +1,8 @@ import localforage from 'localforage'; -// import { readRefMeta } from '../../../core/reference/readRefMeta'; import { isElectron } from '@/core/handleElectron'; import writeToFile from '@/core/editor/writeToFile'; import { readRefBurrito } from '@/core/reference/readRefBurrito'; import packageInfo from '../../../../../../package.json'; -import { newPath } from '../../../../../../supabase'; // function to save to file. export const saveToFile = async (usfmText, bookCode) => { @@ -14,12 +12,12 @@ export const saveToFile = async (usfmText, bookCode) => { const projectName = await localforage.getItem('currentProject'); const path = require('path'); const newpath = localStorage.getItem('userPath'); - const metaPath = isElectron() ? path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName, 'metadata.json') : `${newPath}/${userName}/projects/${projectName}/metadata.json`; + const metaPath = path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName, 'metadata.json'); const metaData = JSON.parse(await readRefBurrito({ metaPath })); Object.entries(metaData.ingredients).forEach(async ([key, _ingredients]) => { if (_ingredients.scope) { const _bookID = Object.entries(_ingredients.scope)[0][0]; - if (_bookID === bookCode) { + if (_bookID.toUpperCase() === bookCode.toUpperCase()) { await writeToFile({ username: userName, projectname: projectName, diff --git a/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js b/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js index 193486311..2f4fa52f0 100644 --- a/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js +++ b/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js @@ -1,20 +1,21 @@ -import { useEffect, useState, useContext } from 'react'; +import { useEffect, useState } from 'react'; import localforage from 'localforage'; -import { ReferenceContext } from '@/components/context/ReferenceContext'; import { readRefBurrito } from '../../../../core/reference/readRefBurrito'; import { readFile } from '../../../../core/editor/readFile'; import packageInfo from '../../../../../../package.json'; -// hook to fetch usfmfile from system drive -export const useReadUsfmFile = () => { +import { handleCache } from '../cacheUtils'; + +export const useReadUsfmFile = (bookId) => { const [usfmData, setUsfmData] = useState([]); const [bookAvailable, setbookAvailable] = useState(false); - const { - state: { - bookId, - }, - } = useContext(ReferenceContext); + const [usfmString, setUsfmString] = useState(''); + const [cachedData, setCachedData] = useState({}); + const [loading, setLoading] = useState(true); + const [booksInProject, setBooksInProject] = useState([]); + useEffect(() => { async function readLocalFile() { + setLoading(true); try { const userProfile = await localforage.getItem('userProfile'); const userName = userProfile?.username; @@ -31,27 +32,49 @@ export const useReadUsfmFile = () => { _books.push(bookObj); } }); + setBooksInProject(_books.map((bookObj) => bookObj.bookId.toLowerCase())); const [currentBook] = _books.filter((bookObj) => bookObj.bookId === bookId?.toUpperCase()); + const projectCachePath = path.join(newpath, packageInfo.name, 'users', userName, 'project_cache', projectName); + const fileCacheMapPath = path.join(projectCachePath, 'fileCacheMap.json'); + const filePath = path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName, 'ingredients', `${bookId?.toUpperCase()}.usfm`); if (currentBook) { const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); + const cachedData = await handleCache(filePath, fileData, projectCachePath, fileCacheMapPath); const books = [{ selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, - bookCode: currentBook.bookId.toLowerCase(), + bookCode: currentBook.bookId?.toLowerCase(), data: fileData, }]; setUsfmData(books); setbookAvailable(true); + setUsfmString(fileData); + setCachedData(cachedData); } else { setUsfmData([]); setbookAvailable(false); } - // setUsfmData(fileData); + setLoading(false); } catch (err) { + setLoading(false); // eslint-disable-next-line no-console return console.log(err); } } readLocalFile(); }, [bookId]); - return { usfmData, bookAvailable }; + return { + usfmData, bookAvailable, usfmString, bookId, cachedData, loading, booksInProject, + }; }; + +export async function getCachePaths(bookId) { + const path = require('path'); + const userProfile = await localforage.getItem('userProfile'); + const projectName = await localforage.getItem('currentProject'); + const newPath = await localforage.getItem('userPath'); + const userName = userProfile?.username; + const projectCachePath = path.join(newPath, packageInfo.name, 'users', userName, 'project_cache', projectName); + const fileCacheMapPath = path.join(projectCachePath, 'fileCacheMap.json'); + const filePath = path.join(newPath, packageInfo.name, 'users', userName, 'projects', projectName, 'ingredients', `${bookId?.toUpperCase()}.usfm`); + return { filePath, projectCachePath, fileCacheMapPath }; +} diff --git a/renderer/src/components/EditorPage/TextEditor/index.jsx b/renderer/src/components/EditorPage/TextEditor/index.jsx index 76734ba1e..b534a997d 100644 --- a/renderer/src/components/EditorPage/TextEditor/index.jsx +++ b/renderer/src/components/EditorPage/TextEditor/index.jsx @@ -1,127 +1,121 @@ import React, { - useEffect, useState, useContext, Fragment, + useEffect, useState, useContext, useMemo, } from 'react'; -import { useProskomma, useImport, useCatalog } from 'proskomma-react-hooks'; -import { useDeepCompareEffect } from 'use-deep-compare'; -import { ScribexContext } from '@/components/context/ScribexContext'; import { ReferenceContext } from '@/components/context/ReferenceContext'; -import { ProjectContext } from '@/components/context/ProjectContext'; -import EditorSideBar from '@/modules/editorsidebar/EditorSideBar'; +import { debounce } from 'lodash'; + +import { LoadingSpinner } from '@/components/LoadingSpinner'; import { useReadUsfmFile } from './hooks/useReadUsfmFile'; -import htmlMap from './hooks/htmlmap'; -import usePerf from './hooks/usePerf'; import EditorMenuBar from './EditorMenuBar'; -import Editor from './Editor'; +import LexicalEditor from './LexicalEditor'; +import { updateCacheNSaveFile } from './updateAndSave'; +import EmptyScreen from './EmptyScreen'; + +const defaultScrRef = { + bookCode: 'PSA', + chapterNum: 1, + verseNum: 1, +}; export default function TextEditor() { - const { state, actions } = useContext(ScribexContext); - const { verbose } = state; - const [selectedBook, setSelectedBook] = useState(); - const [bookChange, setBookChange] = useState(false); const [chapterNumber, setChapterNumber] = useState(1); const [verseNumber, setVerseNumber] = useState(1); - const [triggerVerseInsert, setTriggerVerseInsert] = useState(false); - // const [newVerChapNumber, setInsertNumber] = useState(''); - // const [insertVerseRChapter, setInsertVerseRChapter] = useState(''); - - const { usfmData, bookAvailable } = useReadUsfmFile(); + const [usjInput, setUsjInput] = useState(); + const [scrRef, setScrRef] = useState(defaultScrRef); + const [navRef, setNavRef] = useState(); const { - state: { bookId, selectedFont, editorFontSize }, + state: { + bookId: defaultBookId, selectedFont, editorFontSize, projectScriptureDir, + }, actions: { handleSelectedFont, onChangeChapter, onChangeVerse, handleEditorFontSize, }, } = useContext(ReferenceContext); + const [book, setBook] = useState(defaultBookId); const { - states: { openSideBar }, - actions: { setOpenSideBar }, - } = useContext(ProjectContext); - - let selectedDocument; - - const { proskomma, stateId, newStateId } = useProskomma({ verbose }); - const { done } = useImport({ - proskomma, - stateId, - newStateId, - documents: usfmData, - }); - - function closeSideBar(status) { - setOpenSideBar(status); - } + cachedData, loading, bookAvailable, booksInProject, + } = useReadUsfmFile(book); useEffect(() => { - setSelectedBook(bookId.toUpperCase()); - setBookChange(true); - }, [bookId]); + if (cachedData.error) { + console.error('Error parsing USFM', cachedData.error); + return; + } + const { usj } = cachedData; + if (!usj && usj?.entries(usj).length === 0) { return; } + console.log(usj); + setUsjInput(usj); + }, [book, cachedData]); useEffect(() => { + setScrRef({ + bookCode: book, + chapterNum: chapterNumber, + verseNum: verseNumber, + }); onChangeChapter(chapterNumber, 1); onChangeVerse(verseNumber, 1); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [chapterNumber, verseNumber]); - - const { catalog } = useCatalog({ proskomma, stateId, verbose }); - const { id: docSetId, documents } = (done && catalog.docSets[0]) || {}; - if (done) { - selectedDocument = documents?.find( - (doc) => doc.bookCode === selectedBook, - ); - } - - const { bookCode, h: bookName } = selectedDocument || {}; - const ready = (docSetId && bookCode) || false; - const isLoading = !done || !ready; - const { state: perfState, actions: perfActions } = usePerf({ - proskomma, - ready, - docSetId, - bookCode, - verbose, - htmlMap, - }); - const { htmlPerf } = perfState; + }, [chapterNumber, verseNumber, book]); - useDeepCompareEffect(() => { - if (htmlPerf && htmlPerf.mainSequenceId !== state.sequenceIds[0]) { - actions.setSequenceIds([htmlPerf?.mainSequenceId]); + useEffect(() => { + if (navRef) { + const { chapterNum, verseNum } = navRef; + setChapterNumber(chapterNum); + setVerseNumber(verseNum); } - }, [htmlPerf, state.sequenceIds, perfState]); + }, [navRef]); + + const handleUsjChange = useMemo( + () => debounce(async (updatedUsj) => { + updateCacheNSaveFile(updatedUsj, book); + console.log('usj updated', updatedUsj); + }, 1000), + [book], + ); const _props = { - ...state, - ...perfState, - ...actions, - ...perfActions, - editorFontSize, selectedFont, chapterNumber, - verseNumber, - isLoading, - bookName, - bookChange, - bookAvailable, - handleEditorFontSize, - setBookChange, setChapterNumber, + verseNumber, setVerseNumber, + book, + setBook, handleSelectedFont, - triggerVerseInsert, - setTriggerVerseInsert, + bookId: book, + loading, + editorFontSize, + handleEditorFontSize, + bookAvailable, + booksInProject, + }; + + const props = { + selectedFont, + fontSize: editorFontSize, + textDirection: projectScriptureDir?.toLowerCase(), + usjInput, + onUsjChange: handleUsjChange, + setNavRef, + scrRef, + setScrRef, + bookId: book, + }; return ( - <> - -
- - -
- +
+ + {loading ? ( + + ) : ( + <> + {!bookAvailable && } + {bookAvailable && usjInput && } + + )} +
); } diff --git a/renderer/src/components/EditorPage/TextEditor/updateAndSave.js b/renderer/src/components/EditorPage/TextEditor/updateAndSave.js new file mode 100644 index 000000000..d07f95115 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/updateAndSave.js @@ -0,0 +1,15 @@ +import { getCachePaths } from './hooks/useReadUsfmFile'; +import { convertUsjToUsfm } from './conversionUtils'; +import { updateCache } from './cacheUtils'; +import { saveToFile } from './hooks/saveToFile'; + +export async function updateCacheNSaveFile(usj, bookId) { + const usfm = await convertUsjToUsfm(usj); + const { filePath, projectCachePath, fileCacheMapPath } = await getCachePaths(bookId); + updateCache(filePath, usj, usfm, fileCacheMapPath, projectCachePath); + if (usfm) { + await saveToFile(usfm, bookId); + // eslint-disable-next-line no-console + console.log('updated usfm file saved'); + } +} diff --git a/renderer/src/components/EditorPage/TextEditor/utils/IntersectionObserver.js b/renderer/src/components/EditorPage/TextEditor/utils/IntersectionObserver.js deleted file mode 100644 index 164b2b80e..000000000 --- a/renderer/src/components/EditorPage/TextEditor/utils/IntersectionObserver.js +++ /dev/null @@ -1,36 +0,0 @@ -export const scrollReference = (() => { - let prevCV; - return (c, v) => { - const refEditors = document.getElementsByClassName('ref-editor'); - refEditors.length > 0 && Array.prototype.filter.call(refEditors, (refEditor) => { - if (!prevCV || prevCV.c !== c) { - const chapterInView = refEditor.querySelector(`#ch-${c}`); - if (chapterInView) { - chapterInView.scrollIntoView(); - chapterInView.classList.add('scroll-mt-10'); - } - } else { - const verseInView = refEditor.querySelector(`#ch${c}v${v}`); - if (verseInView) { - verseInView.scrollIntoView(); - } - } - }); - prevCV = { c, v }; - }; -})(); - -export const onIntersection = ({ - scroll, entries, setChapterNumber, scrollLock, setVerseNumber, -}) => { - if (scroll) { - // eslint-disable-next-line no-restricted-syntax - for (const entry of entries) { - if (entry.isIntersecting) { - setChapterNumber(entry.target.dataset.attsNumber); - setVerseNumber(1); - scrollLock === false ? scrollReference(entry.target.dataset.attsNumber) : {}; - } - } - } -}; diff --git a/renderer/src/components/EditorPage/TextEditor/utils/getReferences.js b/renderer/src/components/EditorPage/TextEditor/utils/getReferences.js deleted file mode 100644 index b923fa370..000000000 --- a/renderer/src/components/EditorPage/TextEditor/utils/getReferences.js +++ /dev/null @@ -1,64 +0,0 @@ -export const getCurrentVerse = (currentNode) => { - let verse; - let previousElement = currentNode?.previousElementSibling; - const verseText = currentNode?.nextSibling; - while (previousElement) { - if (previousElement.dataset.type === 'mark' && previousElement.dataset.subtype === 'verses') { - verse = previousElement.dataset.attsNumber; - break; - } - previousElement = previousElement?.previousElementSibling; - } - return { verse, verseText }; -}; - -export const removeHighlightFromRefVerse = ({ c, v }) => { - const refEditors = document.getElementsByClassName('ref-editor'); - refEditors.length > 0 && Array.prototype.filter.call(refEditors, (refEditor) => { - const prevHighlight = refEditor.querySelector(`#ch${c}v${v}`)?.nextElementSibling; - const hightlightText = prevHighlight && prevHighlight.innerHTML; - prevHighlight && prevHighlight.replaceWith(hightlightText); - }); -}; - -export const hightlightRefVerse = (() => { - let prevCV; - return (c, v) => { - const refEditors = document.getElementsByClassName('ref-editor'); - refEditors.length > 0 && Array.prototype.filter.call(refEditors, (refEditor) => { - if (!(prevCV && prevCV.c !== c)) { - const verseInView = refEditor.querySelector(`#ch${c}v${v}`); - const { verseText } = getCurrentVerse(verseInView); - // highlight verse - const range = document.createRange(); - range.setStart(verseText, 0); - range.setEnd(verseText, verseText.textContent.length); - const newSpan = document.createElement('span'); - newSpan.classList.add('bg-primary-50'); - range.surroundContents(newSpan); - // remove highlight from previous verse - prevCV && removeHighlightFromRefVerse({ ...prevCV }); - } - }); - prevCV = { c, v }; - }; -})(); - -export const getCurrentChapter = (currentNode) => { - let currentChapter; - const closestParaDiv = currentNode.parentNode.parentNode; - if (closestParaDiv.firstElementChild?.firstElementChild?.classList.contains('chapter')) { - currentChapter = closestParaDiv.firstElementChild.firstElementChild.dataset.attsNumber; - return currentChapter; - } - - let prevParaDiv = closestParaDiv.previousElementSibling; - while (prevParaDiv) { - if (prevParaDiv.firstElementChild?.firstElementChild?.classList.contains('chapter')) { - currentChapter = prevParaDiv.firstElementChild.firstElementChild.dataset.attsNumber; - break; - } - prevParaDiv = prevParaDiv.previousElementSibling; - } - return currentChapter; -}; diff --git a/renderer/src/components/EditorPage/TextEditor/utils/insertFunctionMap.js b/renderer/src/components/EditorPage/TextEditor/utils/insertFunctionMap.js deleted file mode 100644 index a4fedbc64..000000000 --- a/renderer/src/components/EditorPage/TextEditor/utils/insertFunctionMap.js +++ /dev/null @@ -1,18 +0,0 @@ -import { - insertVerseNumber, insertChapterNumber, insertFootnote, insertXRef, -} from '@/util/cursorUtils'; - -export const functionMapping = { - insertVerseNumber: { - title: 'Insert Verse', function: insertVerseNumber, icon: 'V', pholder: 'Verse number', - }, - insertChapterNumber: { - title: 'Insert Chapter', function: insertChapterNumber, icon: 'C', placeholder: 'Chapter number', - }, - insertFootnote: { - title: 'Insert Footnote', function: insertFootnote, icon: 'FN', placeholder: 'Footnote', - }, - insertXRef: { - title: 'Insert Cross Reference', function: insertXRef, icon: 'XR', placeholder: 'Cross Reference', - }, -}; diff --git a/renderer/src/components/hooks/scribex/htmlmap.js b/renderer/src/components/hooks/scribex/htmlmap.js deleted file mode 100644 index e9b9d9729..000000000 --- a/renderer/src/components/hooks/scribex/htmlmap.js +++ /dev/null @@ -1,55 +0,0 @@ -const htmlMap = (context) => ({ - '*': { - '*': { - tagName: 'span', - }, - sequence: { - tagName: 'section', - }, - }, - wrapper: { - '*': { - tagName: 'wrapper', - }, - sequence: { - tagName: 'section', - }, - }, - paragraph: { - '*': { - tagName: 'p', - }, - }, - mark: { - '*': { - tagName: 'span', - }, - chapter: ({ atts }) => { - context.lastChapter = atts.number; - return ({ - classList: ['mark', 'chapter', `chapter-${atts.number}`], - id: `ch-${atts.number}`, - tagName: 'span', - }); - }, - verses: ({ atts }) => ({ - classList: ['mark', 'verse', `verse-${atts.number}`], - id: `ch${context.lastChapter}v${atts.number}`, - tagName: 'span', - attributes: { contenteditable: false }, - }), - }, - graft: { - heading: { - tagName: 'div', - }, - title: { - tagName: 'div', - }, - introduction: { - tagName: 'div', - }, - }, -}); - -export default htmlMap({}); diff --git a/renderer/src/components/hooks/scribex/htmlmap.json b/renderer/src/components/hooks/scribex/htmlmap.json deleted file mode 100644 index bf319d520..000000000 --- a/renderer/src/components/hooks/scribex/htmlmap.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "*": { - "*": { - "tagName": "span" - }, - "sequence": { - "tagName": "section" - } - }, - "graft": { - "title": { - "tagName": "p" - }, - "footnote":{ - "tagName":"span" - } - }, - "ms": { - "paragraph": { - "tagName": "h3" - } - }, - "paragraph": { - "usfm:mt": { - "classList": ["major-title paragraph mt"], - "tagName": "h2" - }, - "usfm:ms": { - "classList": ["major-section-heading paragraph ms"], - "tagName": "h3" - }, - "*": { - "tagName": "p" - } - }, - "mark": { - "chapter": { - "tagName": "sub" - }, - "verses": { - "tagName": "sup" - } - } -} diff --git a/renderer/src/components/hooks/scribex/saveToFile.js b/renderer/src/components/hooks/scribex/saveToFile.js deleted file mode 100644 index cb8a2cd7d..000000000 --- a/renderer/src/components/hooks/scribex/saveToFile.js +++ /dev/null @@ -1,42 +0,0 @@ -import localforage from 'localforage'; -// import { readRefMeta } from '../../../core/reference/readRefMeta'; -import { isElectron } from '@/core/handleElectron'; -import { readRefBurrito } from '../../../core/reference/readRefBurrito'; -import writeToFile from '../../../core/editor/writeToFile'; -import packageInfo from '../../../../../package.json'; -import { newPath } from '../../../../../supabase'; -// if (!process.env.NEXT_PUBLIC_IS_ELECTRON) { -// const newPath = require('../../../../../supabase').newPath -// } -// function to save to file. -export const saveToFile = async (usfmText, bookCode) => { - try { - const userProfile = await localforage.getItem('userProfile'); - const userName = isElectron() ? userProfile?.username : userProfile?.user?.email; - const projectName = await localforage.getItem('currentProject'); - const path = require('path'); - const newpath = localStorage.getItem('userPath'); - // const projectsDir = path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName); - const metaPath = isElectron() ? path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName, 'metadata.json') : `${newPath}/${userName}/projects/${projectName}/metadata.json`; - // const refs = await readRefMeta({ projectsDir }) - const metaData = JSON.parse(await readRefBurrito({ metaPath })); - Object.entries(metaData.ingredients).forEach(async ([key, _ingredients]) => { - if (_ingredients.scope) { - const _bookID = Object.entries(_ingredients.scope)[0][0]; - if (_bookID === bookCode) { - // setTimeout(() => { - await writeToFile({ - username: userName, - projectname: projectName, - filename: key, - data: usfmText, - }); - // }, 2000); - } - } - }); - } catch (err) { - // eslint-disable-next-line no-console - return console.log(err); - } -}; diff --git a/renderer/src/components/hooks/scribex/usePerf.js b/renderer/src/components/hooks/scribex/usePerf.js deleted file mode 100644 index 18bdcccf8..000000000 --- a/renderer/src/components/hooks/scribex/usePerf.js +++ /dev/null @@ -1,123 +0,0 @@ -/* eslint-disable no-unused-vars */ -import { useState, useTransition } from 'react'; -import { - useDeepCompareCallback, - useDeepCompareEffect, - useDeepCompareMemo, -} from 'use-deep-compare'; -import isEqual from 'lodash.isequal'; -import EpiteleteHtml from 'epitelete-html'; -import { saveToFile } from './saveToFile'; - -export default function usePerf({ - proskomma, - ready, - docSetId, - bookCode, - verbose, - htmlMap, - refName, -}) { - const [isSaving, startSaving] = useTransition(); - const [htmlPerf, setHtmlPerf] = useState(); - const [usfmText, setUsfmText] = useState(); - - const epiteleteHtml = useDeepCompareMemo( - () => ready - && new EpiteleteHtml({ - proskomma, - docSetId, - htmlMap, - options: { historySize: 100 }, - }), - [proskomma, ready, docSetId, refName], - ); - - useDeepCompareEffect(() => { - if (epiteleteHtml) { - epiteleteHtml.readHtml(bookCode, { cloning: false }, htmlMap).then((_htmlPerf) => { - // remove htmlMap for default classes - setHtmlPerf(_htmlPerf); - }); - } - }, [epiteleteHtml, bookCode]); - - // exports perf to usfm and writes to file. - const exportUsfm = async (bookCode) => { - const usfmString = await epiteleteHtml?.readUsfm(bookCode); - setUsfmText(usfmString); - saveToFile(usfmString, bookCode); - epiteleteHtml?.readHtml(bookCode, { cloning: false }, htmlMap).then((_htmlPerf) => { // remove htmlMap for default classes - setHtmlPerf(_htmlPerf); - }); - }; - - const saveHtmlPerf = useDeepCompareCallback( - (_htmlPerf, { sequenceId }) => { - if (!isEqual(htmlPerf, _htmlPerf)) { setHtmlPerf(_htmlPerf); } - - startSaving(async () => { - const newHtmlPerf = await epiteleteHtml?.writeHtml( - bookCode, - sequenceId, - _htmlPerf, - { insertSequences: true }, - ); - if (!isEqual(htmlPerf, newHtmlPerf)) { setHtmlPerf(newHtmlPerf); } - exportUsfm(bookCode); - }); - }, - [htmlPerf, bookCode], - ); - - const insertNewGraft = useDeepCompareCallback( - (_htmlPerf, { sequenceId }) => { - if (!isEqual(htmlPerf, _htmlPerf)) { setHtmlPerf(_htmlPerf); } - - startSaving(async () => { - const newHtmlPerf = await epiteleteHtml?.writeHtml( - bookCode, - sequenceId, - _htmlPerf, - { insertSequences: true }, - ); - - if (!isEqual(htmlPerf, newHtmlPerf)) { setHtmlPerf(newHtmlPerf); } - exportUsfm(bookCode); - }); - }, - [htmlPerf, bookCode], - ); - - const undo = async () => { - const newPerfHtml = await epiteleteHtml?.undoHtml(bookCode); - setHtmlPerf(newPerfHtml); - }; - - const redo = async () => { - const newPerfHtml = await epiteleteHtml?.redoHtml(bookCode); - setHtmlPerf(newPerfHtml); - }; - - const canUndo = (epiteleteHtml?.canUndo && epiteleteHtml?.canUndo(bookCode)) || false; - const canRedo = (epiteleteHtml?.canRedo && epiteleteHtml?.canRedo(bookCode)) || false; - - const state = { - bookCode, - htmlPerf, - canUndo, - canRedo, - isSaving, - usfmText, - }; - - const actions = { - insertNewGraft, - saveHtmlPerf, - exportUsfm, - undo, - redo, - }; - - return { state, actions }; -} diff --git a/renderer/src/components/hooks/scribex/useReadUsfmFile.js b/renderer/src/components/hooks/scribex/useReadUsfmFile.js deleted file mode 100644 index b3a9f4ad0..000000000 --- a/renderer/src/components/hooks/scribex/useReadUsfmFile.js +++ /dev/null @@ -1,57 +0,0 @@ -import { useEffect, useState, useContext } from 'react'; -import localforage from 'localforage'; -import { ReferenceContext } from '@/components/context/ReferenceContext'; -import { readRefBurrito } from '../../../core/reference/readRefBurrito'; -import { readFile } from '../../../core/editor/readFile'; -import packageInfo from '../../../../../package.json'; -// hook to fetch usfmfile from system drive -export const useReadUsfmFile = () => { - const [usfmData, setUsfmData] = useState([]); - const [bookAvailable, setbookAvailable] = useState(false); - const { - state: { - bookId, - }, - } = useContext(ReferenceContext); - useEffect(() => { - async function readLocalFile() { - try { - const userProfile = await localforage.getItem('userProfile'); - const userName = userProfile?.username; - const projectName = await localforage.getItem('currentProject'); - const path = require('path'); - const newpath = localStorage.getItem('userPath'); - const metaPath = path.join(newpath, packageInfo.name, 'users', userName, 'projects', projectName, 'metadata.json'); - const metaData = JSON.parse(await readRefBurrito({ metaPath })); - const _books = []; - Object.entries(metaData.ingredients).forEach(async ([key, _ingredients]) => { - if (_ingredients.scope) { - const _bookID = Object.entries(_ingredients.scope)[0][0]; - const bookObj = { bookId: _bookID, fileName: key }; - _books.push(bookObj); - } - }); - const [currentBook] = _books.filter((bookObj) => bookObj.bookId === bookId?.toUpperCase()); - if (currentBook) { - const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); - const books = [{ - selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, - bookCode: currentBook.bookId.toLowerCase(), - data: fileData, - }]; - setUsfmData(books); - setbookAvailable(true); - } else { - setUsfmData([]); - setbookAvailable(false); - } - // setUsfmData(fileData); - } catch (err) { - // eslint-disable-next-line no-console - return console.log(err); - } - } - readLocalFile(); - }, [bookId]); - return { usfmData, bookAvailable }; -}; diff --git a/renderer/src/layouts/editor/SectionContainer.js b/renderer/src/layouts/editor/SectionContainer.js index 4e4415eb2..fffa5e607 100644 --- a/renderer/src/layouts/editor/SectionContainer.js +++ b/renderer/src/layouts/editor/SectionContainer.js @@ -28,6 +28,20 @@ const SectionContainer = () => { const data = fs.readFileSync(metaPath, 'utf-8'); const metadata = JSON.parse(data); setEditor(metadata.type.flavorType.flavor.name); + + if (metadata.type.flavorType.flavor.name === 'textTranslation') { + // Check for project_cache folder and create if it doesn't exist + const projectCachePath = path.join(newpath, packageInfo.name, 'users', username, 'project_cache', projectName); + if (!fs.existsSync(projectCachePath)) { + fs.mkdirSync(projectCachePath, { recursive: true }); + } + + // Check for fileCacheMap.json and create if it doesn't exist + const fileCacheMapPath = path.join(projectCachePath, 'fileCacheMap.json'); + if (!fs.existsSync(fileCacheMapPath)) { + fs.writeFileSync(fileCacheMapPath, JSON.stringify({}), 'utf-8'); + } + } }); }); }, [editor]); diff --git a/renderer/src/modules/editorsidebar/EditorSideBar.js b/renderer/src/modules/editorsidebar/EditorSideBar.js index 34742ca90..24b166ffb 100644 --- a/renderer/src/modules/editorsidebar/EditorSideBar.js +++ b/renderer/src/modules/editorsidebar/EditorSideBar.js @@ -18,14 +18,15 @@ import { BookmarkIcon, } from '@heroicons/react/24/outline'; +import { NoteEditor } from '@biblionexus-foundation/scribe-editor'; import PinIcon from '@/icons/basil/Outline/Status/Pin.svg'; import CrossReferenceIcon from '@/icons/crossreference.svg'; import FootNotesIcon from '@/icons/footnotes.svg'; import Search from './Search'; -import CrossReferences from './CrossReferences'; +// import CrossReferences from './CrossReferences'; // import FootNotes from './FootNotes'; -import GraftEditor from './GraftEditor'; +// import GraftEditor from './GraftEditor'; import Comments from './Comments'; import Bookmarks from '../../components/EditorPage/BookMarks/Bookmarks'; @@ -54,7 +55,7 @@ export default function EditorSideBar(props) { const { isOpen, closeSideBar, - graftProps, + notesProps, } = props; const { @@ -192,10 +193,18 @@ export default function EditorSideBar(props) {
{state.tabIndex === 0 && } - {state.tabIndex === 1 - && } - {state.tabIndex === 2 - && } + {/* {state.tabIndex === 1 + && } */} + {state.tabIndex === 2 && ( + + )} + {/* && } */} {state.tabIndex === 3 && } {state.tabIndex === 4 diff --git a/styles/globals.css b/styles/globals.css index 0bc61f88d..b11a89c2c 100755 --- a/styles/globals.css +++ b/styles/globals.css @@ -109,7 +109,7 @@ p.paragraph:has(.chapter) { } .ref-editor ::selection { - @apply bg-primary-50; + @apply bg-primary-50; } /* .perf .verse:after { @@ -271,7 +271,7 @@ p.paragraph:has(.chapter) { margin: 0.1em; } */ .button { - @apply flex h-8 cursor-pointer items-center justify-center rounded-lg p-2 text-xs font-bold outline-none xl:px-4; + @apply flex h-8 cursor-pointer items-center justify-center rounded-lg p-2 text-xs font-bold outline-none xl:px-4; } .pdfViewer { @@ -576,28 +576,7 @@ MODAL SECTION SELECTION BLOCK END #sundesmosToolbar { background-color: #E5E7EB; border-color: white; -} - -.chunk-row:hover { - background-color: rgba(135, 206, 250, 0.3); -} - -div.draggable { - border-color: #121212; - border-width: 1px; -} - -@media (prefers-color-scheme: dark) { - .source-text { - color: #ffffff; - } -} -@media (prefers-color-scheme: light) { - .source-text { - color: #121212; - } -} .prevent-select { -webkit-user-select: none; @@ -856,4 +835,2420 @@ Select scribe theme Start align-self: "flex-end"; margin-top: 16; margin-right: 16; -} \ No newline at end of file +} + + +} +.editor-input { + text-align: start; +} + +.editor-input > p { + direction: inherit; + margin-top: 0; + margin-bottom: 0; + line-height: 1.5; +} + +/* USJ Nodes */ + +.leadingFloat { + float: start; +} +.clearFloat { + clear: both; +} +.align_start { + text-align: start; +} +.align_center { + text-align: center; +} +.align_end { + text-align: end; +} +@font-face { + font-family: 'Charis SIL'; + src: local('Charis SIL'), local('Charis SIL Bold'), + local('Charis SIL Bold Italic'), local('Charis SIL Italic'), + url('file:///C:/Windows/Fonts/CharisSIL-B.ttf'); + font-weight: normal; +} +@font-face { + font-family: 'Charis SIL'; + src: local('Charis SIL Bold'); + font-weight: bold; +} +@font-face { + font-family: 'Charis SIL'; + src: local('Charis SIL Italic'); + font-style: italic; +} +@font-face { + font-family: 'Charis SIL'; + src: local('Charis SIL Bold Italic'); + font-weight: bold; + font-style: italic; +} +.formatted-font .usfm { + font-family: 'Charis SIL'; + font-size: 12pt; +} + +/* BookNode */ + +.usfm_id { + display: none; +} +.formatted-font .usfm_id { + font-size: 100%; +} + +/* ChapterNode, ImmutableChapterNode */ + +.formatted-font .usfm_c { + @apply text-primary block break-before-column font-medium uppercase tracking-wider before:content-['Chapter_:_']; +} +.text-spacing[dir='ltr'] .usfm_c { + @apply pl-4 text-left; +} +.text-spacing[dir='rtl'] .usfm_c { + @apply pr-4 text-right; +} +.formatted-font .usfm_ca { + color: #007306; + font-size: 133%; + font-style: italic; +} + +.formatted-font .usfm_cp { + font-weight: bold; + color: #003380; + font-size: 150%; +} +.text-spacing .usfm_cp { + margin-bottom: 4pt; + margin-top: 8pt; +} + +/* VerseNode, ImmutableVerseNode */ + +.formatted-font .usfm_v { + @apply align-top text-xs uppercase tracking-wider text-primary; +} +.text-spacing[dir='ltr'] .usfm_v { + @apply text-left; +} +.text-spacing[dir='rtl'] .usfm_v { + @apply text-right; +} + +.formatted-font .usfm_va { + color: #007306; + font-size: 100%; + vertical-align: text-top; + font-size: 66%; +} + +.formatted-font .usfm_vp { + color: #003380; + font-size: 100%; + vertical-align: text-top; + font-size: 66%; +} + +/* ParaNode */ + +.formatted-font .usfm_usfm { + font-size: 100%; +} + +.formatted-font .usfm_ide { + font-size: 100%; + display: none; +} + +.formatted-font .usfm_h { + font-size: 100%; + display: none; +} + +.formatted-font .usfm_h1 { + font-size: 100%; +} + +.formatted-font .usfm_h2 { + font-size: 100%; +} + +.formatted-font .usfm_h3 { + font-size: 100%; +} + +.usfm_toc1 { + @apply hidden; +} +.formatted-font .usfm_toc1 { + @apply font-bold italic text-green-900; +} +.text-spacing[dir='ltr'] .usfm_toc1 { + @apply ml-2 text-left; +} +.text-spacing[dir='rtl'] .usfm_toc1 { + @apply mr-2 text-right; +} + +.usfm_toc2 { + @apply hidden; +} +.formatted-font .usfm_toc2 { + @apply italic text-green-900; +} +.text-spacing[dir='ltr'] .usfm_toc2 { + @apply ml-2 text-left; +} +.text-spacing[dir='rtl'] .usfm_toc2 { + @apply mr-2 text-right; +} + +.usfm_toc3 { + @apply hidden; +} +.formatted-font .usfm_toc3 { + @apply font-bold italic text-red-500; +} +.text-spacing[dir='ltr'] .usfm_toc3 { + @apply ml-2 text-left; +} +.text-spacing[dir='rtl'] .usfm_toc3 { + @apply mr-2 text-right; +} + +.formatted-font .usfm_toca1 { + color: #8c8c8c; + font-size: 83%; + font-style: italic; +} + +.formatted-font .usfm_toca2 { + color: #8c8c8c; + font-size: 83%; + font-style: italic; +} + +.formatted-font .usfm_toca3 { + color: #8c8c8c; + font-size: 83%; + font-style: italic; +} + +.formatted-font .usfm_rem { + color: #003380; + font-size: 100%; +} + +.formatted-font .usfm_sts { + color: #003380; + font-size: 100%; +} + +.formatted-font .usfm_restore { + color: #003380; + font-size: 100%; +} + +.formatted-font .usfm_imt { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_imt { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_imt1 { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_imt1 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_imt2 { + font-size: 108%; + font-style: italic; +} +.text-spacing .usfm_imt2 { + text-align: center; + margin-bottom: 3pt; + margin-top: 6pt; +} + +.formatted-font .usfm_imt3 { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_imt3 { + text-align: center; + margin-bottom: 2pt; + margin-top: 2pt; +} + +.formatted-font .usfm_imt4 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_imt4 { + text-align: center; + margin-bottom: 2pt; + margin-top: 2pt; +} + +.formatted-font .usfm_imte { + font-weight: bold; + font-size: 166%; +} +.text-spacing .usfm_imte { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_imte1 { + font-weight: bold; + font-size: 166%; +} +.text-spacing .usfm_imte1 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_imte2 { + font-size: 133%; + font-style: italic; +} +.text-spacing .usfm_imte2 { + text-align: center; + margin-bottom: 2pt; +} + +.formatted-font .usfm_is { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_is { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_is1 { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_is1 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_is2 { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_is2 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_iot { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_iot { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_io { + font-size: 100%; +} +.text-spacing[dir='ltr'] .usfm_io { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_io { + margin-right: 10vw; +} + +.formatted-font .usfm_io1 { + font-size: 100%; +} +.text-spacing[dir='ltr'] .usfm_io1 { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_io1 { + margin-right: 10vw; +} + +.formatted-font .usfm_io2 { + font-size: 100%; +} +.text-spacing[dir='ltr'] .usfm_io2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_io2 { + margin-right: 15vw; +} + +.formatted-font .usfm_io3 { + font-size: 100%; +} +.text-spacing[dir='ltr'] .usfm_io3 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_io3 { + margin-right: 20vw; +} + +.formatted-font .usfm_io4 { + font-size: 100%; +} +.text-spacing[dir='ltr'] .usfm_io4 { + margin-left: 25vw; +} +.text-spacing[dir='rtl'] .usfm_io4 { + margin-right: 25vw; +} + +.formatted-font .usfm_ior { + font-size: 100%; +} + +.formatted-font .usfm_ip { + font-size: 100%; +} +.text-spacing .usfm_ip { + text-indent: 2.5vw; +} + +.formatted-font .usfm_im { + font-size: 100%; +} + +.formatted-font .usfm_ipi { + font-size: 100%; +} +.text-spacing .usfm_ipi { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_imi { + font-size: 100%; +} +.text-spacing .usfm_imi { + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_ili { + font-size: 100%; +} +.text-spacing .usfm_ili { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_ili { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_ili { + margin-right: 10vw; +} + +.formatted-font .usfm_ili1 { + font-size: 100%; +} +.text-spacing .usfm_ili1 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_ili1 { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_ili1 { + margin-right: 10vw; +} + +.formatted-font .usfm_ili2 { + font-size: 100%; +} +.text-spacing .usfm_ili2 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_ili2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_ili2 { + margin-right: 15vw; +} + +.formatted-font .usfm_ipq { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_ipq { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_imq { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_imq { + margin-left: 5vw; + margin-right: 5vw; +} + +.usfm_ipr { + text-align: end; +} +.formatted-font .usfm_ipr { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_ipr { + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_ib { + font-size: 83%; +} + +.formatted-font .usfm_iq { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_iq { + text-indent: -15vw; +} +.text-spacing[dir='ltr'] .usfm_iq { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_iq { + margin-right: 20vw; +} + +.formatted-font .usfm_iq1 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_iq1 { + text-indent: -15vw; +} +.text-spacing[dir='ltr'] .usfm_iq1 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_iq1 { + margin-right: 20vw; +} + +.formatted-font .usfm_iq2 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_iq2 { + text-indent: -10vw; +} +.text-spacing[dir='ltr'] .usfm_iq2 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_iq2 { + margin-right: 20vw; +} + +.formatted-font .usfm_iq3 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_iq3 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_iq3 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_iq3 { + margin-right: 20vw; +} + +.formatted-font .usfm_iex { + font-size: 100%; +} +.text-spacing .usfm_iex { + text-indent: 2.5vw; + margin-bottom: 4pt; + margin-top: 4pt; +} + +.formatted-font .usfm_iqt { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_ie { + font-size: 83%; +} + +.formatted-font .usfm_cl { + font-weight: bold; + font-size: 150%; +} +.text-spacing .usfm_cl { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_cd { + font-size: 91%; +} +.text-spacing .usfm_cd { + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_p { + font-size: 100%; +} +.text-spacing .usfm_p { + text-indent: 2.5vw; +} + +.formatted-font .usfm_m { + font-size: 100%; +} + +.formatted-font .usfm_po { + font-size: 100%; +} +.text-spacing .usfm_po { + text-indent: 2.5vw; + margin-bottom: 4pt; + margin-top: 4pt; +} + +.usfm_pr { + text-align: end; +} +.formatted-font .usfm_pr { + font-size: 100%; +} + +.usfm_cls { + text-align: end; +} +.formatted-font .usfm_cls { + font-size: 100%; +} + +.formatted-font .usfm_pmo { + font-size: 100%; +} +.text-spacing .usfm_pmo { + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_pm { + font-size: 100%; +} +.text-spacing .usfm_pm { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_pmc { + font-size: 100%; +} +.text-spacing .usfm_pmc { + margin-left: 5vw; + margin-right: 5vw; +} + +.usfm_pmr { + text-align: end; +} +.formatted-font .usfm_pmr { + font-size: 100%; +} +.text-spacing .usfm_pmr { + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_pi { + font-size: 100%; +} +.text-spacing .usfm_pi { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_pi1 { + font-size: 100%; +} +.text-spacing .usfm_pi1 { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_pi2 { + font-size: 100%; +} +.text-spacing .usfm_pi2 { + text-indent: 2.5vw; +} +.text-spacing[dir='ltr'] .usfm_pi2 { + margin-left: 10vw; + margin-right: 5vw; +} +.text-spacing[dir='rtl'] .usfm_pi2 { + margin-left: 5vw; + margin-right: 10vw; +} + +.formatted-font .usfm_pi3 { + font-size: 100%; +} +.text-spacing .usfm_pi3 { + text-indent: 2.5vw; +} +.text-spacing[dir='ltr'] .usfm_pi3 { + margin-left: 15vw; + margin-right: 5vw; +} +.text-spacing[dir='rtl'] .usfm_pi3 { + margin-left: 5vw; + margin-right: 15vw; +} + +.formatted-font .usfm_pc { + font-size: 100%; +} +.text-spacing .usfm_pc { + text-align: center; +} + +.formatted-font .usfm_mi { + font-size: 100%; +} +.text-spacing .usfm_mi { + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_nb { + font-size: 100%; +} + +.formatted-font .usfm_q { + font-size: 100%; +} +.text-spacing .usfm_q { + text-indent: -10vw; +} +.text-spacing[dir='ltr'] .usfm_q { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_q { + margin-right: 15vw; +} + +.formatted-font .usfm_q1 { + font-size: 100%; +} +.text-spacing .usfm_q1 { + text-indent: -10vw; +} +.text-spacing[dir='ltr'] .usfm_q1 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_q1 { + margin-right: 15vw; +} + +.formatted-font .usfm_q2 { + font-size: 100%; +} +.text-spacing .usfm_q2 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_q2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_q2 { + margin-right: 15vw; +} + +.formatted-font .usfm_q3 { + font-size: 100%; +} +.text-spacing .usfm_q3 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_q3 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_q3 { + margin-right: 15vw; +} + +.formatted-font .usfm_q4 { + font-size: 100%; +} +.text-spacing .usfm_q4 { + text-indent: -2.5vw; +} +.text-spacing[dir='ltr'] .usfm_q4 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_q4 { + margin-right: 15vw; +} + +.formatted-font .usfm_qc { + font-size: 100%; +} +.text-spacing .usfm_qc { + text-align: center; +} + +.usfm_qr { + text-align: end; +} +.formatted-font .usfm_qr { + font-size: 100%; +} + +.formatted-font .usfm_qa { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_qm { + font-size: 100%; +} +.text-spacing .usfm_qm { + text-indent: -15vw; +} +.text-spacing[dir='ltr'] .usfm_qm { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_qm { + margin-right: 20vw; +} + +.formatted-font .usfm_qm1 { + font-size: 100%; +} +.text-spacing .usfm_qm1 { + text-indent: -15vw; +} +.text-spacing[dir='ltr'] .usfm_qm1 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_qm1 { + margin-right: 20vw; +} + +.formatted-font .usfm_qm2 { + font-size: 100%; +} +.text-spacing .usfm_qm2 { + text-indent: -10vw; +} +.text-spacing[dir='ltr'] .usfm_qm2 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_qm2 { + margin-right: 20vw; +} + +.formatted-font .usfm_qm3 { + font-size: 100%; +} +.text-spacing .usfm_qm3 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_qm3 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_qm3 { + margin-right: 20vw; +} + +.formatted-font .usfm_qd { + font-size: 100%; + font-style: italic; +} +.text-spacing[dir='ltr'] .usfm_qd { + margin-left: 5vw; +} +.text-spacing[dir='rtl'] .usfm_qd { + margin-right: 5vw; +} + +.formatted-font .usfm_b { + font-size: 83%; +} + +.formatted-font .usfm_mt { + font-weight: bold; + font-size: 166%; +} +.text-spacing .usfm_mt { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_mt1 { + @apply text-2xl font-bold; +} +.text-spacing .usfm_mt1 { + @apply my-2 text-center; +} + +.formatted-font .usfm_mt2 { + font-size: 133%; + font-style: italic; +} +.text-spacing .usfm_mt2 { + text-align: center; + margin-bottom: 2pt; +} + +.formatted-font .usfm_mt3 { + font-weight: bold; + font-size: 133%; +} +.text-spacing .usfm_mt3 { + text-align: center; + margin-bottom: 2pt; + margin-top: 2pt; +} + +.formatted-font .usfm_mt4 { + font-size: 100%; +} +.text-spacing .usfm_mt4 { + text-align: center; + margin-bottom: 2pt; + margin-top: 2pt; +} + +.formatted-font .usfm_mte { + font-weight: bold; + font-size: 166%; +} +.text-spacing .usfm_mte { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_mte1 { + font-weight: bold; + font-size: 166%; +} +.text-spacing .usfm_mte1 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_mte2 { + font-size: 133%; + font-style: italic; +} +.text-spacing .usfm_mte2 { + text-align: center; + margin-bottom: 2pt; +} + +.formatted-font .usfm_ms { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_ms { + text-align: center; + margin-bottom: 4pt; + margin-top: 16pt; +} + +.formatted-font .usfm_ms1 { + @apply text-lg; +} +.text-spacing .usfm_ms1 { + @apply m-2 text-center; +} + +.formatted-font .usfm_ms2 { + font-weight: bold; + font-size: 116%; +} +.text-spacing .usfm_ms2 { + text-align: center; + margin-bottom: 4pt; + margin-top: 16pt; +} + +.formatted-font .usfm_ms3 { + font-size: 116%; + font-style: italic; +} +.text-spacing .usfm_ms3 { + text-align: center; + margin-bottom: 4pt; + margin-top: 16pt; +} + +.formatted-font .usfm_mr { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_mr { + text-align: center; + margin-bottom: 4pt; +} + +.formatted-font .usfm_s { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_s { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_s1 { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_s1 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_s2 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_s2 { + text-align: center; + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_s3 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_s3 { + margin-bottom: 3pt; + margin-top: 6pt; +} + +.formatted-font .usfm_s4 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_s4 { + margin-bottom: 3pt; + margin-top: 6pt; +} + +.formatted-font .usfm_sr { + font-weight: bold; + font-size: 100%; +} +.text-spacing .usfm_sr { + text-align: center; + margin-bottom: 4pt; +} + +.formatted-font .usfm_r { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_r { + text-align: center; + margin-bottom: 4pt; +} + +.formatted-font .usfm_sp { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_sp { + margin-bottom: 4pt; + margin-top: 8pt; +} + +.formatted-font .usfm_d { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_d { + text-align: center; + margin-bottom: 4pt; + margin-top: 4pt; +} + +.text-spacing .usfm_sd { + margin-bottom: 24pt; + margin-top: 24pt; +} + +.text-spacing .usfm_sd1 { + margin-bottom: 24pt; + margin-top: 24pt; +} + +.text-spacing .usfm_sd2 { + margin-bottom: 18pt; + margin-top: 18pt; +} + +.text-spacing .usfm_sd3 { + margin-bottom: 12pt; + margin-top: 12pt; +} + +.text-spacing .usfm_sd4 { + margin-bottom: 8pt; + margin-top: 8pt; +} + +.formatted-font .usfm_lh { + font-size: 100%; +} +.text-spacing .usfm_lh { + text-indent: 2.5vw; +} + +.formatted-font .usfm_li { + font-size: 100%; +} +.text-spacing .usfm_li { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_li { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_li { + margin-right: 10vw; +} + +.formatted-font .usfm_li1 { + font-size: 100%; +} +.text-spacing .usfm_li1 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_li1 { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_li1 { + margin-right: 10vw; +} + +.formatted-font .usfm_li2 { + font-size: 100%; +} +.text-spacing .usfm_li2 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_li2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_li2 { + margin-right: 15vw; +} + +.formatted-font .usfm_li3 { + font-size: 100%; +} +.text-spacing .usfm_li3 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_li3 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_li3 { + margin-right: 20vw; +} + +.formatted-font .usfm_li4 { + font-size: 100%; +} +.text-spacing .usfm_li4 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_li4 { + margin-left: 25vw; +} +.text-spacing[dir='rtl'] .usfm_li4 { + margin-right: 25vw; +} + +.formatted-font .usfm_lf { + font-size: 100%; +} + +.formatted-font .usfm_lim { + font-size: 100%; +} +.text-spacing .usfm_lim { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_lim { + margin-left: 15vw; + margin-right: 5vw; +} +.text-spacing[dir='rtl'] .usfm_lim { + margin-left: 5vw; + margin-right: 15vw; +} + +.formatted-font .usfm_lim1 { + font-size: 100%; +} +.text-spacing .usfm_lim1 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_lim1 { + margin-left: 15vw; + margin-right: 5vw; +} +.text-spacing[dir='rtl'] .usfm_lim1 { + margin-left: 5vw; + margin-right: 15vw; +} + +.formatted-font .usfm_lim2 { + font-size: 100%; +} +.text-spacing .usfm_lim2 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_lim2 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_lim2 { + margin-right: 20vw; +} + +.formatted-font .usfm_lim3 { + font-size: 100%; +} +.text-spacing .usfm_lim3 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_lim3 { + margin-left: 25vw; +} +.text-spacing[dir='rtl'] .usfm_lim3 { + margin-right: 25vw; +} + +.formatted-font .usfm_lim4 { + font-size: 100%; +} +.text-spacing .usfm_lim4 { + text-indent: -7.5vw; +} +.text-spacing[dir='ltr'] .usfm_lim4 { + margin-left: 30vw; +} +.text-spacing[dir='rtl'] .usfm_lim4 { + margin-right: 30vw; +} + +.usfm_lit { + text-align: end; +} +.formatted-font .usfm_lit { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_ph { + font-size: 100%; +} +.text-spacing .usfm_ph { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_ph { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_ph { + margin-right: 10vw; +} + +.formatted-font .usfm_ph1 { + font-size: 100%; +} +.text-spacing .usfm_ph1 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_ph1 { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_ph1 { + margin-right: 10vw; +} + +.formatted-font .usfm_ph2 { + font-size: 100%; +} +.text-spacing .usfm_ph2 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_ph2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_ph2 { + margin-right: 15vw; +} + +.formatted-font .usfm_ph3 { + font-size: 100%; +} +.text-spacing .usfm_ph3 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_ph3 { + margin-left: 20vw; +} +.text-spacing[dir='rtl'] .usfm_ph3 { + margin-right: 20vw; +} + +/* CharNode */ + +.formatted-font .usfm_qs { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_qac { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_litl { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_lik { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_liv { + font-size: 100%; +} + +.formatted-font .usfm_liv1 { + font-size: 100%; +} + +.formatted-font .usfm_liv2 { + font-size: 100%; +} + +.formatted-font .usfm_liv3 { + font-size: 100%; +} + +.formatted-font .usfm_liv4 { + font-size: 100%; +} + +.formatted-font .usfm_liv5 { + font-size: 100%; +} + +.formatted-font .usfm_rq { + font-size: 83%; + font-style: italic; +} + +.formatted-font .usfm_qt { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_nd { + font-size: 100%; + text-decoration: underline; +} + +.formatted-font .usfm_tl { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_dc { + font-style: italic; +} + +.formatted-font .usfm_bk { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_sig { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_pn { + font-weight: bold; + font-size: 100%; + text-decoration: underline; +} + +.formatted-font .usfm_png { + font-size: 100%; + text-decoration: underline; +} + +.formatted-font .usfm_addpn { + font-weight: bold; + font-size: 100%; + font-style: italic; + text-decoration: underline; +} + +.formatted-font .usfm_wj { + color: #d43128; + font-size: 100%; +} + +.formatted-font .usfm_k { + font-weight: bold; + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_sls { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_ord { + vertical-align: text-top; + font-size: 66%; +} + +.formatted-font .usfm_add { + font-weight: bold; + font-style: italic; +} + +.formatted-font .usfm_no { + font-size: 100%; +} + +.formatted-font .usfm_it { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_bd { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_bdit { + font-weight: bold; + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_em { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_sc { + font-size: 100%; + font-variant: small-caps; +} + +.formatted-font .usfm_sup { + vertical-align: text-top; + font-size: 66%; +} + +.formatted-font .usfm_pb { + font-size: 100%; +} + +.formatted-font .usfm_fig { + font-size: 100%; +} + +.formatted-font .usfm_jmp { + color: #003380; + text-decoration: underline; +} + +.formatted-font .usfm_pro { + font-size: 83%; +} + +.formatted-font .usfm_rb { + font-size: 100%; +} + +.formatted-font .usfm_w { + font-size: 100%; +} + +.formatted-font .usfm_wh { + font-size: 100%; +} + +.formatted-font .usfm_wg { + font-size: 100%; +} + +.formatted-font .usfm_wa { + font-size: 100%; +} + +.formatted-font .usfm_ndx { + font-size: 100%; +} + +/* Footnote NoteNode */ + +.formatted-font .usfm_f { + font-size: 80%; + position: relative; + top: -0.5em; +} + +.formatted-font .usfm_fe { + font-size: 100%; +} + +/* Footnote CharNode */ + +.formatted-font .usfm_fr { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_ft { + font-size: 100%; +} + +.formatted-font .usfm_fk { + font-weight: bold; + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_fq { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_fqa { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_fl { + font-weight: bold; + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_fw { + font-size: 100%; +} + +.formatted-font .usfm_fp { + font-size: 100%; +} + +.formatted-font .usfm_fv { + vertical-align: text-top; + font-size: 66%; +} + +.formatted-font .usfm_fdc { + font-size: 100%; +} + +.formatted-font .usfm_fm { + vertical-align: text-top; + font-size: 66%; +} + +/* Cross-reference NoteNode */ + +.formatted-font .usfm_x { + font-size: 100%; +} + +/* Cross-reference CharNode */ + +.formatted-font .usfm_xo { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_xop { + font-size: 100%; +} + +.formatted-font .usfm_xt { + font-size: 100%; + unicode-bidi: embed; +} + +.formatted-font .usfm_xta { + font-size: 100%; +} + +.formatted-font .usfm_xk { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_xq { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_xot { + font-size: 100%; +} + +.formatted-font .usfm_xnt { + font-size: 100%; +} + +.formatted-font .usfm_xdc { + font-size: 100%; +} + +/* periph */ + +.formatted-font .usfm_periph { + font-weight: bold; + color: #e87217; + font-size: 116%; +} +.text-spacing .usfm_periph { + margin-bottom: 4pt; + margin-top: 16pt; +} + +.formatted-font .usfm_p1 { + font-size: 100%; +} +.text-spacing .usfm_p1 { + text-indent: 2.5vw; +} + +.formatted-font .usfm_p2 { + font-size: 100%; +} +.text-spacing .usfm_p2 { + text-indent: 2.5vw; +} +.text-spacing[dir='ltr'] .usfm_p2 { + margin-left: 2.5vw; +} +.text-spacing[dir='rtl'] .usfm_p2 { + margin-right: 2.5vw; +} + +.formatted-font .usfm_k1 { + font-size: 100%; +} + +.formatted-font .usfm_k2 { + font-size: 100%; +} + +.formatted-font .usfm_xtSee { + color: #003380; + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_xtSeeAlso { + color: #003380; + font-size: 100%; + font-style: italic; +} + +/* MilestoneNode */ + +.formatted-font .usfm_qt-s { + font-size: 100%; +} + +.formatted-font .usfm_qt-e { + font-size: 100%; +} + +.formatted-font .usfm_qt1-s { + font-size: 100%; +} + +.formatted-font .usfm_qt1-e { + font-size: 100%; +} + +.formatted-font .usfm_qt2-s { + font-size: 100%; +} + +.formatted-font .usfm_qt2-e { + font-size: 100%; +} + +.formatted-font .usfm_qt3-s { + font-size: 100%; +} + +.formatted-font .usfm_qt3-e { + font-size: 100%; +} + +.formatted-font .usfm_qt4-s { + font-size: 100%; +} + +.formatted-font .usfm_qt4-e { + font-size: 100%; +} + +.formatted-font .usfm_qt5-s { + font-size: 100%; +} + +.formatted-font .usfm_qt5-e { + font-size: 100%; +} + +.formatted-font .usfm_ts-s { + font-size: 100%; +} + +.formatted-font .usfm_ts-e { + font-size: 100%; +} + +/* table */ + +.formatted-font .usfm_tr { + font-size: 100%; +} +.text-spacing .usfm_tr { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_tr { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_tr { + margin-right: 10vw; +} + +.formatted-font .usfm_th1 { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_th2 { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_th3 { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_th4 { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_th5 { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_tc1 { + font-size: 100%; +} + +.formatted-font .usfm_tc2 { + font-size: 100%; +} + +.formatted-font .usfm_tc3 { + font-size: 100%; +} + +.formatted-font .usfm_tc4 { + font-size: 100%; +} + +.formatted-font .usfm_tc5 { + font-size: 100%; +} + +.formatted-font .usfm_thc1 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thc1 { + text-align: center; +} + +.formatted-font .usfm_thc2 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thc2 { + text-align: center; +} + +.formatted-font .usfm_thc3 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thc3 { + text-align: center; +} + +.formatted-font .usfm_thc4 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thc4 { + text-align: center; +} + +.formatted-font .usfm_thc5 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thc5 { + text-align: center; +} + +.formatted-font .usfm_tcc1 { + font-size: 100%; +} +.text-spacing .usfm_tcc1 { + text-align: center; +} + +.formatted-font .usfm_tcc2 { + font-size: 100%; +} +.text-spacing .usfm_tcc2 { + text-align: center; +} + +.formatted-font .usfm_tcc3 { + font-size: 100%; +} +.text-spacing .usfm_tcc3 { + text-align: center; +} + +.formatted-font .usfm_tcc4 { + font-size: 100%; +} +.text-spacing .usfm_tcc4 { + text-align: center; +} + +.formatted-font .usfm_tcc5 { + font-size: 100%; +} +.text-spacing .usfm_tcc5 { + text-align: center; +} + +.formatted-font .usfm_thr1 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thr1 { + text-align: end; +} + +.formatted-font .usfm_thr2 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thr2 { + text-align: end; +} + +.formatted-font .usfm_thr3 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thr3 { + text-align: end; +} + +.formatted-font .usfm_thr4 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thr4 { + text-align: end; +} + +.formatted-font .usfm_thr5 { + font-size: 100%; + font-style: italic; +} +.text-spacing .usfm_thr5 { + text-align: end; +} + +.formatted-font .usfm_tcr1 { + font-size: 100%; +} +.text-spacing .usfm_tcr1 { + text-align: end; +} + +.formatted-font .usfm_tcr2 { + font-size: 100%; +} +.text-spacing .usfm_tcr2 { + text-align: end; +} + +.formatted-font .usfm_tcr3 { + font-size: 100%; +} +.text-spacing .usfm_tcr3 { + text-align: end; +} + +.formatted-font .usfm_tcr4 { + font-size: 100%; +} +.text-spacing .usfm_tcr4 { + text-align: end; +} + +.formatted-font .usfm_tcr5 { + font-size: 100%; +} +.text-spacing .usfm_tcr5 { + text-align: end; +} + +/* table/unknown */ + +.formatted-font .usfm_tr1 { + font-size: 100%; +} +.text-spacing .usfm_tr1 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_tr1 { + margin-left: 10vw; +} +.text-spacing[dir='rtl'] .usfm_tr1 { + margin-right: 10vw; +} + +.formatted-font .usfm_tr2 { + font-size: 100%; +} +.text-spacing .usfm_tr2 { + text-indent: -5vw; +} +.text-spacing[dir='ltr'] .usfm_tr2 { + margin-left: 15vw; +} +.text-spacing[dir='rtl'] .usfm_tr2 { + margin-right: 15vw; +} + +.formatted-font .usfm_ps { + font-size: 100%; +} +.text-spacing .usfm_ps { + text-indent: 2.5vw; +} + +.formatted-font .usfm_psi { + font-size: 100%; +} +.text-spacing .usfm_psi { + text-indent: 2.5vw; + margin-left: 5vw; + margin-right: 5vw; +} + +.formatted-font .usfm_fs { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_wr { + font-size: 100%; + font-style: italic; +} + +.formatted-font .usfm_pub { + font-size: 83%; +} + +.formatted-font .usfm_toc { + font-size: 83%; +} + +.formatted-font .usfm_pref { + font-size: 83%; +} + +.formatted-font .usfm_intro { + font-size: 83%; +} + +.formatted-font .usfm_conc { + font-size: 83%; +} + +.formatted-font .usfm_glo { + font-size: 83%; +} + +.formatted-font .usfm_idx { + font-size: 83%; +} + +.formatted-font .usfm_maps { + font-size: 83%; +} + +.formatted-font .usfm_cov { + font-size: 83%; +} + +.formatted-font .usfm_spine { + font-size: 83%; +} + +.formatted-font .usfm_pubinfo { + color: #003380; + font-size: 100%; +} + +.formatted-font .usfm_zpa-xb { + font-size: 100%; +} + +.formatted-font .usfm_zpa-xc { + font-weight: bold; + font-size: 100%; +} + +.formatted-font .usfm_zpa-xv { + font-size: 100%; +} + +.formatted-font .usfm_zpa-d { + font-size: 100%; +} + +body { + background-color: rgba(252, 252, 252, 1); + color: rgba(25, 25, 25, 1); +} + +.marker { + unicode-bidi: isolate; +} +.formatted-font .marker { + color: rgba(140, 140, 140, 1); + font-size: 0.7em; +} + +/* Used for unformatted displays */ +.markerplain { + unicode-bidi: isolate; +} + +.notetext { + unicode-bidi: embed; +} + +.attribute { + color: rgba(170, 170, 170, 1); +} + +.attribute:hover { + color: rgba(25, 25, 25, 1); +} + +.invalid { + color: rgba(204, 30, 20, 1); + font-weight: bold; +} + +/* NoteNode, ImmutableNoteCallerNode */ + +.immutable-note-caller > button, +/* Styles for Preview (and Ruby) views */ +.caller_preview, +.previewcallee { + color: rgba(18, 82, 179, 1); + font-weight: bold; + line-height: 1; + vertical-align: super; + font-size: 0.66em; +} + +.immutable-note-caller > button { + cursor: pointer; + text-decoration: none; + border: 0; + padding: 0; + background-color: inherit; +} + +.immutable-note-caller[data-caller='-'] { + display: none; +} + +.formatted-font .immutable-note-caller { + @apply text-xs text-blue-500; +} + +.caller_big { + unicode-bidi: normal; + color: rgba(18, 82, 179, 1); + font-weight: bold; + text-indent: 0pt; + vertical-align: text-top; + font-size: 0.66em; +} + +.caller_small { + unicode-bidi: normal; + color: rgba(18, 82, 179, 1); + font-family: Times New Roman; + vertical-align: text-top; + text-indent: 0pt; + font-size: 0.66em; +} + +.caller_highlight { + background-color: #ffffb5; + border-top: solid 1px #0000ff; + border-bottom: solid 1px #0000ff; +} + +.opennote { + color: #7777ff; +} + +rt { + cursor: pointer; +} + +/* Style statues */ +.status_unknown { + color: rgba(204, 30, 20, 1); + font-weight: bold; +} + +.status_invalid { + border-bottom: 1px solid rgba(204, 30, 20, 1); + color: rgba(204, 30, 20, 1); +} + +.caption { + text-align: center; + font-style: italic; + font-weight: bold; +} + +.figure { + text-align: center; +} + +.sidebar { + border: solid 1px rgba(18, 82, 179, 1); + margin-left: 10px; +} + +/* VerseNode, ImmutableVerseNode */ + +/* +.formatted-font .verse { + @apply text-cyan-500; + background-color: rgba(222, 222, 222, 1); + vertical-align: super; + font-size: 0.66em; +} +.text-spacing .verse { + margin: 0px 2px 0px 2px; + padding: 0px 1px 0px 1px; + text-indent: 0in; + white-space: nowrap; +} +*/ + +.annot_comment_todo { + border-bottom: 1px dashed #888888; +} +.annot_comment_todo { + border-bottom: 1px dashed #888888; +} +span.unread img { + background-color: #ffff99; + position: relative; + bottom: -1px; /* negative of border-width to align baseline */ + border-width: 1px; + border-style: solid; + border-color: #808080; +} +span.read img { + background-color: transparent; + position: relative; + bottom: 0px; + border-width: 0px; + border-style: none; +} + +.annot_comment_todo { + border-bottom: 1px dashed #888888; +} + +.annot_comment_done { + border-bottom: 1px dashed #888888; +} + +.annot_greencursor { + background-color: rgba(152, 235, 157, 1); +} +.annot_goldcursor { + background-color: rgba(255, 255, 163, 1); +} +.annot_bluecursor { + background-color: rgba(204, 224, 255, 1); +} +.annot_greycursor { + background-color: rgba(222, 222, 222, 1); +} +.annot_violetcursor { + background-color: rgba(233, 212, 255, 1); +} + +.annot_spellingerror { + background-repeat: repeat-x; + background-position: left bottom; + padding-bottom: 0px; + vertical-align: text-top; +} + +.annot_spellingunknown { + background-repeat: repeat-x; + background-position: left bottom; + padding-bottom: 0px; + vertical-align: text-top; +} + +.found_term { + background-color: rgba(222, 222, 222, 1); + text-indent: 0; + margin-left: 0; + display: inline-block; + border-bottom-style: solid; + border-bottom-width: medium medium thick medium; + border-bottom-color: rgba(252, 252, 252, 1); + text-decoration: inherit; +} +.guessed_term { + background-color: rgba(255, 191, 143, 1); + text-indent: 0; + margin-left: 0; + display: inline-block; + border-bottom-style: solid; + border-bottom-width: medium medium thick medium; + border-bottom-color: rgba(252, 252, 252, 1); + text-decoration: inherit; +} +.found_term.unselected_term { + background-color: rgba(222, 222, 222, 0.6); + text-indent: 0; + margin-left: 0; + display: inline-block; + border-bottom-style: solid; + border-bottom-width: medium medium thick medium; + border-bottom-color: rgba(252, 252, 252, 1); + text-decoration: inherit; +} +.guessed_term.unselected_term { + background-color: rgba(255, 191, 143, 0.3); + text-indent: 0; + margin-left: 0; + display: inline-block; + border-bottom-style: solid; + border-bottom-width: medium medium thick medium; + border-bottom-color: rgba(252, 252, 252, 1); + text-decoration: inherit; +} +.selected_term { + border-style: none none solid none; + text-indent: 0; + margin-left: 0; + display: inline-block; + border-bottom-style: solid; + border-bottom-width: medium medium thick medium; + border-bottom-color: rgba(252, 252, 252, 1); + text-decoration: inherit; +} +.annot_reference_link { + border-bottom: 1px solid #93c4ff; +} +.annot_invalid_reference { + border-bottom: 1px solid #ff8080; +} +.annot_checkError { + border-top: 1px solid #ff0000; + border-bottom: 1px solid #ff0000; + background-color: rgba(255, 204, 204, 0.5); +} + +/* ContextMenuPlugin */ + +.auto-embed-menu { + width: 150px; +} + +.typeahead-popover { + background: #fff; + box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3); + border-radius: 8px; +} + +.typeahead-popover ul { + padding: 0; + list-style: none; + margin: 0; + border-radius: 8px; + max-height: 200px; + overflow-y: scroll; + -ms-overflow-style: none; + scrollbar-width: none; +} + +.typeahead-popover ul::-webkit-scrollbar { + display: none; +} + +.typeahead-popover ul li { + margin: 0; + min-width: 180px; + font-size: 14px; + outline: none; + cursor: pointer; + border-radius: 8px; +} + +.typeahead-popover ul li.selected { + background: #eee; +} + +.typeahead-popover li { + margin: 0 8px 0 8px; + padding: 8px; + color: #050505; + cursor: pointer; + line-height: 16px; + font-size: 15px; + display: flex; + align-content: center; + flex-direction: row; + flex-shrink: 0; + background-color: #fff; + border-radius: 8px; + border: 0; +} + +.typeahead-popover li.active { + display: flex; + width: 20px; + height: 20px; + background-size: contain; +} + +.typeahead-popover li:first-child { + border-radius: 8px 8px 0px 0px; +} + +.typeahead-popover li:last-child { + border-radius: 0px 0px 8px 8px; +} + +.typeahead-popover li:hover { + background-color: #eee; +} + +.typeahead-popover li .text { + display: flex; + line-height: 20px; + flex-grow: 1; + min-width: 150px; +} + +.typeahead-popover li .icon { + display: flex; + width: 20px; + height: 20px; + user-select: none; + margin-right: 8px; + line-height: 16px; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} diff --git a/yarn.lock b/yarn.lock index 9050bac93..5ac165303 100755 --- a/yarn.lock +++ b/yarn.lock @@ -87,7 +87,7 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.24.7": +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== @@ -113,7 +113,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.25.0", "@babel/helper-create-class-features-plugin@^7.25.4": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.25.0", "@babel/helper-create-class-features-plugin@^7.25.4": version "7.25.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz#57eaf1af38be4224a9d9dd01ddde05b741f50e14" integrity sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ== @@ -361,6 +361,16 @@ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== +"@babel/plugin-proposal-private-property-in-object@^7.21.11": + version "7.21.11" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" + integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.21.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-proposal-throw-expressions@^7.18.6", "@babel/plugin-proposal-throw-expressions@^7.22.5": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.24.7.tgz#8a386bcb77965d82f5b926508b27919d9ac9450f" @@ -1187,11 +1197,55 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@biblionexus-foundation/scribe-editor@0.1.2-scribe-v1": + version "0.1.2-scribe-v1" + resolved "https://registry.yarnpkg.com/@biblionexus-foundation/scribe-editor/-/scribe-editor-0.1.2-scribe-v1.tgz#1368b95b1ba71d7a5257868bdf4735f33ea525b7" + integrity sha512-8cAqbdz+VdBima+q7Yr22b537nddICiBn+mI4/ctuke+FlCobHEweQgigNAaTOBF9h1dzOF0H+sHiBvETUceow== + dependencies: + "@biblionexus-foundation/scripture-utilities" "^0.0.4" + "@lexical/mark" "^0.17.1" + "@lexical/react" "^0.17.1" + "@lexical/selection" "^0.17.1" + "@lexical/utils" "^0.17.1" + autoprefixer "^10.4.20" + fast-equals "^5.0.1" + lexical "^0.17.1" + +"@biblionexus-foundation/scripture-utilities@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@biblionexus-foundation/scripture-utilities/-/scripture-utilities-0.0.4.tgz#aac4cd5c7ffd98b60990b661b475f2c0f8a5a832" + integrity sha512-EslK90TulsLaePMRhcJV/lClFC7NTdbQXbNCXbMN4rR07ES9ZSqKRKaMelNOtWh0eZgXa+glBf7mPC2vdwM6uQ== + dependencies: + "@xmldom/xmldom" "^0.8.10" + "@capacitor/app@5.0.6": version "5.0.6" resolved "https://registry.yarnpkg.com/@capacitor/app/-/app-5.0.6.tgz#2ee02551115fd2e92dc7e81bc30a6c6fa78efa66" integrity sha512-6ZXVdnNmaYILasC/RjQw+yfTmq2ZO7Q3v5lFcDVfq3PFGnybyYQh+RstBrYri+376OmXOXxBD7E6UxBhrMzXGA== +"@capacitor/cli@5.4.2": + version "5.4.2" + resolved "https://registry.yarnpkg.com/@capacitor/cli/-/cli-5.4.2.tgz#673ef8ff19b87e896467bac57b8272b223273051" + integrity sha512-ck2DC9hEai2BWsBM08WN98xjC2LDusSzUWQySTNQ81S/cQUpSPXk9YX+KTd3rP/kI/sXpOuDEe7SSS7qkD1a2w== + dependencies: + "@ionic/cli-framework-output" "^2.2.5" + "@ionic/utils-fs" "^3.1.6" + "@ionic/utils-subprocess" "^2.1.11" + "@ionic/utils-terminal" "^2.3.3" + commander "^9.3.0" + debug "^4.3.4" + env-paths "^2.2.0" + kleur "^4.1.4" + native-run "^1.7.3" + open "^8.4.0" + plist "^3.0.5" + prompts "^2.4.2" + rimraf "^4.4.1" + semver "^7.3.7" + tar "^6.1.11" + tslib "^2.4.0" + xml2js "^0.5.0" + "@capacitor/core@5.4.2": version "5.4.2" resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-5.4.2.tgz#c7303f6b0b080e5f585b79399f246701c4c8ea84" @@ -1739,6 +1793,15 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@ionic/cli-framework-output@^2.2.5": + version "2.2.8" + resolved "https://registry.yarnpkg.com/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz#29d541acc7773a6aaceec5f3b079937fbcef5402" + integrity sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g== + dependencies: + "@ionic/utils-terminal" "2.3.5" + debug "^4.0.0" + tslib "^2.0.1" + "@ionic/core@7.8.6": version "7.8.6" resolved "https://registry.yarnpkg.com/@ionic/core/-/core-7.8.6.tgz#523f5a3d0fd52c9560213a32719af06fe3f6d769" @@ -1765,6 +1828,96 @@ ionicons "^7.0.0" tslib "*" +"@ionic/utils-array@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@ionic/utils-array/-/utils-array-2.1.6.tgz#eee863be945ee1a28b9a10ff16fdea776fa18c22" + integrity sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg== + dependencies: + debug "^4.0.0" + tslib "^2.0.1" + +"@ionic/utils-fs@3.1.7", "@ionic/utils-fs@^3.1.6": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@ionic/utils-fs/-/utils-fs-3.1.7.tgz#e0d41225272c346846867e88a0b84b1a4ee9d9c9" + integrity sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA== + dependencies: + "@types/fs-extra" "^8.0.0" + debug "^4.0.0" + fs-extra "^9.0.0" + tslib "^2.0.1" + +"@ionic/utils-object@2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@ionic/utils-object/-/utils-object-2.1.6.tgz#c0259bf925b6c12663d06f6bc1703e5dcb565e6d" + integrity sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww== + dependencies: + debug "^4.0.0" + tslib "^2.0.1" + +"@ionic/utils-process@2.1.11": + version "2.1.11" + resolved "https://registry.yarnpkg.com/@ionic/utils-process/-/utils-process-2.1.11.tgz#ac06dfa2307027095ab0420a234924a9effeb6bd" + integrity sha512-Uavxn+x8j3rDlZEk1X7YnaN6wCgbCwYQOeIjv/m94i1dzslqWhqIHEqxEyeE8HsT5Negboagg7GtQiABy+BLbA== + dependencies: + "@ionic/utils-object" "2.1.6" + "@ionic/utils-terminal" "2.3.4" + debug "^4.0.0" + signal-exit "^3.0.3" + tree-kill "^1.2.2" + tslib "^2.0.1" + +"@ionic/utils-stream@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@ionic/utils-stream/-/utils-stream-3.1.6.tgz#7c2fdcf4d9e621e8b2260e2fee2471825a4e214f" + integrity sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA== + dependencies: + debug "^4.0.0" + tslib "^2.0.1" + +"@ionic/utils-subprocess@^2.1.11": + version "2.1.14" + resolved "https://registry.yarnpkg.com/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz#06224bdc6d9891ed86b1e556fc172a0eeabdc846" + integrity sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg== + dependencies: + "@ionic/utils-array" "2.1.6" + "@ionic/utils-fs" "3.1.7" + "@ionic/utils-process" "2.1.11" + "@ionic/utils-stream" "3.1.6" + "@ionic/utils-terminal" "2.3.4" + cross-spawn "^7.0.3" + debug "^4.0.0" + tslib "^2.0.1" + +"@ionic/utils-terminal@2.3.4": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@ionic/utils-terminal/-/utils-terminal-2.3.4.tgz#e40c44b676265ed6a07a68407bda6e135870f879" + integrity sha512-cEiMFl3jklE0sW60r8JHH3ijFTwh/jkdEKWbylSyExQwZ8pPuwoXz7gpkWoJRLuoRHHSvg+wzNYyPJazIHfoJA== + dependencies: + "@types/slice-ansi" "^4.0.0" + debug "^4.0.0" + signal-exit "^3.0.3" + slice-ansi "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + tslib "^2.0.1" + untildify "^4.0.0" + wrap-ansi "^7.0.0" + +"@ionic/utils-terminal@2.3.5", "@ionic/utils-terminal@^2.3.3": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz#a48465f40496ee8f29c6d92e4506d5f19762ac3c" + integrity sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A== + dependencies: + "@types/slice-ansi" "^4.0.0" + debug "^4.0.0" + signal-exit "^3.0.3" + slice-ansi "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + tslib "^2.0.1" + untildify "^4.0.0" + wrap-ansi "^7.0.0" + "@ioredis/commands@^1.1.1": version "1.2.0" resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" @@ -2643,6 +2796,207 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== +"@lexical/clipboard@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/clipboard/-/clipboard-0.17.1.tgz#816b2559e60c5cfb5df5c6a4d1d1dcd850662d14" + integrity sha512-OVqnEfWX8XN5xxuMPo6BfgGKHREbz++D5V5ISOiml0Z8fV/TQkdgwqbBJcUdJHGRHWSUwdK7CWGs/VALvVvZyw== + dependencies: + "@lexical/html" "0.17.1" + "@lexical/list" "0.17.1" + "@lexical/selection" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/code@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/code/-/code-0.17.1.tgz#1db1cd221fb6ec74342e8a6526ec8ac370f4c06b" + integrity sha512-ZspfTm6g6dN3nAb4G5bPp3SqxzdkB/bjGfa0uRKMU6/eBKtrMUgZsGxt0a8JRZ1eq2TZrQhx+l1ceRoLXii/bQ== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + prismjs "^1.27.0" + +"@lexical/devtools-core@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/devtools-core/-/devtools-core-0.17.1.tgz#08e0e0fe7312486a41b49d75c075d6edf60fc11e" + integrity sha512-SzL1EX9Rt5GptIo87t6nDxAc9TtYtl6DyAPNz/sCltspdd69KQgs23sTRa26/tkNFCS1jziRN7vpN3mlnmm5wA== + dependencies: + "@lexical/html" "0.17.1" + "@lexical/link" "0.17.1" + "@lexical/mark" "0.17.1" + "@lexical/table" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/dragon@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/dragon/-/dragon-0.17.1.tgz#e196a8a226889f0d0a7ef271163e9cecd53b8a85" + integrity sha512-lhBRKP7RlhiVCLtF0qiNqmMhEO6cQB43sMe7d4bvuY1G2++oKY/XAJPg6QJZdXRrCGRQ6vZ26QRNhRPmCxL5Ng== + dependencies: + lexical "0.17.1" + +"@lexical/hashtag@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/hashtag/-/hashtag-0.17.1.tgz#137896cff6d7d2e3638cfc8cadf1d3e035809c14" + integrity sha512-XtP0BI8vEewAe7tzq9MC49UPUvuChuNJI/jqFp+ezZlt/RUq0BClQCOPuSlrTJhluvE2rWnUnOnVMk8ILRvggQ== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/history@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/history/-/history-0.17.1.tgz#864f8bd5450bc6a2b513e02c42f022299400e63b" + integrity sha512-OU/ohajz4FXchUhghsWC7xeBPypFe50FCm5OePwo767G7P233IztgRKIng2pTT4zhCPW7S6Mfl53JoFHKehpWA== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/html@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/html/-/html-0.17.1.tgz#746ecfeea6a1aef3b0a5ce821cf059262f182dd5" + integrity sha512-yGG+K2DXl7Wn2DpNuZ0Y3uCHJgfHkJN3/MmnFb4jLnH1FoJJiuy7WJb/BRRh9H+6xBJ9v70iv+kttDJ0u1xp5w== + dependencies: + "@lexical/selection" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/link@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/link/-/link-0.17.1.tgz#ef93c41710e33028512986334c98df7f0ad285c4" + integrity sha512-qFJEKBesZAtR8kfJfIVXRFXVw6dwcpmGCW7duJbtBRjdLjralOxrlVKyFhW9PEXGhi4Mdq2Ux16YnnDncpORdQ== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/list@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/list/-/list-0.17.1.tgz#8b29d42fe310b25de0a160577adf5fc0b7c2a874" + integrity sha512-k9ZnmQuBvW+xVUtWJZwoGtiVG2cy+hxzkLGU4jTq1sqxRIoSeGcjvhFAK8JSEj4i21SgkB1FmkWXoYK5kbwtRA== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/mark@0.17.1", "@lexical/mark@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/mark/-/mark-0.17.1.tgz#58e74f494e3dc4a43b5b5efd1b28436f2941f937" + integrity sha512-V82SSRjvygmV+ZMwVpy5gwgr2ZDrJpl3TvEDO+G5I4SDSjbgvua8hO4dKryqiDVlooxQq9dsou0GrZ9Qtm6rYg== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/markdown@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/markdown/-/markdown-0.17.1.tgz#e5435f4aa711f0859433eba2b96ee2afb04b636a" + integrity sha512-uexR9snyT54jfQTrbr/GZAtzX+8Oyykr4p1HS0vCVL1KU5MDuP2PoyFfOv3rcfB2TASc+aYiINhU2gSXzwCHNg== + dependencies: + "@lexical/code" "0.17.1" + "@lexical/link" "0.17.1" + "@lexical/list" "0.17.1" + "@lexical/rich-text" "0.17.1" + "@lexical/text" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/offset@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/offset/-/offset-0.17.1.tgz#3c008d9a0eb17ff0a056e6db4eab61f1ae909522" + integrity sha512-fX0ZSIFWwUKAjxf6l21vyXFozJGExKWyWxA+EMuOloNAGotHnAInxep0Mt8t/xcvHs7luuyQUxEPw7YrTJP7aw== + dependencies: + lexical "0.17.1" + +"@lexical/overflow@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/overflow/-/overflow-0.17.1.tgz#f158c5498cac353764d7f0c8c53b42ee14582f5b" + integrity sha512-oElVDq486R3rO2+Zz0EllXJGpW3tN0tfcH+joZ5h36+URKuNeKddqkJuDRvgSLOr9l8Jhtv3+/YKduPJVKMz6w== + dependencies: + lexical "0.17.1" + +"@lexical/plain-text@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/plain-text/-/plain-text-0.17.1.tgz#da03dfee8862622c150e64db823065a4eff751cd" + integrity sha512-CSvi4j1a4ame0OAvOKUCCmn2XrNsWcST4lExGTa9Ei/VIh8IZ+a97h4Uby8T3lqOp10x+oiizYWzY30pb9QaBg== + dependencies: + "@lexical/clipboard" "0.17.1" + "@lexical/selection" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/react@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/react/-/react-0.17.1.tgz#ec9595e6d554d3d8787885db4558848233c2ce33" + integrity sha512-DI4k25tO0E1WyozrjaLgKMOmLjOB7+39MT4eZN9brPlU7g+w0wzdGbTZUPgPmFGIKPK+MSLybCwAJCK97j8HzQ== + dependencies: + "@lexical/clipboard" "0.17.1" + "@lexical/code" "0.17.1" + "@lexical/devtools-core" "0.17.1" + "@lexical/dragon" "0.17.1" + "@lexical/hashtag" "0.17.1" + "@lexical/history" "0.17.1" + "@lexical/link" "0.17.1" + "@lexical/list" "0.17.1" + "@lexical/mark" "0.17.1" + "@lexical/markdown" "0.17.1" + "@lexical/overflow" "0.17.1" + "@lexical/plain-text" "0.17.1" + "@lexical/rich-text" "0.17.1" + "@lexical/selection" "0.17.1" + "@lexical/table" "0.17.1" + "@lexical/text" "0.17.1" + "@lexical/utils" "0.17.1" + "@lexical/yjs" "0.17.1" + lexical "0.17.1" + react-error-boundary "^3.1.4" + +"@lexical/rich-text@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/rich-text/-/rich-text-0.17.1.tgz#c74b8d5d2ca767e021c313e4f3258e1ecf5cd1a6" + integrity sha512-T3kvj4P1OpedX9jvxN3WN8NP1Khol6mCW2ScFIRNRz2dsXgyN00thH1Q1J/uyu7aKyGS7rzcY0rb1Pz1qFufqQ== + dependencies: + "@lexical/clipboard" "0.17.1" + "@lexical/selection" "0.17.1" + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/selection@0.17.1", "@lexical/selection@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/selection/-/selection-0.17.1.tgz#9a537e69fec4e5682b43b226239c78fd7af19811" + integrity sha512-qBKVn+lMV2YIoyRELNr1/QssXx/4c0id9NCB/BOuYlG8du5IjviVJquEF56NEv2t0GedDv4BpUwkhXT2QbNAxA== + dependencies: + lexical "0.17.1" + +"@lexical/table@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/table/-/table-0.17.1.tgz#62473f95a96c44ab20e4a1c1dec4b53a5093897c" + integrity sha512-2fUYPmxhyuMQX3MRvSsNaxbgvwGNJpHaKx1Ldc+PT2MvDZ6ALZkfsxbi0do54Q3i7dOon8/avRp4TuVaCnqvoA== + dependencies: + "@lexical/utils" "0.17.1" + lexical "0.17.1" + +"@lexical/text@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/text/-/text-0.17.1.tgz#b54ce8c7e6d891e063321d340172053bb43bbd87" + integrity sha512-zD2pAGXaMfPpT8PeNrx3+n0+jGnQORHyn0NEBO+hnyacKfUq5z5sI6Gebsq5NwH789bRadmJM5LvX5w8fsuv6w== + dependencies: + lexical "0.17.1" + +"@lexical/utils@0.17.1", "@lexical/utils@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/utils/-/utils-0.17.1.tgz#58465121a977a04b7995efde6fde8ca97cbfff8d" + integrity sha512-jCQER5EsvhLNxKH3qgcpdWj/necUb82Xjp8qWQ3c0tyL07hIRm2tDRA/s9mQmvcP855HEZSmGVmR5SKtkcEAVg== + dependencies: + "@lexical/list" "0.17.1" + "@lexical/selection" "0.17.1" + "@lexical/table" "0.17.1" + lexical "0.17.1" + +"@lexical/yjs@0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@lexical/yjs/-/yjs-0.17.1.tgz#6d13506f168f465fd6e68cc64aa822b6c49adedb" + integrity sha512-9mn5PDtaH5uLMH6hQ59EAx5FkRzmJJFcVs3E6zSIbtgkG3UASR3CFEfgsLKTjl/GC5NnTGuMck+jXaupDVBhOg== + dependencies: + "@lexical/offset" "0.17.1" + lexical "0.17.1" + "@malept/cross-spawn-promise@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" @@ -4455,6 +4809,13 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/fs-extra@^8.0.0": + version "8.1.5" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.5.tgz#33aae2962d3b3ec9219b5aca2555ee00274f5927" + integrity sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ== + dependencies: + "@types/node" "*" + "@types/fs-extra@^9.0.11": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -4793,6 +5154,11 @@ "@types/node" "*" "@types/send" "*" +"@types/slice-ansi@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/slice-ansi/-/slice-ansi-4.0.0.tgz#eb40dfbe3ac5c1de61f6bcb9ed471f54baa989d6" + integrity sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ== + "@types/sockjs@^0.3.33": version "0.3.36" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" @@ -5174,7 +5540,7 @@ lodash.isequal "^4.5.0" use-deep-compare "^1.1.0" -"@xmldom/xmldom@^0.8.8": +"@xmldom/xmldom@^0.8.10", "@xmldom/xmldom@^0.8.8": version "0.8.10" resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== @@ -5927,7 +6293,7 @@ automation-events@^7.0.9: "@babel/runtime" "^7.25.6" tslib "^2.7.0" -autoprefixer@^10.4.13: +autoprefixer@^10.4.13, autoprefixer@^10.4.20: version "10.4.20" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== @@ -6425,7 +6791,7 @@ bidi-js@^1.0.2: dependencies: require-from-string "^2.0.2" -big-integer@^1.6.17: +big-integer@1.6.x, big-integer@^1.6.17: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== @@ -6549,6 +6915,13 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== +bplist-parser@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7" + integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ== + dependencies: + big-integer "1.6.x" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -6989,11 +7362,16 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001646: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001406: version "1.0.30001659" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001659.tgz#f370c311ffbc19c4965d8ec0064a3625c8aaa7af" integrity sha512-Qxxyfv3RdHAfJcXelgf0hU4DFUVXBGTjqrBUZLUh8AtlGnsDo+CnncYtTd95+ZKfnANUOzxyIQCuU/UeBZBYoA== +caniuse-lite@^1.0.30001646: + version "1.0.30001667" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz#99fc5ea0d9c6e96897a104a8352604378377f949" + integrity sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw== + canvas@^2.11.2: version "2.11.2" resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.11.2.tgz#553d87b1e0228c7ac0fc72887c3adbac4abbd860" @@ -7596,6 +7974,11 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.3.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + common-ancestor-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" @@ -9159,9 +9542,9 @@ electron-publish@23.6.0: mime "^2.5.2" electron-to-chromium@^1.5.4: - version "1.5.18" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz#5fe62b9d21efbcfa26571066502d94f3ed97e495" - integrity sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ== + version "1.5.27" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz#5203ce5d6054857d84ba84d3681cbe59132ade78" + integrity sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw== electron-updater@^5.0.1: version "5.3.0" @@ -9194,6 +9577,13 @@ element-resize-detector@^1.1.10: dependencies: batch-processor "1.0.0" +elementtree@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/elementtree/-/elementtree-0.1.7.tgz#9ac91be6e52fb6e6244c4e54a4ac3ed8ae8e29c0" + integrity sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg== + dependencies: + sax "1.1.4" + elliptic@^6.5.3, elliptic@^6.5.5: version "6.5.7" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" @@ -10243,6 +10633,11 @@ fast-equals@^3.0.1: resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-3.0.3.tgz#8e6cb4e51ca1018d87dd41982ef92758b3e4197f" integrity sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg== +fast-equals@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.0.1.tgz#a4eefe3c5d1c0d021aeed0bc10ba5e0c12ee405d" + integrity sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ== + fast-fifo@^1.2.0, fast-fifo@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" @@ -11123,6 +11518,16 @@ glob@^8.0.1: minimatch "^5.0.1" once "^1.3.0" +glob@^9.2.0: + version "9.3.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" + integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== + dependencies: + fs.realpath "^1.0.0" + minimatch "^8.0.2" + minipass "^4.2.4" + path-scurry "^1.6.1" + global-agent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6" @@ -11827,9 +12232,9 @@ humanize-ms@^1.2.1: ms "^2.0.0" hyphen@^1.6.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/hyphen/-/hyphen-1.10.4.tgz#ae16551b8a56ae7c34ffd4b98777221795e6c912" - integrity sha512-SejXzIpv9gOVdDWXd4suM1fdF1k2dxZGvuTdkOVLoazYfK7O4DykIQbdrvuyG+EaTNlXAGhMndtKrhykgbt0gg== + version "1.10.6" + resolved "https://registry.yarnpkg.com/hyphen/-/hyphen-1.10.6.tgz#0e779d280e696102b97d7e42f5ca5de2cc97e274" + integrity sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw== hyphenate-style-name@^1.0.3: version "1.1.0" @@ -12252,7 +12657,14 @@ is-cidr@^4.0.2: dependencies: cidr-regex "^3.1.1" -is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.8.1: +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-core-module@^2.15.1, is-core-module@^2.8.1: version "2.15.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== @@ -14366,6 +14778,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kleur@^4.1.4: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + klona@^2.0.4, klona@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" @@ -14446,6 +14863,11 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lexical@0.17.1, lexical@^0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/lexical/-/lexical-0.17.1.tgz#02f4057b82cb302ceb9ca9b031dcf9406be5780a" + integrity sha512-72/MhR7jqmyqD10bmJw8gztlCm4KDDT+TPtU4elqXrEvHoO5XENi34YAEUD9gIkPfqSwyLa9mwAX1nKzIr5xEA== + libnpmaccess@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.4.tgz#2dd158bd8a071817e2207d3b201d37cf1ad6ae6b" @@ -15718,6 +16140,13 @@ minimatch@^5.0.1, minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" +minimatch@^8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" + integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -15791,6 +16220,11 @@ minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: dependencies: yallist "^4.0.0" +minipass@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + minipass@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" @@ -15981,6 +16415,23 @@ napi-wasm@^1.1.0: resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.3.tgz#7bb95c88e6561f84880bb67195437b1cfbe99224" integrity sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg== +native-run@^1.7.3: + version "1.7.4" + resolved "https://registry.yarnpkg.com/native-run/-/native-run-1.7.4.tgz#b98b74812805cef8665cfceec651e66e662123e3" + integrity sha512-yDEwTp66vmXpqFiSQzz4sVQgyq5U58gGRovglY4GHh12ITyWa6mh6Lbpm2gViVOVD1JYFtYnwcgr7GTFBinXNA== + dependencies: + "@ionic/utils-fs" "^3.1.6" + "@ionic/utils-terminal" "^2.3.3" + bplist-parser "^0.3.2" + debug "^4.3.4" + elementtree "^0.1.7" + ini "^3.0.1" + plist "^3.0.6" + split2 "^4.1.0" + through2 "^4.0.2" + tslib "^2.4.0" + yauzl "^2.10.0" + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -17291,7 +17742,7 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.1: +path-scurry@^1.11.1, path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -17524,7 +17975,7 @@ playwright@1.47.0: optionalDependencies: fsevents "2.3.2" -plist@^3.0.1, plist@^3.0.4: +plist@^3.0.1, plist@^3.0.4, plist@^3.0.5, plist@^3.0.6: version "3.1.0" resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -18228,6 +18679,11 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +prismjs@^1.27.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + proc-log@^2.0.0, proc-log@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685" @@ -18867,6 +19323,13 @@ react-draggable@^4.4.3: clsx "^1.1.1" prop-types "^15.8.1" +react-error-boundary@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0" + integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA== + dependencies: + "@babel/runtime" "^7.12.5" + react-error-overlay@^6.0.11: version "6.0.11" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" @@ -19835,6 +20298,13 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755" + integrity sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og== + dependencies: + glob "^9.2.0" + rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -19989,6 +20459,11 @@ sass-loader@^12.3.0: klona "^2.0.4" neo-async "^2.6.2" +sax@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.4.tgz#74b6d33c9ae1e001510f179a91168588f1aedaa9" + integrity sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg== + sax@>=0.6.0, sax@^1.2.4: version "1.4.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" @@ -20131,11 +20606,18 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3: +semver@^7.0.0, semver@^7.1.1, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== +semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + semver@~7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -20400,6 +20882,13 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +sj-usfm-grammar@^3.0.0, sj-usfm-grammar@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sj-usfm-grammar/-/sj-usfm-grammar-3.0.3.tgz#3e62d05a386bdca2946b54fb910635fb1685b6d7" + integrity sha512-5c915LAa09Y5XYI3F+iLxRdVym+/YS+6zS7nerKzgm88l3koUEC+DLkwO7MTTRjInurU6gT8L0S/094wZ/Uphg== + dependencies: + sj-usfm-grammar "^3.0.0" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -20459,6 +20948,15 @@ slice-ansi@^3.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + smart-buffer@^4.0.2, smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -20690,6 +21188,11 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +split2@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@^1.1.2, sprintf-js@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" @@ -20898,7 +21401,7 @@ string-punctuation-tokenizer@2.1.2: dependencies: xregexp "^4.1.1" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -20916,6 +21419,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -21032,7 +21544,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -21053,6 +21565,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -21818,6 +22337,11 @@ translation-helps-rcl@3.5.12: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + treeverse@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-2.0.0.tgz#036dcef04bc3fd79a9b79a68d4da03e882d8a9ca" @@ -22372,6 +22896,11 @@ unstorage@1.9.0: ofetch "^1.1.1" ufo "^1.2.0" +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + untun@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.3.tgz#5d10dee37a3a5737ff03d158be877dae0a0e58a6" @@ -22536,7 +23065,7 @@ usfm-editor@0.8.7: slate-react "0.69.0" usfm-js "2.0.1" -usfm-grammar@^2.3.0: +usfm-grammar@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/usfm-grammar/-/usfm-grammar-2.3.1.tgz#58c635106f258e094bfce7d64ed5069a3469ab18" integrity sha512-kUQObcSJqxmtU2pOG5unLZ2hlwJQu9bFodTsQyDPDeSiEpZapzeHPl6zB+RyXkU1DplbQHzhJaMpV5342aRevg== @@ -22906,7 +23435,7 @@ watchpack@^2.4.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -wavesurfer.js@^6.6.2: +wavesurfer.js@^6.6.4: version "6.6.4" resolved "https://registry.yarnpkg.com/wavesurfer.js/-/wavesurfer.js-6.6.4.tgz#45e2d613fbfd60d906362ed6e11b649f481e4485" integrity sha512-nBbc0pD/3FdClxKUKL1UW2V9AJPL+JOjC8T6/YF9/FCAn4uo+H6Y8VBkXo9UJXIHoBewoc7iXj3tPeL0UCJhjA== @@ -23476,7 +24005,7 @@ worker-factory@^7.0.24, worker-factory@^7.0.29: fast-unique-numbers "^9.0.9" tslib "^2.7.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -23511,6 +24040,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"