From fce2c338e346cac7b7279316920910da0d6d3e42 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 16 Dec 2024 14:42:15 +0100 Subject: [PATCH 01/16] new clean branch for checks --- package.json | 5 +- .../EditorPage/TextEditor/ChecksContent.jsx | 97 +++ .../EditorPage/TextEditor/Editor.jsx | 302 +++++++++ .../EditorPage/TextEditor/hooks/usePerf.js | 6 + .../TextEditor/hooks/useReadUsfmFile.js | 15 +- .../src/components/Resources/ListResources.js | 1 + .../components/Resources/ResourcesPopUp.js | 38 +- .../components/Resources/ResourcesSideBar.js | 34 +- renderer/src/layouts/editor/CheckSelector.js | 124 ++++ renderer/src/layouts/editor/EditorSection.js | 154 ++++- styles/globals.css | 12 + yarn.lock | 639 +++++++++++++++++- 12 files changed, 1379 insertions(+), 48 deletions(-) create mode 100644 renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx create mode 100644 renderer/src/components/EditorPage/TextEditor/Editor.jsx create mode 100644 renderer/src/layouts/editor/CheckSelector.js diff --git a/package.json b/package.json index 41b89d024..c5ab24c72 100644 --- a/package.json +++ b/package.json @@ -186,7 +186,7 @@ "is-electron": "^2.2.1", "isomorphic-git": "^1.24.0", "js-yaml": "^4.1.0", - "jxl-pdf": "0.8.0", + "jxl-pdf": "0.9.0", "localforage": "1.10.0", "lodash.isequal": "^4.5.0", "markdown-translatable": "1.3.0", @@ -199,6 +199,7 @@ "next-on-netlify": "^3.0.1", "next-optimized-images": "^2.6.2", "nprogress": "^0.2.0", + "perf-checks": "^0.1.0", "phosphor-react": "^1.4.1", "postcss-import": "^15.1.0", "postcss-nested": "^6.0.0", @@ -253,4 +254,4 @@ "word-aligner": "$word-aligner", "@mui/lab": "$@mui/lab" } -} +} \ No newline at end of file diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx new file mode 100644 index 000000000..021d30e38 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -0,0 +1,97 @@ +/* eslint-disable no-unused-vars */ +import React, { useEffect, useState } from 'react'; +import { XMarkIcon } from '@heroicons/react/24/solid'; +import { SnackBar } from '@/components/SnackBar'; +import { Disclosure } from '@headlessui/react'; +import { ChevronUpIcon, ArrowPathIcon } from '@heroicons/react/20/solid'; +import LoadingScreen from '@/components/Loading/LoadingScreen'; +// import { useReadUsfmFile } from './hooks/useReadUsfmFile'; + +export default function ChecksContent({ content, updateContent }) { + const [openSnackBar, setOpenSnackBar] = useState(false); + const [snackText, setSnackText] = useState(''); + const [groupedData, setGroupedData] = useState({}); + const [error, setError] = useState(''); + const [isRefreshing, setIsRefreshing] = useState(false); + + + const isArray = Array.isArray(content); + + useEffect(() => { + if (isArray) { + let tmpGroupedData = {}; + let currentName = ""; + for (let check of content) { + currentName = check.name; + if (!tmpGroupedData[currentName]) { + tmpGroupedData[currentName] = []; + } + delete check.name; + tmpGroupedData[currentName].push(check); + } + setGroupedData(tmpGroupedData); + } + }, [content]); + + const handleRefreshClick = () => { + setIsRefreshing(true); + updateContent(); + + // Add delay to simulate refreshing and stop the rotation animation after 1 second + setTimeout(() => { + setIsRefreshing(false); + }, 1000); + }; + + return ( +
+
+

Checks

+ +
+
+ {(isRefreshing && (groupedData && Object.keys(groupedData).length < 1)) && } + {!isRefreshing && groupedData && Object.keys(groupedData).length > 0 ? ( + Object.keys(groupedData).map((key) => ( + + {({ open }) => ( + <> + + {key} + + + +
    + {groupedData[key].map((item, index) => ( +
  • + {item.args.cv} +
  • ) + )} +
+
+ + )} +
+ )) + ) : !isRefreshing && ( +

No content available.

+ )} +
+ +
+ ); +} diff --git a/renderer/src/components/EditorPage/TextEditor/Editor.jsx b/renderer/src/components/EditorPage/TextEditor/Editor.jsx new file mode 100644 index 000000000..5c4ad0688 --- /dev/null +++ b/renderer/src/components/EditorPage/TextEditor/Editor.jsx @@ -0,0 +1,302 @@ +import React, { + useContext, useEffect, useLayoutEffect, useRef, useState +} 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'; +import xre from 'xregexp'; + +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(() => { + // let incElems = document.getElementsByClassName('incorrect'); + // console.log("incElems ==", incElems); + // console.log("decorators ==", decorators); + // if (incElems.length > 0) { + // for (let elem of incElems) { + // if (elem.getAttribute('listener') !== 'true') { + // elem.addEventListener('click', function (e) { + // e.target.setAttribute('listener', 'true'); + // }); + // } + // }; + // } + // }, [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); + } + + function wrapWord(word) { + return "" + word + ""; + } + + function alreadyWrapped(str) { + const re = new RegExp('(.*?)', 'gi'); + const arr = re.exec(str); + if (arr && arr[0]) return true; + return false + } + + function getAWord() { + if (!String.prototype.splice) { + String.prototype.splice = function (start, delCount, newSubStr) { + return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount)); + }; + } + + let sequenceIds = htmlPerf ? Object.keys(htmlPerf?.sequencesHtml) : []; + + // console.log('mur ==', htmlPerf?.sequencesHtml[sequenceIds[0]].substring(murIndex, murIndex + 'mur'.length)); + + // let innerHtmlRegex = /<\/span>(.*?)(.*?)(.*?)]*)(\\b(?!${dict.slice(0, 2000).join('\\b|')}\\b)(?!\\d+)\\w+\\b)`, 'gui'); + const emptySpans = xre(/\s*<\/span>/gui); + const words = xre.match(htmlPerf.sequencesHtml[sequenceIds[0]], re, "all"); + + // console.log("inSpans", inSpans); + // let cleanedRet = xre.replace(htmlPerf.sequencesHtml[sequenceIds[0]], emptySpans, ""); + let ret = xre.replace(htmlPerf.sequencesHtml[sequenceIds[0]], re, "$1"); + // console.log('ret ==', ret); + // let tempIndexof = htmlPerf.sequencesHtml[sequenceIds[0]].search('incorrect'); + htmlPerf.sequencesHtml[sequenceIds[0]] = ret; + // let fullMatch = htmlPerf.sequencesHtml[sequenceIds[0]].substring(tempIndexof - 100, tempIndexof + 100); + // console.log('fullMatch ==', fullMatch); + // htmlPerf.sequencesHtml[sequenceIds[0]].replaceAll(re,) + // let match, result = []; + // while (match = xre.exec(htmlPerf.sequencesHtml[sequenceIds[0]], re), 0, 'sticky') { + // console.log('curr match ==', match); + // break; + // // result.push(match[1]); + // // pos = match.index + match[0].length; + // } + // console.log(result); + } + + + // const decorators = { + // embededHtml: [/<\/span>\\b(.*?)\\b$1"], + // } + // setDecorators({ + // embededHtml: [/<\/span>.*?(.*?).*?$1"], + // }); + // const matches = string.matchAll(regexp); + // const matches = re.exec(htmlPerf?.sequencesHtml[sequenceIds[0]]); + // let newWord, fullMatch, match; + // let matches = []; + // let tempIndexof = -1; + // let indexInHtmlPerf; + // let oneMatch; + // let fullCopyHtml = htmlPerf?.sequencesHtml[sequenceIds[0]]; + // while (match = re.exec(htmlPerf?.sequencesHtml[sequenceIds[0]])) { + // newWord = match[0]; + // indexInHtmlPerf = match.index; + // tempIndexof = newWord.search('\\bmur\\b'); + // if (tempIndexof != -1) { + // console.log("match", match.index, "==", match); + // newWord = match[0].substring(tempIndexof, tempIndexof + 'mur'.length); + // fullMatch = match[0].substring(tempIndexof - 25, tempIndexof + 'mur'.length + 5); + // if (!alreadyWrapped(fullMatch) && htmlPerf != undefined) { + // console.log('indexInHtmlPerf, indexInHtmlPerf + \'mur\'.length ==', indexInHtmlPerf, indexInHtmlPerf + 'mur'.length); + // console.log('slice BEFORE ==', fullCopyHtml.slice(indexInHtmlPerf - 200, indexInHtmlPerf + 'mur'.length + 200)); + // console.log('real slice ==', fullCopyHtml.slice(indexInHtmlPerf + tempIndexof, indexInHtmlPerf + tempIndexof + 'mur'.length)); + // fullCopyHtml = fullCopyHtml.slice(0, indexInHtmlPerf + tempIndexof) + wrapWord(newWord) + fullCopyHtml.slice(indexInHtmlPerf + tempIndexof + 'mur'.length); + // console.log('slice AFTER ==', fullCopyHtml.slice(indexInHtmlPerf - 100, indexInHtmlPerf + 'mur'.length + 100)); + // matches.push(newWord); + // htmlPerf.sequencesHtml[sequenceIds[0]] = fullCopyHtml; + // oneMatch = indexInHtmlPerf; + // } + // } + // } + + // let murIndex = htmlPerf?.sequencesHtml[sequenceIds[0]].indexOf('mur'); + // console.log(dict['ABANDONNER']); + // console.log('indexof(mur) ==', htmlPerf?.sequencesHtml[sequenceIds[0]].substring(murIndex, murIndex + 3)); + // array.map(m => m[1]); + // const array = [...matches]; + + // console.log("matches ==", array.map(m => m[1])); + // console.log("matches ==", matches); + + // console.log(sequenceIds); + // console.log('slice htmlPerf ==', htmlPerf?.sequencesHtml[sequenceIds[0]].slice(oneMatch - 100, oneMatch + 'mur'.length + 100)); + + } + + 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" + spellCheck="false" + > +
+ {!bookAvailable && } + {bookAvailable && (!sequenceId || bookChange) && } + {bookAvailable && sequenceId && !bookChange && ( + + )} +
+
+ ); +} diff --git a/renderer/src/components/EditorPage/TextEditor/hooks/usePerf.js b/renderer/src/components/EditorPage/TextEditor/hooks/usePerf.js index 18bdcccf8..8ee029374 100644 --- a/renderer/src/components/EditorPage/TextEditor/hooks/usePerf.js +++ b/renderer/src/components/EditorPage/TextEditor/hooks/usePerf.js @@ -99,6 +99,11 @@ export default function usePerf({ setHtmlPerf(newPerfHtml); }; + const getPerf = async () => { + const thePerf = await epiteleteHtml?.readPerf(bookCode); + return thePerf; + } + const canUndo = (epiteleteHtml?.canUndo && epiteleteHtml?.canUndo(bookCode)) || false; const canRedo = (epiteleteHtml?.canRedo && epiteleteHtml?.canRedo(bookCode)) || false; @@ -117,6 +122,7 @@ export default function usePerf({ exportUsfm, undo, redo, + getPerf, }; return { state, actions }; diff --git a/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js b/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js index 2f4fa52f0..516575e96 100644 --- a/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js +++ b/renderer/src/components/EditorPage/TextEditor/hooks/useReadUsfmFile.js @@ -5,7 +5,7 @@ import { readFile } from '../../../../core/editor/readFile'; import packageInfo from '../../../../../../package.json'; import { handleCache } from '../cacheUtils'; -export const useReadUsfmFile = (bookId) => { +export const useReadUsfmFile = (bookId, onlyUsfm=false) => { const [usfmData, setUsfmData] = useState([]); const [bookAvailable, setbookAvailable] = useState(false); const [usfmString, setUsfmString] = useState(''); @@ -39,16 +39,18 @@ export const useReadUsfmFile = (bookId) => { 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(), data: fileData, }]; setUsfmData(books); - setbookAvailable(true); - setUsfmString(fileData); - setCachedData(cachedData); + if(!onlyUsfm) { + const cachedData = await handleCache(filePath, fileData, projectCachePath, fileCacheMapPath); + setbookAvailable(true); + setUsfmString(fileData); + setCachedData(cachedData); + } } else { setUsfmData([]); setbookAvailable(false); @@ -62,6 +64,9 @@ export const useReadUsfmFile = (bookId) => { } readLocalFile(); }, [bookId]); + if(onlyUsfm) { + return usfmData; + } return { usfmData, bookAvailable, usfmString, bookId, cachedData, loading, booksInProject, }; diff --git a/renderer/src/components/Resources/ListResources.js b/renderer/src/components/Resources/ListResources.js index ab37a6184..57a4785f4 100644 --- a/renderer/src/components/Resources/ListResources.js +++ b/renderer/src/components/Resources/ListResources.js @@ -38,6 +38,7 @@ export const ListResources = ({ setFilteredResources, setfilteredBibleObsAudio, endPoint, + choosingSourceLang, }) => { const { states: { diff --git a/renderer/src/components/Resources/ResourcesPopUp.js b/renderer/src/components/Resources/ResourcesPopUp.js index b0b2ff3d6..0b795b9e7 100644 --- a/renderer/src/components/Resources/ResourcesPopUp.js +++ b/renderer/src/components/Resources/ResourcesPopUp.js @@ -22,6 +22,8 @@ export default function ResourcesPopUp( header, selectedProjectMeta, referenceResources, + choosingSourceLang, + setReferenceSourceLang }, ) { const cancelButtonRef = useRef(null); @@ -64,16 +66,29 @@ export default function ResourcesPopUp( const offlineResource = offline ? { offline: true, data: offline } : { offline: false }; - setReferenceResources({ - selectedResource: selectResource, - languageId: row, - refName: name, - header: title, - owner, - offlineResource, - flavor: flavorname, - ownership: userOrCommon, - }); + if (choosingSourceLang) { + setReferenceSourceLang({ + selectedResource: selectResource, + languageId: row, + refName: name, + header: title, + owner, + offlineResource, + flavor: flavorname, + ownership: userOrCommon, + }); + } else { + setReferenceResources({ + selectedResource: selectResource, + languageId: row, + refName: name, + header: title, + owner, + offlineResource, + flavor: flavorname, + ownership: userOrCommon, + }); + } removeSection(); }; @@ -116,7 +131,7 @@ export default function ResourcesPopUp(
- +
{selectResource !== 'local-helps' && (
@@ -194,6 +209,7 @@ export default function ResourcesPopUp( setLoading={setLoading} setSubMenuItems={setSubMenuItems} endPoint={searchSource} + choosingSourceLang={choosingSourceLang} /> )}
diff --git a/renderer/src/components/Resources/ResourcesSideBar.js b/renderer/src/components/Resources/ResourcesSideBar.js index 02eec3772..a6648a94f 100644 --- a/renderer/src/components/Resources/ResourcesSideBar.js +++ b/renderer/src/components/Resources/ResourcesSideBar.js @@ -24,6 +24,7 @@ export default function ResourcesSidebar({ setShowInput, setTitle, selectedProjectMeta, + choosingSourceLang, }) { const { t } = useTranslation(); const handleClick = (id) => { @@ -140,36 +141,45 @@ export default function ResourcesSidebar({
{resourcesList.map((resource, idx) => { const { Icon, id, title } = resource; + const isClickable = choosingSourceLang ? id === 'bible' : true; + if(choosingSourceLang) setSelectResource('bible'); return (
{}} selectedMenu={selectResource} setSelectedMenu={setSelectResource} setShowInput={setShowInput} />
- {resource.subCategory.length !== 0 - && resource.subCategory.map( - (subCategory, categoryIdx) => { - const { Icon, id, title } = subCategory; - return ( + {resource.subCategory.length !== 0 && + resource.subCategory.map((subCategory, categoryIdx) => { + return ( +
{} : handleClick} selectedMenu={selectResource} setSelectedMenu={setSelectResource} setShowInput={setShowInput} /> - ); - }, - )} +
+ ); + })}
); diff --git a/renderer/src/layouts/editor/CheckSelector.js b/renderer/src/layouts/editor/CheckSelector.js new file mode 100644 index 000000000..6e1ee6206 --- /dev/null +++ b/renderer/src/layouts/editor/CheckSelector.js @@ -0,0 +1,124 @@ +import React, { useState } from "react"; +import packageInfo from '../../../../package.json'; +import AdjustmentsVerticalIcon from '@/icons/Common/AdjustmentsVertical.svg'; +import md5 from 'md5'; +// import * as fs from 'node:fs/promises'; +// import path from "path"; + +const checksData = [ + { + name: "versestats::verse_stats", + description: "Checks for empty, short and long verses", + level: "minor", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::duplicate_chapters", + description: "Checks for duplicate chapter numbers", + level: "major", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::duplicate_verses", + description: "Checks for duplicate verse numbers", + level: "major", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::missing_chapters", + description: "Checks for missing chapter numbers", + level: "minor", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::missing_verses", + description: "Checks for missing verse numbers within chapters", + level: "major", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::out_of_order_chapters", + description: "Checks for out-of-order chapter numbers within chapters", + level: "major", + contentType: "perf", + children: [], + }, + { + name: "chapterverse::out_of_order_verses", + description: "Checks for out-of-order verse numbers within chapters", + level: "major", + contentType: "perf", + children: [], + }, +]; + +const CheckSelector = ({ showResourcesPanel, setChoosingSourceLang }) => { + const [selectedChecks, setSelectedChecks] = useState([]); + + const writeJSONToFile = (updatedChecks) => { + const fs = window.require('fs'); + const path = require('path'); + const generatedJSON = { + name: "Scribe checks", + description: "", + checks: checksData.filter((check) => updatedChecks.includes(check.name)), + }; + + const newpath = localStorage.getItem('userPath'); + console.log("newpath ==", newpath); + const projectsPath = path.join(newpath, packageInfo.name, 'config_checks.json'); + + const filePath = projectsPath; + try { + fs.writeFileSync(filePath, JSON.stringify(generatedJSON, null, 2), "utf8"); + } catch (error) { + console.error("Error writing file:", error); + } + }; + + const handleCheckToggle = (checkName) => { + setSelectedChecks((prev) => { + const updatedChecks = prev.includes(checkName) + ? prev.filter((name) => name !== checkName) + : [...prev, checkName]; + writeJSONToFile(updatedChecks); + return updatedChecks; + }); + }; + + return ( +
+

Checks Selector

+ +
+ {checksData.map((check) => ( + + ))} +
+
+ ); +}; + +export default CheckSelector; diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index e44105acd..5958a1184 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -5,6 +5,9 @@ import { useTranslation } from 'react-i18next'; import { ReferenceContext } from '@/components/context/ReferenceContext'; import { ProjectContext } from '@/components/context/ProjectContext'; import ResourcesPopUp from '@/components/Resources/ResourcesPopUp'; +import { readRefBurrito } from 'src/core/reference/readRefBurrito.js'; +import { readFile } from 'src/core/editor/readFile'; +import ChecksContent from '@/components/EditorPage/TextEditor/ChecksContent'; import { classNames } from '@/util/classNames'; import TaNavigation from '@/components/EditorPage/Reference/TA/TaNavigation'; import TwNavigation from '@/components/EditorPage/Reference/TW/TwNavigation'; @@ -13,8 +16,15 @@ import MenuDropdown from '@/components/MenuDropdown/MenuDropdown'; import AdjustmentsVerticalIcon from '@/icons/Common/AdjustmentsVertical.svg'; import XMarkIcon from '@/icons/Common/XMark.svg'; import SquaresPlusIcon from '@/icons/Common/SquaresPlus.svg'; +import { Cog8ToothIcon } from '@heroicons/react/24/outline'; import ConfirmationModal from './ConfirmationModal'; import * as logger from '../../logger'; +import packageInfo from '../../../../package.json'; +import localforage from 'localforage'; +import checker from 'perf-checks'; +import { Proskomma } from 'proskomma-core'; +import CheckSelector from './CheckSelector'; +// import ScriptureContentPicker from '@/components/ScriptureContentPicker/ScriptureContentPicker.tsx'; export default function EditorSection({ title, @@ -46,10 +56,14 @@ export default function EditorSection({ const [openResourcePopUp, setOpenResourcePopUp] = useState(false); const [openModal, setOpenModal] = useState(false); const [projectScriptureDir, setProjectScriptureDir] = useState(); + const [contentChecks, setContentChecks] = useState({}); + const [choosingSourceLang, setChoosingSourceLang] = useState(false); + const [referenceSourceLang, setReferenceSourceLang] = useState({}); const { t } = useTranslation(); const { state: { layout, + bookId, openResource1, openResource2, openResource3, @@ -57,6 +71,25 @@ export default function EditorSection({ }, actions: { setLayout }, } = useContext(ReferenceContext); + // const { + // state: { + // bookId, + // bookList, + // bookName, + // chapter, + // verse, + // chapterList, + // verseList, + // languageId, + // // closeNavigation, + // }, actions: { + // onChangeBook, + // onChangeChapter, + // onChangeVerse, + // applyBooksFilter, + // setCloseNavigation, + // }, + // } = useContext(ReferenceContext); const { states: { scrollLock, selectedProjectMeta }, } = useContext(ProjectContext); @@ -120,6 +153,13 @@ export default function EditorSection({ }); const showResourcesPanel = () => { + setChoosingSourceLang(false); + setOpenResourcePopUp(true); + setLoadResource(true); + }; + + const showResourcesPanelFromChecks = () => { + setChoosingSourceLang(true); setOpenResourcePopUp(true); setLoadResource(true); }; @@ -168,8 +208,63 @@ export default function EditorSection({ } }; + const checks = async () => { + const fse = window.require('fs-extra'); + const path = window.require('path'); + + // const usfmContent = { usfm: "\\id MRK" }; + const userProfile = await localforage.getItem('userProfile'); + const userName = userProfile?.username; + const projectName = await localforage.getItem('currentProject'); + 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 filePath = path.join(newpath, packageInfo.name, 'config_checks.json'); + let spec = {}; + try { + spec = fse.readJsonSync(filePath); + } catch (error) { + logger.error( + 'EditorSection.js', + 'Unable to open config_checks.json', + ); + } + 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()); + // const projectCachePath = path.join(newpath, packageInfo.name, 'users', userName, 'project_cache', projectName); + if (currentBook) { + const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); + const book = { + selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, + bookCode: currentBook.bookId?.toLowerCase(), + data: fileData, + }; + // setUsfmData(books); + const usfmContent = book.data; + const pk = new Proskomma(); + const selectors = { + lang: 'xxx', + abbr: 'yyy', + } + pk.importDocuments(selectors, 'usfm', [usfmContent]); + const perfResultDocument = pk.gqlQuerySync('{documents {perf} }').data.documents[0]; + const perf = JSON.parse(perfResultDocument.perf); + if (perf && spec.checks && spec.checks.length > 0) { + let ret = checker({ content: { perf }, spec, contentType: "perf" }); + setContentChecks(ret); + } + } + } + useEffect(() => { - // Since we are adding reference resources from different places the data we have are inconsistant. + // Since we are adding reference resources from different places we have inconsistant data. // Looking for flavor from the flavors because flavor is only available for scripture and gloss(obs), not for Translation resources const flavors = ['obs', 'bible', 'audio']; if ( @@ -303,6 +398,18 @@ export default function EditorSection({ setSelectedFont={setFont} showIcon={false} /> +
- {loadResource === false ? ( -
+ {loadResource === false && referenceResources.selectedResource !== 'checks' ? ( +
-
+
{t('label-editor-load-module')}
+ {selectedProjectMeta?.type?.flavorType?.flavor?.name == 'textTranslation' && + (
+
+ {"Open checks"} +
+ +
)}
- ) : ( + ) : referenceResources.selectedResource !== 'checks' ? (
{children}
+ ) : ( + <> + + + )} {/* //div 12 */} - {openResourcePopUp && ( + { openResourcePopUp && (
)} diff --git a/styles/globals.css b/styles/globals.css index fae1087fc..2b8721854 100755 --- a/styles/globals.css +++ b/styles/globals.css @@ -274,6 +274,18 @@ p.paragraph:has(.chapter) { @apply flex h-8 cursor-pointer items-center justify-center rounded-lg p-2 text-xs font-bold outline-none xl:px-4; } +span.incorrect { + text-decoration-line: underline; + text-decoration-color: #F24822; + text-decoration-style: wavy; + text-decoration-thickness: 1px; +} + +span.incorrect:hover { + background: var(--Primary-100, #FFCCB3); + cursor: pointer; +} + .pdfViewer { overflow-y: scroll; flex: 1; diff --git a/yarn.lock b/yarn.lock index 9dd11f308..51fd1ec75 100755 --- a/yarn.lock +++ b/yarn.lock @@ -2997,6 +2997,21 @@ "@lexical/offset" "0.17.1" lexical "0.17.1" +"@ljharb/resumer@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@ljharb/resumer/-/resumer-0.1.3.tgz#5ef4a4958da1b4e71ffea8ef33499cc622672d89" + integrity sha512-d+tsDgfkj9X5QTriqM4lKesCkMMJC3IrbPKHvayP00ELx2axdXvDfWkqjxrLXIzGcQzmj7VAUT1wopqARTvafw== + dependencies: + "@ljharb/through" "^2.3.13" + call-bind "^1.0.7" + +"@ljharb/through@^2.3.13": + version "2.3.13" + resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.13.tgz#b7e4766e0b65aa82e529be945ab078de79874edc" + integrity sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ== + dependencies: + call-bind "^1.0.7" + "@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" @@ -5668,6 +5683,11 @@ ajv@^8.0.0, ajv@^8.11.0, ajv@^8.12.0, ajv@^8.6.0, ajv@^8.9.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +ansi-escape@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ansi-escape/-/ansi-escape-1.1.0.tgz#8ad859e84a69e0ff91779694793a92e4e8c05e99" + integrity sha512-zSh7blKiz2ZUqDuEz4a3L59OheDkTuhG2Q1D875rpAJ4lt7AxMhyEXN20+6lpHXq4ul3rMcDzC2Hv6g33m58oQ== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -5997,6 +6017,17 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== +array.prototype.every@^1.1.6: + version "1.1.7" + resolved "https://registry.yarnpkg.com/array.prototype.every/-/array.prototype.every-1.1.7.tgz#e019a90842b00569efce73263ff90de35096c907" + integrity sha512-BIP72rKvrKd08ptbetLb4qvrlGjkv30yOKgKcTtOIbHyQt3shr/jyOzdApiCOh3LPYrpJo5M6i0zmVldOF2pUw== + dependencies: + call-bound "^1.0.2" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + is-string "^1.1.0" + array.prototype.findlast@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" @@ -6079,6 +6110,19 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -7059,6 +7103,11 @@ buffer-loader@^0.1.0: resolved "https://registry.yarnpkg.com/buffer-loader/-/buffer-loader-0.1.0.tgz#a6db0c1fc3af429640bc7cca20efad3e27431e09" integrity sha512-ucbiQL7IicJm1EHuXC4Oheu2oGjz6qKRmyqAXYTtWe4iC49743AU2DHlWpF51qKF+g/t62Jk8Yn+3FaCz5jJEA== +buffer-shims@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + integrity sha512-Zy8ZXMyxIT6RMTeY7OP/bDndfj6bwCan7SS98CEndS6deHwWPpseeHlwarNcBim+etXnF9HBc1non5JgDaJU1g== + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -7224,6 +7273,14 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" + integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -7235,6 +7292,24 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bin get-intrinsic "^1.2.4" set-function-length "^1.2.1" +call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" + call-me-maybe@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa" @@ -7875,7 +7950,7 @@ commander@^11.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== -commander@^2.20.0, commander@^2.20.3: +commander@^2.20.0, commander@^2.20.3, commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -8779,7 +8854,7 @@ deep-equal@^1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.5.1" -deep-equal@^2.0.5, deep-equal@^2.2.2: +deep-equal@^2.0.5, deep-equal@^2.2.2, deep-equal@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== @@ -8894,6 +8969,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +defined@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" + integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== + defu@^6.1.2, defu@^6.1.4: version "6.1.4" resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" @@ -9312,6 +9392,22 @@ dotenv@^9.0.2: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05" integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg== +dotignore@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +dunder-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.0.tgz#c2fce098b3c8f8899554905f4377b6d85dabaa80" + integrity sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-errors "^1.3.0" + gopd "^1.2.0" + duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -9730,6 +9826,60 @@ es-abstract@^1.17.2, es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22 unbox-primitive "^1.0.2" which-typed-array "^1.1.15" +es-abstract@^1.23.5: + version "1.23.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.6.tgz#55f0e1ce7128995cc04ace0a57d7dca348345108" + integrity sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.7" + get-intrinsic "^1.2.6" + get-symbol-description "^1.0.2" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.2" + is-negative-zero "^2.0.3" + is-regex "^1.2.1" + is-shared-array-buffer "^1.0.3" + is-string "^1.1.1" + is-typed-array "^1.1.13" + is-weakref "^1.1.0" + math-intrinsics "^1.0.0" + object-inspect "^1.13.3" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-regex-test "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.3" + typed-array-length "^1.0.7" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.16" + es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -9742,6 +9892,11 @@ es-define-property@^1.0.0: dependencies: get-intrinsic "^1.2.4" +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + es-errors@^1.2.1, es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" @@ -9819,6 +9974,15 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + es6-error@^4.0.1, es6-error@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" @@ -10679,6 +10843,13 @@ fecha@^4.2.0: resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== + dependencies: + escape-string-regexp "^1.0.5" + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -11129,6 +11300,17 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" +function.prototype.name@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.7.tgz#9df48ea5f746bf577d7e15b5da89df8952a98e7b" + integrity sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" + functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" @@ -11184,6 +11366,22 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" + integrity sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA== + dependencies: + call-bind-apply-helpers "^1.0.1" + dunder-proto "^1.0.0" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + function-bind "^1.1.2" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.0.0" + get-nonce@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" @@ -11517,7 +11715,7 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globalthis@^1.0.1, globalthis@^1.0.3: +globalthis@^1.0.1, globalthis@^1.0.3, globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -11567,6 +11765,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -11698,6 +11901,15 @@ has-bigints@^1.0.1, has-bigints@^1.0.2: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== +has-dynamic-import@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/has-dynamic-import/-/has-dynamic-import-2.1.1.tgz#c81e5ad210483b76b4fbe3393c96c2269c0b06b8" + integrity sha512-DuTCn6K/RW8S27npDMumGKsjG6HE7MxzedZka5tJP+9dqfxks+UMqKBmeCijHtIhsBEZPlbMg0qMHi2nKYVtKQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -11720,11 +11932,23 @@ has-proto@^1.0.1, has-proto@^1.0.3: resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" @@ -12372,6 +12596,15 @@ internal-slot@^1.0.4, internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -12530,6 +12763,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -12545,6 +12785,14 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-boolean-object@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89" + integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -12616,6 +12864,15 @@ is-data-view@^1.0.1: dependencies: is-typed-array "^1.1.13" +is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -12623,6 +12880,14 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + is-decimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" @@ -12705,6 +12970,13 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" +is-finalizationregistry@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz#d74a7d0c5f3578e34a20729e69202e578d495dc2" + integrity sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA== + dependencies: + call-bind "^1.0.7" + is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -12822,6 +13094,14 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -12911,6 +13191,16 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -12955,6 +13245,14 @@ is-string@^1.0.5, is-string@^1.0.7: dependencies: has-tostringtag "^1.0.0" +is-string@^1.1.0, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" @@ -12962,6 +13260,15 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" @@ -13001,6 +13308,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-weakref@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.0.tgz#47e3472ae95a63fa9cf25660bcf0c181c39770ef" + integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q== + dependencies: + call-bound "^1.0.2" + is-weakset@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" @@ -14649,10 +14963,10 @@ just-diff@^5.0.1: resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-5.2.0.tgz#60dca55891cf24cd4a094e33504660692348a241" integrity sha512-6ufhP9SHjb7jibNFrNxyFZ6od3g+An6Ai9mhGRvcYe8UJlH0prseN64M+6ZBBUoKYHZsitDP42gAJ8+eVWr3lw== -jxl-pdf@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/jxl-pdf/-/jxl-pdf-0.8.0.tgz#a85409d6028c06f0b0657c39f8c6ec3875e83f07" - integrity sha512-L8DtNv9N+Y3lS6vk0EUbKq+iayvxGBgS0BVuSi7JIHpMRUKBU3aKC25OpRG/kMORiUrZmjreJlDGXtHFmA4cRQ== +jxl-pdf@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/jxl-pdf/-/jxl-pdf-0.9.0.tgz#1548e90f18c3f0a4b1e6653f501aac45cd5fbaac" + integrity sha512-eBpxqQKdrMhEqD9KjA2NMRV4KMtfJXyVQx3/iwKfftHeweRKVbSEBa4Slv7GDHZ3KVxRe0zZ12GNnAA9W3Di4w== dependencies: commander "^11.1.0" fontkit "^2.0.2" @@ -15464,6 +15778,11 @@ matcher@^3.0.0: dependencies: escape-string-regexp "^4.0.0" +math-intrinsics@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.0.0.tgz#4e04bf87c85aa51e90d078dac2252b4eb5260817" + integrity sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA== + math-random@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" @@ -16085,7 +16404,7 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -16228,6 +16547,19 @@ mlly@^1.6.1, mlly@^1.7.1: pkg-types "^1.1.1" ufo "^1.5.3" +mock-property@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mock-property/-/mock-property-1.1.0.tgz#b38b9961476d2e54cde2033b62847b9546b3670d" + integrity sha512-1/JjbLoGwv87xVsutkX0XJc0M0W4kb40cZl/K41xtTViBOD9JuFPKfyMNTrLJ/ivYAd0aPqu/vduamXO0emTFQ== + dependencies: + define-data-property "^1.1.4" + functions-have-names "^1.2.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + hasown "^2.0.2" + isarray "^2.0.5" + object-inspect "^1.13.2" + module@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/module/-/module-1.2.5.tgz#b503eb06cdc13473f56818426974cde7ec59bf15" @@ -17003,7 +17335,12 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== -object-is@^1.1.5: +object-inspect@^1.13.2, object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + +object-is@^1.1.5, object-is@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== @@ -17553,6 +17890,11 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-ms@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" + integrity sha512-LpH1Cf5EYuVjkBvCDBYvkUPh+iv2bk3FHflxHkpCYT0/FZ1d3N3uJaLiHr4yGuMcFUhv6eAivitTvWZI4B/chg== + parse-svg-path@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb" @@ -17783,6 +18125,18 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== +perf-checks@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/perf-checks/-/perf-checks-0.1.0.tgz#6a8e1a268f36e23106396c29b50dcd45ace5278b" + integrity sha512-gB+krJ+Fqb2AjYEzR2vY/Hb1ZzOEmZK7gMgnLmq3LWaYk+IfIyVauV/nsMIWRXsGOK/Y0w8FV/S2lC46z0lkqw== + dependencies: + deep-copy-all "^1.3.4" + fs-extra "^11.2.0" + path "^0.12.7" + proskomma-json-tools "^0.8.10" + tap-summary "^4.0.0" + tape "^5.7.3" + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -18610,6 +18964,13 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-ms@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-3.2.0.tgz#87a8feaf27fc18414d75441467d411d6e6098a25" + integrity sha512-ZypexbfVUGTFxb0v+m1bUyy92DHe5SyYlnyY0msyms5zd3RwyvNgyxZZsXXgoyzlxjx5MiqtXUdhUfvQbe0A2Q== + dependencies: + parse-ms "^1.0.0" + prismjs@^1.27.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" @@ -18787,7 +19148,7 @@ proskomma-json-tools@^0.7.1: cheerio "^1.0.0-rc.12" deep-equal "^2.2.2" -proskomma-json-tools@^0.8.16, proskomma-json-tools@^0.8.20: +proskomma-json-tools@^0.8.10, proskomma-json-tools@^0.8.16, proskomma-json-tools@^0.8.20: version "0.8.21" resolved "https://registry.yarnpkg.com/proskomma-json-tools/-/proskomma-json-tools-0.8.21.tgz#e385e00feb1bd339dc9d4ad6fa7ddf62ab04b750" integrity sha512-iQXTr7rE1+dmdNuGrVlp/phBkhWBv6Y1hSzpdEEum8QSj5H7JQp8E1NhLQWyd2pUfENZGx9AhaqkHfpHmd36oQ== @@ -19148,6 +19509,11 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +re-emitter@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/re-emitter/-/re-emitter-1.1.3.tgz#fa9e319ffdeeeb35b27296ef0f3d374dac2f52a7" + integrity sha512-bHJul9CWcocrS+w5e5QrKYXV9NkbSA9hxSEyhYuctwm6keY9NXR2Xt/4A0vbMP0QvuwyfEyb4bkowYXv1ziEbg== + react-app-polyfill@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7" @@ -19673,6 +20039,19 @@ read@1, read@^1.0.7, read@~1.0.7: dependencies: mute-stream "~0.0.4" +readable-stream@2.2.9: + version "2.2.9" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" + integrity sha512-iuxqX7b7FYt08AriYECxUsK9KTXE3A/FenxIa3IPmvANHxaTP/wGIwwf+IidvvIDk/MsCp/oEV6A8CXo4SDcCg== + dependencies: + buffer-shims "~1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~1.0.0" + util-deprecate "~1.0.1" + readable-stream@3, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0, readable-stream@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" @@ -19854,6 +20233,20 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +reflect.getprototypeof@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz#c58afb17a4007b4d1118c07b92c23fca422c5d82" + integrity sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + dunder-proto "^1.0.0" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + gopd "^1.2.0" + which-builtin-type "^1.2.0" + regenerate-unicode-properties@^10.1.0: version "10.1.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" @@ -19923,6 +20316,16 @@ regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" +regexp.prototype.flags@^1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.2" + regexpu-core@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" @@ -20319,6 +20722,17 @@ safe-array-concat@^1.0.0, safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" + isarray "^2.0.5" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -20338,6 +20752,15 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -20622,7 +21045,7 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-function-length@^1.2.1: +set-function-length@^1.2.1, set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -20751,6 +21174,35 @@ showdown@^1.9.1: dependencies: yargs "^14.2" +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -20761,6 +21213,17 @@ side-channel@^1.0.4, side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -21122,6 +21585,13 @@ split2@^4.1.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +split@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" + integrity sha512-3SVfJe2A0WZg3D+ZEtXqYkvpSGAVaZ1MgufNCeHioBESCqQFsuT1VcQufiopBfJZqh92ZwQ6ddL378iUSbqVNQ== + dependencies: + through "2" + 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" @@ -21400,6 +21870,19 @@ string.prototype.repeat@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" @@ -21419,6 +21902,16 @@ string.prototype.trimend@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string.prototype.trimstart@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" @@ -21440,6 +21933,13 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== +string_decoder@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== + dependencies: + safe-buffer "~5.1.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -21775,6 +22275,27 @@ tailwindcss@^3.0.2, tailwindcss@^3.2.4: resolve "^1.22.2" sucrase "^3.32.0" +tap-out@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tap-out/-/tap-out-2.1.0.tgz#c093079a915036de8b835bfa3297f14458b15358" + integrity sha512-LJE+TBoVbOWhwdz4+FQk40nmbIuxJLqaGvj3WauQw3NYYU5TdjoV3C0x/yq37YAvVyi+oeBXmWnxWSjJ7IEyUw== + dependencies: + re-emitter "1.1.3" + readable-stream "2.2.9" + split "1.0.0" + trim "0.0.1" + +tap-summary@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tap-summary/-/tap-summary-4.0.0.tgz#93214862ba467c50a09f378ea0e5edc5dd04433d" + integrity sha512-xF6VzYZaunoIifiwM3NxsQ50c2zOcGo+c2A16pLvMGVsyp5yhVob57UmViqYYJ9DMfIXgd11EqDFO+r2pzZYLQ== + dependencies: + ansi-escape "^1.0.1" + commander "^2.9.0" + figures "^2.0.0" + pretty-ms "^3.0.0" + tap-out "^2.0.0" + tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" @@ -21785,6 +22306,34 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tape@^5.7.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/tape/-/tape-5.9.0.tgz#8d1a7472c6a154b82ce23b20dd9dc70ec0729b46" + integrity sha512-czbGgxSVwRlbB3Ly/aqQrNwrDAzKHDW/kVXegp4hSFmR2c8qqm3hCgZbUy1+3QAQFGhPDG7J56UsV1uNilBFCA== + dependencies: + "@ljharb/resumer" "^0.1.3" + "@ljharb/through" "^2.3.13" + array.prototype.every "^1.1.6" + call-bind "^1.0.7" + deep-equal "^2.2.3" + defined "^1.0.1" + dotignore "^0.1.2" + for-each "^0.3.3" + get-package-type "^0.1.0" + glob "^7.2.3" + has-dynamic-import "^2.1.0" + hasown "^2.0.2" + inherits "^2.0.4" + is-regex "^1.1.4" + minimist "^1.2.8" + mock-property "^1.1.0" + object-inspect "^1.13.2" + object-is "^1.1.6" + object-keys "^1.1.1" + object.assign "^4.1.5" + resolve "^2.0.0-next.5" + string.prototype.trim "^1.2.9" + tar-fs@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" @@ -22029,7 +22578,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -through@^2.3.8: +through@2, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -22472,6 +23021,19 @@ typed-array-byte-offset@^1.0.2: has-proto "^1.0.3" is-typed-array "^1.1.13" +typed-array-byte-offset@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz#3fa9f22567700cc86aaf86a1e7176f74b59600f2" + integrity sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + reflect.getprototypeof "^1.0.6" + typed-array-length@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" @@ -22484,6 +23046,18 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + typed-emitter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/typed-emitter/-/typed-emitter-2.1.0.tgz#ca78e3d8ef1476f228f548d62e04e3d4d3fd77fb" @@ -23599,6 +24173,17 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-boxed-primitive@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + which-builtin-type@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" @@ -23617,6 +24202,25 @@ which-builtin-type@^1.1.3: which-collection "^1.0.2" which-typed-array "^1.1.15" +which-builtin-type@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + which-collection@^1.0.1, which-collection@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" @@ -23643,6 +24247,17 @@ which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, gopd "^1.0.1" has-tostringtag "^1.0.2" +which-typed-array@^1.1.16: + version "1.1.16" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.16.tgz#db4db429c4706feca2f01677a144278e4a8c216b" + integrity sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" From c17e8c6d3adf36dc7b331bf81edc2e8b1c5596da Mon Sep 17 00:00:00 2001 From: danielc-n Date: Thu, 19 Dec 2024 17:34:59 +0100 Subject: [PATCH 02/16] bible-check works within scribe env --- package.json | 3 +- .../EditorPage/TextEditor/ChecksContent.jsx | 57 ++++++++++--------- renderer/src/layouts/editor/EditorSection.js | 45 ++++++++++----- yarn.lock | 5 ++ 4 files changed, 68 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index c5ab24c72..1c0d38f17 100644 --- a/package.json +++ b/package.json @@ -163,6 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", + "bible-checker": "^0.0.1", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", @@ -254,4 +255,4 @@ "word-aligner": "$word-aligner", "@mui/lab": "$@mui/lab" } -} \ No newline at end of file +} diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index 021d30e38..99def0e95 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -5,7 +5,6 @@ import { SnackBar } from '@/components/SnackBar'; import { Disclosure } from '@headlessui/react'; import { ChevronUpIcon, ArrowPathIcon } from '@heroicons/react/20/solid'; import LoadingScreen from '@/components/Loading/LoadingScreen'; -// import { useReadUsfmFile } from './hooks/useReadUsfmFile'; export default function ChecksContent({ content, updateContent }) { const [openSnackBar, setOpenSnackBar] = useState(false); @@ -14,22 +13,19 @@ export default function ChecksContent({ content, updateContent }) { const [error, setError] = useState(''); const [isRefreshing, setIsRefreshing] = useState(false); - - const isArray = Array.isArray(content); - useEffect(() => { - if (isArray) { - let tmpGroupedData = {}; - let currentName = ""; - for (let check of content) { - currentName = check.name; - if (!tmpGroupedData[currentName]) { - tmpGroupedData[currentName] = []; + console.log("yoooooooooooooo bro content ==", content); + if (Array.isArray(content)) { + // Group the checks by their names + const grouped = content.reduce((acc, check) => { + if (!acc[check.name]) { + acc[check.name] = []; } - delete check.name; - tmpGroupedData[currentName].push(check); - } - setGroupedData(tmpGroupedData); + acc[check.name].push(check); + return acc; + }, {}); + console.log('grouped ==', grouped), + setGroupedData(grouped); } }, [content]); @@ -48,33 +44,42 @@ export default function ChecksContent({ content, updateContent }) {

Checks

- {(isRefreshing && (groupedData && Object.keys(groupedData).length < 1)) && } + {(isRefreshing && (!groupedData || Object.keys(groupedData).length < 1)) && } {!isRefreshing && groupedData && Object.keys(groupedData).length > 0 ? ( - Object.keys(groupedData).map((key) => ( - + Object.keys(groupedData).map((checkName) => ( + {({ open }) => ( <> - {key} + {checkName}
    - {groupedData[key].map((item, index) => ( -
  • - {item.args.cv} -
  • ) - )} + {groupedData[checkName].map((check, checkIndex) => ( +
  • +

    {check.description}

    +
      + {check.issues.map((issue, issueIndex) => ( +
    • + Type: {issue.type}
      + Chapter: {issue.chapter}
      + Verse: {issue.verse}
      + Message: {issue.message} +
    • + ))} +
    +
  • + ))}
diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index 5958a1184..b41e065d0 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -22,8 +22,10 @@ import * as logger from '../../logger'; import packageInfo from '../../../../package.json'; import localforage from 'localforage'; import checker from 'perf-checks'; +import { getAvailableChecks, checks } from 'bible-checker'; import { Proskomma } from 'proskomma-core'; import CheckSelector from './CheckSelector'; +import { convertUsfmToUsj } from '@/components/EditorPage/TextEditor/conversionUtils.js'; // import ScriptureContentPicker from '@/components/ScriptureContentPicker/ScriptureContentPicker.tsx'; export default function EditorSection({ @@ -208,7 +210,7 @@ export default function EditorSection({ } }; - const checks = async () => { + const doChecks = async () => { const fse = window.require('fs-extra'); const path = window.require('path'); @@ -248,18 +250,31 @@ export default function EditorSection({ }; // setUsfmData(books); const usfmContent = book.data; - const pk = new Proskomma(); - const selectors = { - lang: 'xxx', - abbr: 'yyy', - } - pk.importDocuments(selectors, 'usfm', [usfmContent]); - const perfResultDocument = pk.gqlQuerySync('{documents {perf} }').data.documents[0]; - const perf = JSON.parse(perfResultDocument.perf); - if (perf && spec.checks && spec.checks.length > 0) { - let ret = checker({ content: { perf }, spec, contentType: "perf" }); - setContentChecks(ret); + // const pk = new Proskomma(); + // const selectors = { + // lang: 'xxx', + // abbr: 'yyy', + // } + // pk.importDocuments(selectors, 'usfm', [usfmContent]); + // const perfResultDocument = pk.gqlQuerySync('{documents {perf} }').data.documents[0]; + // const perf = JSON.parse(perfResultDocument.perf); + // if (perf && spec.checks && spec.checks.length > 0) { + // let ret = checker({ content: { perf }, spec, contentType: "perf" }); + // setContentChecks(ret); + // } + // recipe[0].enabled = true; // Enable short/long verses check + const recipe = getAvailableChecks(); + recipe[1].enabled = true; // Enable chapter/verse integrity check + console.log("recipe ==",recipe); + const { usj, error } = await convertUsfmToUsj(usfmContent); + if (error) { + console.error('Error parsing USFM:', error); + return { error, usj: null }; // Return consistent error object } + const usjStr = JSON.stringify(usj); + const response = await checks(usjStr, usjStr, recipe); + setContentChecks(response.checks); + console.log("response ==",response.checks); } } @@ -405,7 +420,7 @@ export default function EditorSection({ referenceResources.selectedResource = 'checks'; setLoadResource(true); setReferenceResources(referenceResources); - checks(); + doChecks(); }} > @@ -464,7 +479,7 @@ export default function EditorSection({ referenceResources.selectedResource = 'checks'; setLoadResource(true); setReferenceResources(referenceResources); - checks(); + doChecks(); }} > )} diff --git a/yarn.lock b/yarn.lock index 51fd1ec75..e08f53165 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,6 +6745,11 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" +bible-checker@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.0.1.tgz#84c741588318546a96b80540988fa39c2b0f5847" + integrity sha512-kRfYzwcsczwvKGT6G5ZkROSxvWlk+HwCFiedQFe4ak3W80YTchWwb6TF1dkYOqog7MsbRtjzJw5IMZyXaeqyqw== + bible-reference-range@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/bible-reference-range/-/bible-reference-range-1.1.1.tgz#9438bb870f853439fa92afe61a04fab53922ab91" From 8b2bd105fd83f0c6fff7f83ba509341fbfc36e9d Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 23 Dec 2024 20:40:37 +0100 Subject: [PATCH 03/16] updated bible-checker and enhanced front end for the checks --- package.json | 2 +- .../EditorPage/TextEditor/ChecksContent.jsx | 62 ++++-- .../EditorPage/TextEditor/LexicalEditor.jsx | 1 + .../EditorPage/TextEditor/index.jsx | 2 +- renderer/src/layouts/editor/CheckSelector.js | 209 ++++++++++-------- renderer/src/layouts/editor/EditorSection.js | 68 +++--- yarn.lock | 8 +- 7 files changed, 197 insertions(+), 155 deletions(-) diff --git a/package.json b/package.json index 1c0d38f17..6a0e7acf9 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "^0.0.1", + "bible-checker": "^0.0.3", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index 99def0e95..3541d2a6a 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -3,10 +3,10 @@ import React, { useEffect, useState } from 'react'; import { XMarkIcon } from '@heroicons/react/24/solid'; import { SnackBar } from '@/components/SnackBar'; import { Disclosure } from '@headlessui/react'; -import { ChevronUpIcon, ArrowPathIcon } from '@heroicons/react/20/solid'; +import { ChevronUpIcon, ArrowPathIcon, ExclamationCircleIcon } from '@heroicons/react/20/solid'; import LoadingScreen from '@/components/Loading/LoadingScreen'; -export default function ChecksContent({ content, updateContent }) { +export default function ChecksContent({ content, updateContent, onReferenceClick }) { const [openSnackBar, setOpenSnackBar] = useState(false); const [snackText, setSnackText] = useState(''); const [groupedData, setGroupedData] = useState({}); @@ -14,18 +14,16 @@ export default function ChecksContent({ content, updateContent }) { const [isRefreshing, setIsRefreshing] = useState(false); useEffect(() => { - console.log("yoooooooooooooo bro content ==", content); if (Array.isArray(content)) { // Group the checks by their names const grouped = content.reduce((acc, check) => { - if (!acc[check.name]) { - acc[check.name] = []; + if (!acc[check.readName]) { + acc[check.readName] = []; } - acc[check.name].push(check); + acc[check.readName].push(check); return acc; }, {}); - console.log('grouped ==', grouped), - setGroupedData(grouped); + setGroupedData(grouped); } }, [content]); @@ -41,7 +39,7 @@ export default function ChecksContent({ content, updateContent }) { return (
-
+

Checks

+
+
))} - - + +
+
))} - +
)} diff --git a/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx b/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx index 68597dd9c..a87f64d33 100644 --- a/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx +++ b/renderer/src/components/EditorPage/TextEditor/LexicalEditor.jsx @@ -34,6 +34,7 @@ export default function LexicalEditor({ useEffect(() => { if (usjInput) { setUsj(usjInput); + localStorage.setItem('usj', JSON.stringify(usjInput)); } }, [usjInput]); useEffect(() => { diff --git a/renderer/src/components/EditorPage/TextEditor/index.jsx b/renderer/src/components/EditorPage/TextEditor/index.jsx index dd1a680a3..4e12815b9 100644 --- a/renderer/src/components/EditorPage/TextEditor/index.jsx +++ b/renderer/src/components/EditorPage/TextEditor/index.jsx @@ -105,7 +105,7 @@ export default function TextEditor() { const handleUsjChange = useMemo( () => debounce(async (updatedUsj) => { updateCacheNSaveFile(updatedUsj, book); - // console.log('usj updated', updatedUsj); + localStorage.setItem('usj', JSON.stringify(updatedUsj)); }, 1000), [book], ); diff --git a/renderer/src/layouts/editor/CheckSelector.js b/renderer/src/layouts/editor/CheckSelector.js index 6e1ee6206..8de7af04d 100644 --- a/renderer/src/layouts/editor/CheckSelector.js +++ b/renderer/src/layouts/editor/CheckSelector.js @@ -1,122 +1,149 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import packageInfo from '../../../../package.json'; import AdjustmentsVerticalIcon from '@/icons/Common/AdjustmentsVertical.svg'; -import md5 from 'md5'; -// import * as fs from 'node:fs/promises'; -// import path from "path"; - -const checksData = [ - { - name: "versestats::verse_stats", - description: "Checks for empty, short and long verses", - level: "minor", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::duplicate_chapters", - description: "Checks for duplicate chapter numbers", - level: "major", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::duplicate_verses", - description: "Checks for duplicate verse numbers", - level: "major", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::missing_chapters", - description: "Checks for missing chapter numbers", - level: "minor", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::missing_verses", - description: "Checks for missing verse numbers within chapters", - level: "major", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::out_of_order_chapters", - description: "Checks for out-of-order chapter numbers within chapters", - level: "major", - contentType: "perf", - children: [], - }, - { - name: "chapterverse::out_of_order_verses", - description: "Checks for out-of-order verse numbers within chapters", - level: "major", - contentType: "perf", - children: [], - }, -]; - -const CheckSelector = ({ showResourcesPanel, setChoosingSourceLang }) => { - const [selectedChecks, setSelectedChecks] = useState([]); - - const writeJSONToFile = (updatedChecks) => { +import { Menu, Transition } from '@headlessui/react'; +import { ChevronDownIcon } from '@heroicons/react/20/solid'; +import { Fragment } from 'react'; +import { readRefBurrito } from '@/core/reference/readRefBurrito'; +import localForage from 'localforage'; +import * as logger from '../../logger'; +import { convertUsfmToUsj } from '@/components/EditorPage/TextEditor/conversionUtils.js'; + +const CheckSelector = ({ + showResourcesPanel, + recipe, + setRecipe, + bookId, + referenceResources, + setReferenceSourceData +}) => { + useEffect(() => { + let dataSrcBook = null; + + localForage.getItem('userProfile').then(async (user) => { + logger.debug('CheckSelector.js', 'reading offline helps ', referenceResources); + + const fs = window.require('fs'); + const path = require('path'); + const newpath = localStorage.getItem('userPath'); + const currentUser = user?.username; + const folder = path.join(newpath, packageInfo.name, 'users', `${currentUser}`, 'resources'); + const projectName = `${referenceResources.refName}`; + const normalizedPath = path.join(folder, projectName); + const metaPath = path.join(normalizedPath, '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()); + + const pathCurrentBook = path.join(normalizedPath, currentBook.fileName); + + if (pathCurrentBook && fs.existsSync(pathCurrentBook)) { + dataSrcBook = fs.readFileSync(pathCurrentBook, "utf8"); + } + + let trg_usfm_bookId = localStorage.getItem('trg_usfm_bookId'); + if (!trg_usfm_bookId || (dataSrcBook && trg_usfm_bookId.toUpperCase() !== currentBook.bookId)) { + let usfmToUsj = await convertUsfmToUsj(dataSrcBook); + let strUsj = JSON.stringify(usfmToUsj.usj); + localStorage.setItem('trg_usfm', strUsj); + localStorage.setItem('trg_usfm_bookId', strUsj); + setReferenceSourceData(strUsj); + } + }).catch((e) => console.log("Error while loading source file", e)); + }, [bookId]); + + const writeJSONToFile = (updatedRecipe) => { const fs = window.require('fs'); const path = require('path'); const generatedJSON = { name: "Scribe checks", description: "", - checks: checksData.filter((check) => updatedChecks.includes(check.name)), + checks: updatedRecipe, }; const newpath = localStorage.getItem('userPath'); - console.log("newpath ==", newpath); const projectsPath = path.join(newpath, packageInfo.name, 'config_checks.json'); - const filePath = projectsPath; try { - fs.writeFileSync(filePath, JSON.stringify(generatedJSON, null, 2), "utf8"); + fs.writeFileSync(projectsPath, JSON.stringify(generatedJSON, null, 2), "utf8"); } catch (error) { console.error("Error writing file:", error); } }; + // TODO : modify this const handleCheckToggle = (checkName) => { - setSelectedChecks((prev) => { - const updatedChecks = prev.includes(checkName) - ? prev.filter((name) => name !== checkName) - : [...prev, checkName]; - writeJSONToFile(updatedChecks); - return updatedChecks; + const updatedRecipe = recipe.map((check) => { + if (check.parameters) { + check.parameters.short_threshold = 30; + } + if (check.name === checkName) { + return { ...check, enabled: !check.enabled }; + } + return check; }); + + setRecipe(updatedRecipe); + writeJSONToFile(updatedRecipe); }; return ( -
-

Checks Selector

+
+ {/* Source Resources Button */} -
- {checksData.map((check) => ( - - ))} -
+ + {/* Dropdown for Checks */} + + + Checks + + + + +
+

Available Checks

+ {recipe.map((check) => ( + + ))} +
+
+
+
); }; diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index b41e065d0..aa0a94719 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -21,11 +21,11 @@ import ConfirmationModal from './ConfirmationModal'; import * as logger from '../../logger'; import packageInfo from '../../../../package.json'; import localforage from 'localforage'; -import checker from 'perf-checks'; +// import checker from 'perf-checks'; import { getAvailableChecks, checks } from 'bible-checker'; -import { Proskomma } from 'proskomma-core'; +// import { Proskomma } from 'proskomma-core'; import CheckSelector from './CheckSelector'; -import { convertUsfmToUsj } from '@/components/EditorPage/TextEditor/conversionUtils.js'; +// import { convertUsfmToUsj } from '@/components/EditorPage/TextEditor/conversionUtils.js'; // import ScriptureContentPicker from '@/components/ScriptureContentPicker/ScriptureContentPicker.tsx'; export default function EditorSection({ @@ -61,6 +61,8 @@ export default function EditorSection({ const [contentChecks, setContentChecks] = useState({}); const [choosingSourceLang, setChoosingSourceLang] = useState(false); const [referenceSourceLang, setReferenceSourceLang] = useState({}); + const [referenceSourceData, setReferenceSourceData] = useState(null); + const [recipe, setRecipe] = useState(getAvailableChecks()); const { t } = useTranslation(); const { state: { @@ -210,6 +212,8 @@ export default function EditorSection({ } }; + const onReferenceClick = () => {} + const doChecks = async () => { const fse = window.require('fs-extra'); const path = window.require('path'); @@ -242,39 +246,27 @@ export default function EditorSection({ const [currentBook] = _books.filter((bookObj) => bookObj.bookId === bookId?.toUpperCase()); // const projectCachePath = path.join(newpath, packageInfo.name, 'users', userName, 'project_cache', projectName); if (currentBook) { - const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); - const book = { - selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, - bookCode: currentBook.bookId?.toLowerCase(), - data: fileData, - }; - // setUsfmData(books); - const usfmContent = book.data; - // const pk = new Proskomma(); - // const selectors = { - // lang: 'xxx', - // abbr: 'yyy', - // } - // pk.importDocuments(selectors, 'usfm', [usfmContent]); - // const perfResultDocument = pk.gqlQuerySync('{documents {perf} }').data.documents[0]; - // const perf = JSON.parse(perfResultDocument.perf); - // if (perf && spec.checks && spec.checks.length > 0) { - // let ret = checker({ content: { perf }, spec, contentType: "perf" }); - // setContentChecks(ret); - // } - // recipe[0].enabled = true; // Enable short/long verses check - const recipe = getAvailableChecks(); - recipe[1].enabled = true; // Enable chapter/verse integrity check - console.log("recipe ==",recipe); - const { usj, error } = await convertUsfmToUsj(usfmContent); - if (error) { - console.error('Error parsing USFM:', error); - return { error, usj: null }; // Return consistent error object + // const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); + // const book = { + // selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, + // bookCode: currentBook.bookId?.toLowerCase(), + // data: fileData, + // }; + + let response = null; + const USJ = localStorage.getItem('usj'); + // console.log("SOURCE ==",JSON.parse(referenceSourceData)); + // console.log("TARGET ==",JSON.parse(USJ)); + + if(referenceSourceData) { + response = await checks(referenceSourceData, USJ, recipe); + } else { + response = await checks(USJ, USJ, recipe); + } + if(response) { + setContentChecks(response.checks); + console.log("response ==",response.checks); } - const usjStr = JSON.stringify(usj); - const response = await checks(usjStr, usjStr, recipe); - setContentChecks(response.checks); - console.log("response ==",response.checks); } } @@ -508,10 +500,16 @@ export default function EditorSection({ <> )} diff --git a/yarn.lock b/yarn.lock index e08f53165..d465d7b2f 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.0.1.tgz#84c741588318546a96b80540988fa39c2b0f5847" - integrity sha512-kRfYzwcsczwvKGT6G5ZkROSxvWlk+HwCFiedQFe4ak3W80YTchWwb6TF1dkYOqog7MsbRtjzJw5IMZyXaeqyqw== +bible-checker@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.0.3.tgz#f14859ae4919b5707e3025b10152b21e1fd625bd" + integrity sha512-xGIOg5Nn41+wjURzDb4yxo8z/VkVv1Wk3+TxWuQE741u1dejpDYNai1izkdXC9l1Zz6ZcoNcg2uBT9J3AlK5xA== bible-reference-range@^1.1.0: version "1.1.1" From de9147c2905088f53f55e9b65fd5873a537c75f5 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Fri, 27 Dec 2024 12:39:11 +0100 Subject: [PATCH 04/16] checks OK : verse_stats, integrity_check, repeated_words_whitespace, unmatched_punctuation and a way to automatically scroll to the correct chapter/verse reference with a highlight --- .../EditorPage/TextEditor/ChecksContent.jsx | 2 +- renderer/src/layouts/editor/CheckSelector.js | 23 +- renderer/src/layouts/editor/EditorSection.js | 314 ++++++++++++------ styles/globals.css | 17 + 4 files changed, 245 insertions(+), 111 deletions(-) diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index 3541d2a6a..f3654f89d 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -84,7 +84,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick
Reference:{' '}
{selectedProjectMeta?.type?.flavorType?.flavor?.name == 'textTranslation' && - (
-
- {"Open checks"} -
- -
)} + (
+
+ {"Open checks"} +
+ +
)}
) : referenceResources.selectedResource !== 'checks' ? (
@@ -504,6 +609,7 @@ export default function EditorSection({ setRecipe={setRecipe} referenceResources={referenceSourceLang} setReferenceSourceData={setReferenceSourceData} + openResourcePopUp={openResourcePopUp} bookId={bookId} /> Date: Fri, 27 Dec 2024 14:00:55 +0100 Subject: [PATCH 05/16] changed the way the verse are highlighted --- .../EditorPage/TextEditor/ChecksContent.jsx | 2 +- renderer/src/layouts/editor/EditorSection.js | 68 ++++++++++--------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index f3654f89d..e07e07503 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -84,7 +84,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick
Reference:{' '}
{ if (usj && editorRef.current) { editorRef.current.setUsj(usj); + localStorage.setItem('usj', JSON.stringify(usj)); } }, 1000); return () => clearTimeout(timeoutId); diff --git a/renderer/src/layouts/editor/CheckSelector.js b/renderer/src/layouts/editor/CheckSelector.js index 57b24c913..9662e80fc 100644 --- a/renderer/src/layouts/editor/CheckSelector.js +++ b/renderer/src/layouts/editor/CheckSelector.js @@ -1,4 +1,4 @@ -import React, { useContext, useEffect } from "react"; +import React, { useContext, useState, useEffect } from "react"; import packageInfo from '../../../../package.json'; import AdjustmentsVerticalIcon from '@/icons/Common/AdjustmentsVertical.svg'; import { Menu, Transition } from '@headlessui/react'; @@ -20,6 +20,8 @@ const CheckSelector = ({ openResourcePopUp }) => { + const [theProjectName, setTheProjectName] = useState(false); + useEffect(() => { console.log("Calling useEffect!") let dataSrcBook = null; @@ -33,6 +35,7 @@ const CheckSelector = ({ const currentUser = user?.username; const folder = path.join(newpath, packageInfo.name, 'users', `${currentUser}`, 'resources'); const projectName = `${referenceResources.refName}`; + setTheProjectName(projectName); const normalizedPath = path.join(folder, projectName); const metaPath = path.join(normalizedPath, 'metadata.json'); @@ -155,6 +158,7 @@ const CheckSelector = ({ + {theProjectName ? `Resource selected : ${theProjectName}` : 'no resource selected'}
); }; diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index 2995751fd..739b4ad67 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -240,18 +240,31 @@ export default function EditorSection({ let currentElement = chapterElement.nextElementSibling; let verseElement = null; + let lastVerseElement = null; + let lastChapterElement = null; + while (currentElement) { // If the element itself matches the verse, select it + if (currentElement.matches(`.chapter[data-number="${parseInt(chapter) + 1}"]`)) { + lastChapterElement = chapterElement; + break; + } if (currentElement.matches(`.verse[data-number="${verse}"]`)) { verseElement = currentElement; break; } - const nestedVerse = currentElement.querySelector(`.verse[data-number="${verse}"]`); + let nestedVerse = currentElement.querySelector(`.verse[data-number="${verse}"]`); if (nestedVerse) { verseElement = nestedVerse; break; + } else { + nestedVerse = currentElement.querySelector(`.verse[data-number="${verse - 1}"]`); + if (nestedVerse) { + lastVerseElement = nestedVerse; + break; + } } // Move to the next sibling @@ -260,6 +273,18 @@ export default function EditorSection({ if (!verseElement) { console.error(`Verse ${verse} in chapter ${chapter} not found.`); + if (!lastVerseElement && !lastChapterElement) { + return; + } else { + verseElement = lastVerseElement; + } + } + + if (lastChapterElement) { + console.warn(`Verse ${verse} in chapter ${chapter} not found. Scrolling to the chapter instead.`); + chapterElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); + chapterElement.classList.add('highlight-chapter'); + setTimeout(() => chapterElement.classList.remove('highlight-chapter'), 5000); return; } @@ -285,12 +310,12 @@ export default function EditorSection({ element.style.transition = 'background-color 0.3s ease'; }); - // Remove highlight after 2 seconds + // Remove highlight after 5 seconds setTimeout(() => { elementsToHighlight.forEach((element) => { element.style.backgroundColor = 'transparent'; }); - }, 2000); + }, 5000); } const onReferenceClick = (source_ref, source_chapter, source_verse, text = '') => { @@ -618,6 +643,7 @@ export default function EditorSection({ content={contentChecks} updateContent={doChecks} onReferenceClick={onReferenceClick} + recipe={recipe} /> )} diff --git a/styles/globals.css b/styles/globals.css index 63f2c5549..c17a65f0a 100755 --- a/styles/globals.css +++ b/styles/globals.css @@ -3621,4 +3621,10 @@ span.read img { font-weight: bold; border-radius: 3px; padding: 0 2px; +} + +.highlight-chapter { + background-color: lightblue; + border-radius: 4px; + transition: background-color 0.3s ease; } \ No newline at end of file From 012b21552dd93291bb58fc7d5676812261ef681f Mon Sep 17 00:00:00 2001 From: danielc-n Date: Sun, 29 Dec 2024 13:40:20 +0100 Subject: [PATCH 07/16] fix for https://github.com/bible-technology/scribe-scripture-editor/pull/389#issuecomment-2564158269 --- .../EditorPage/TextEditor/ChecksContent.jsx | 13 +++--- renderer/src/layouts/editor/CheckSelector.js | 24 +++++----- renderer/src/layouts/editor/EditorSection.js | 45 +++++++++++++------ 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index cb1597d64..90a567333 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -12,13 +12,9 @@ export default function ChecksContent({ content, updateContent, onReferenceClick const [groupedData, setGroupedData] = useState({}); const [error, setError] = useState(''); const [isRefreshing, setIsRefreshing] = useState(false); - const [areAnyCheckSelected, setAreAnyCheckSelected] = useState(false); + const [areAnyCheckSelected, setAreAnyCheckSelected] = useState(recipe.some(el => el.enabled)); useEffect(() => { - // console.log(recipe); - recipe.map((el) => { - if (el.enabled) setAreAnyCheckSelected(true); - }); if (Array.isArray(content)) { // Group the checks by their names const grouped = content.reduce((acc, check) => { @@ -34,6 +30,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick const handleRefreshClick = () => { setIsRefreshing(true); + setAreAnyCheckSelected(recipe.some(el => el.enabled)); updateContent(); // Add delay to simulate refreshing and stop the rotation animation after 1 second @@ -43,7 +40,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick }; return ( -
+

Checks

-
+
{(isRefreshing && (!groupedData || Object.keys(groupedData).length < 1)) && } {!isRefreshing && groupedData && Object.keys(groupedData).length > 0 ? ( Object.keys(groupedData).map((checkName) => ( @@ -108,7 +105,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick )) ) : !isRefreshing && ( -

{areAnyCheckSelected ? 'No results.' : 'Please check at least one check from the check dropdown.'}

+

{areAnyCheckSelected ? 'No results.' : 'Please select at least one check from the check dropdown.'}

)}
{ - const [theProjectName, setTheProjectName] = useState(false); + const [theProjectName, setTheProjectName] = useState(''); + const [firstSelection, setFirstSelection] = useState(true); useEffect(() => { - console.log("Calling useEffect!") let dataSrcBook = null; localForage.getItem('userProfile').then(async (user) => { @@ -65,15 +65,17 @@ const CheckSelector = ({ refName = projectName; } - if (projectName != refName || !trg_usfm_bookId || (dataSrcBook && trg_usfm_bookId.toUpperCase() !== currentBook.bookId)) { - let usfmToUsj = await convertUsfmToUsj(dataSrcBook); - let strUsj = JSON.stringify(usfmToUsj.usj); - localStorage.setItem('trg_usj', strUsj); - localStorage.setItem('trg_usfm_bookId', usfmToUsj.usj?.content[0]?.code); - localStorage.setItem('ref_name', projectName); - setReferenceSourceData(strUsj); + if (firstSelection || projectName != refName || !trg_usfm_bookId || (dataSrcBook && trg_usfm_bookId.toUpperCase() !== currentBook.bookId)) { + convertUsfmToUsj(dataSrcBook).then((usfmToUsj) => { + let strUsj = JSON.stringify(usfmToUsj.usj); + localStorage.setItem('trg_usj', strUsj); + localStorage.setItem('trg_usfm_bookId', usfmToUsj.usj?.content[0]?.code); + localStorage.setItem('ref_name', projectName); + setReferenceSourceData(strUsj); + }).catch((e) => console.error("Error while loading source file", e)); + setFirstSelection(false); } - }).catch((e) => console.log("Error while loading source file", e)); + }).catch((e) => console.error("Error while loading source file", e)); }, [bookId, openResourcePopUp, referenceResources.refName]); const writeJSONToFile = (updatedRecipe) => { @@ -158,7 +160,7 @@ const CheckSelector = ({ - {theProjectName ? `Resource selected : ${theProjectName}` : 'no resource selected'} + {theProjectName != '' && theProjectName != 'undefined' ? `Resource selected : ${theProjectName}` : 'No resource selected'}
); }; diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index 739b4ad67..39402f5c8 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -242,6 +242,7 @@ export default function EditorSection({ let verseElement = null; let lastVerseElement = null; let lastChapterElement = null; + let nestedVerse = null; while (currentElement) { @@ -255,16 +256,16 @@ export default function EditorSection({ break; } - let nestedVerse = currentElement.querySelector(`.verse[data-number="${verse}"]`); + nestedVerse = currentElement.querySelector(`.verse[data-number="${verse}"]`); if (nestedVerse) { verseElement = nestedVerse; break; - } else { - nestedVerse = currentElement.querySelector(`.verse[data-number="${verse - 1}"]`); - if (nestedVerse) { - lastVerseElement = nestedVerse; - break; - } + // } else { + // nestedVerse = currentElement.querySelector(`.verse[data-number="${verse - 1}"]`); + // if (nestedVerse) { + // lastVerseElement = nestedVerse; + // break; + // } } // Move to the next sibling @@ -290,13 +291,28 @@ export default function EditorSection({ // Collect all elements after the verse number until the next verse const elementsToHighlight = []; - let sibling = verseElement.nextElementSibling; - while (sibling) { - if (sibling.matches('.verse')) break; // Stop at the next verse marker - if (sibling.hasAttribute('data-lexical-text') && sibling.getAttribute('data-lexical-text') === 'true') { - elementsToHighlight.push(sibling); + // let sibling = verseElement.nextElementSibling; + let isNextVerse = false; + let isCorrectVerse = false; + while (!isNextVerse) { + let children = currentElement.childNodes; + for (const child of children) { + if (child.matches(`.verse[data-number="${verse}"]`)) { + isCorrectVerse = true; + continue; + } + + // Stop at the next verse marker + if (isCorrectVerse && (child.matches(`.verse`) || child.matches(`.chapter`))) { + isNextVerse = true; + break; + } + + if (isCorrectVerse && child.hasAttribute('data-lexical-text') && child.getAttribute('data-lexical-text') === 'true') { + elementsToHighlight.push(child); + } } - sibling = sibling.nextElementSibling; + currentElement = currentElement.nextElementSibling; } // Scroll the first element into view @@ -385,6 +401,7 @@ export default function EditorSection({ // data: fileData, // }; + let response = null; const USJ = localStorage.getItem('usj'); // console.log("SOURCE ==",JSON.parse(referenceSourceData)); @@ -397,7 +414,7 @@ export default function EditorSection({ } if (response) { setContentChecks(response.checks); - console.log("response ==", response.checks); + // console.log("response ==", response.checks); } } } From 07a82cc3136ef54931f4c2ac936f406d49a18f63 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 30 Dec 2024 14:21:25 +0100 Subject: [PATCH 08/16] some fixes for scrolling problem and highlight problems. See : https://github.com/bible-technology/scribe-scripture-editor/pull/389#issuecomment-2565477073 --- .../EditorPage/TextEditor/ChecksContent.jsx | 12 ++++++--- renderer/src/layouts/editor/EditorSection.js | 25 ++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index 90a567333..bb2f35054 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -40,7 +40,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick }; return ( -
+

Checks

-
+
{(isRefreshing && (!groupedData || Object.keys(groupedData).length < 1)) && } {!isRefreshing && groupedData && Object.keys(groupedData).length > 0 ? ( Object.keys(groupedData).map((checkName) => ( {({ open }) => ( <> - + {checkName} { + if (marker.endsWith('#')) { + return `.para[data-marker^="${marker.slice(0, -1)}"]`; + } + return `.para[data-marker="${marker}"]`; + }) + .join(', '); + const { state: { layout, @@ -244,8 +259,11 @@ export default function EditorSection({ let lastChapterElement = null; let nestedVerse = null; - while (currentElement) { + if (currentElement.matches(query)) { + currentElement = currentElement.nextElementSibling; + continue; + } // If the element itself matches the verse, select it if (currentElement.matches(`.chapter[data-number="${parseInt(chapter) + 1}"]`)) { lastChapterElement = chapterElement; @@ -295,6 +313,11 @@ export default function EditorSection({ let isNextVerse = false; let isCorrectVerse = false; while (!isNextVerse) { + if (currentElement.matches(query)) { + console.log("yup") + currentElement = currentElement.nextElementSibling; + continue; + } let children = currentElement.childNodes; for (const child of children) { if (child.matches(`.verse[data-number="${verse}"]`)) { From 659c49ed37f7c7ba2c8d6eae92f0396f572f8262 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 30 Dec 2024 14:25:01 +0100 Subject: [PATCH 09/16] minor fix for scrolling --- renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index bb2f35054..4750bfadd 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -50,7 +50,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick
-
+
{(isRefreshing && (!groupedData || Object.keys(groupedData).length < 1)) && } {!isRefreshing && groupedData && Object.keys(groupedData).length > 0 ? ( Object.keys(groupedData).map((checkName) => ( From 314fd57c39fc488878910fd265b9a19982952a4e Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 30 Dec 2024 14:25:34 +0100 Subject: [PATCH 10/16] removed a 'console log' --- renderer/src/layouts/editor/EditorSection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index 56c834f3f..e5ae30a22 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -314,7 +314,6 @@ export default function EditorSection({ let isCorrectVerse = false; while (!isNextVerse) { if (currentElement.matches(query)) { - console.log("yup") currentElement = currentElement.nextElementSibling; continue; } From 6890e62f511ad60a3cfe75800afd6d33410db810 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Mon, 30 Dec 2024 15:19:06 +0100 Subject: [PATCH 11/16] it's now highlighting the verse also in the reference if found --- renderer/src/layouts/editor/EditorSection.js | 107 +++++++++++++++++-- 1 file changed, 98 insertions(+), 9 deletions(-) diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index e5ae30a22..f9c06ccca 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -78,7 +78,7 @@ export default function EditorSection({ return `.para[data-marker="${marker}"]`; }) .join(', '); - + const { state: { layout, @@ -235,6 +235,84 @@ export default function EditorSection({ } }; + /** + * Highlights the text of a specific verse in the document and scrolls to it. + * Highlights only the content of the verse, not the verse number. + * Removes the highlight after 5 seconds. + * + * @param {number} chapter - The chapter number. + * @param {number} verse - The verse number. + */ + function highlightVerse(chapter, verse) { + // Construct the ID of the target verse element + const verseId = `ch${chapter}v${verse}`; + + // Find the verse number element by ID + const verseElement = document.getElementById(verseId); + + if (verseElement) { + // Find the parent paragraph containing the verse text + const paragraph = verseElement.closest('p'); + + if (paragraph) { + // Get all text nodes in the paragraph following the verse number + const range = document.createRange(); + const startNode = verseElement.nextSibling; + const endNode = findEndNode(paragraph, chapter, verse); + + // Define the range for highlighting + if (startNode && endNode) { + range.setStartAfter(verseElement); + range.setEndBefore(endNode); + + // Wrap the range in a highlight span + const highlightSpan = document.createElement('span'); + highlightSpan.className = 'highlight'; + range.surroundContents(highlightSpan); + + // Scroll the highlighted text into view + // highlightSpan.scrollIntoView({ + // behavior: 'smooth', + // block: 'center' + // }); + + // Remove the highlight after 5 seconds + setTimeout(() => { + highlightSpan.replaceWith(...highlightSpan.childNodes); + }, 5000); + + return paragraph; + } + } + } else { + console.warn(`Verse with ID "${verseId}" not found.`); + } + + return null; + } + + /** + * Finds the end node of the text for the current verse by searching for the next verse or chapter marker. + * + * @param {HTMLElement} paragraph - The paragraph containing the verse text. + * @param {number} chapter - The current chapter number. + * @param {number} verse - The current verse number. + * @returns {Node} The node where the current verse ends. + */ + function findEndNode(paragraph, chapter, verse) { + const children = Array.from(paragraph.children); + let foundCurrent = false; + + for (const child of children) { + if (child.id === `ch${chapter}v${verse}`) { + foundCurrent = true; + } else if (foundCurrent && (child.classList.contains('mark') || child.classList.contains('chapter'))) { + return child; + } + } + + return paragraph.lastChild; // If no next marker is found, return the last node in the paragraph + } /** * Scrolls to the specified chapter and verse in the document. @@ -301,10 +379,10 @@ export default function EditorSection({ if (lastChapterElement) { console.warn(`Verse ${verse} in chapter ${chapter} not found. Scrolling to the chapter instead.`); - chapterElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); + // chapterElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); chapterElement.classList.add('highlight-chapter'); setTimeout(() => chapterElement.classList.remove('highlight-chapter'), 5000); - return; + return chapterElement; } // Collect all elements after the verse number until the next verse @@ -337,11 +415,6 @@ export default function EditorSection({ currentElement = currentElement.nextElementSibling; } - // Scroll the first element into view - if (elementsToHighlight.length > 0) { - elementsToHighlight[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); - } - // Highlight all elements elementsToHighlight.forEach((element) => { element.style.backgroundColor = 'orange'; @@ -354,6 +427,13 @@ export default function EditorSection({ element.style.backgroundColor = 'transparent'; }); }, 5000); + + // Scroll the first element into view + if (elementsToHighlight.length > 0) { + // elementsToHighlight[0].scrollIntoView({ behavior: 'smooth', block: 'center' }); + return elementsToHighlight[0]; + } + } const onReferenceClick = (source_ref, source_chapter, source_verse, text = '') => { @@ -381,7 +461,16 @@ export default function EditorSection({ onChangeChapter(clicked_chapter); } onChangeVerse(clicked_verse); - scrollToChapterVerse(clicked_chapter, clicked_verse); + const elementToScrollTo = []; + + elementToScrollTo.push(highlightVerse(clicked_chapter, clicked_verse)); + elementToScrollTo.push(scrollToChapterVerse(clicked_chapter, clicked_verse)); + + for(const elem of elementToScrollTo) { + if(elem) { + elem.scrollIntoView({ top: elem.offsetTop, behavior: "smooth", block: 'center' }); + } + } } const doChecks = async () => { From 3bdd4ca7482fc9f7c86d6a4d9c5c6d7381f5d268 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Tue, 31 Dec 2024 11:06:03 +0100 Subject: [PATCH 12/16] updated bible-checker --- package.json | 4 +- renderer/src/layouts/editor/CheckSelector.js | 49 ++++++++++++++++---- renderer/src/layouts/editor/EditorSection.js | 8 ---- yarn.lock | 8 ++-- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 6a0e7acf9..f74423902 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "^0.0.3", + "bible-checker": "^0.1.0", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", @@ -255,4 +255,4 @@ "word-aligner": "$word-aligner", "@mui/lab": "$@mui/lab" } -} +} \ No newline at end of file diff --git a/renderer/src/layouts/editor/CheckSelector.js b/renderer/src/layouts/editor/CheckSelector.js index 874f2fe44..e719c0ed0 100644 --- a/renderer/src/layouts/editor/CheckSelector.js +++ b/renderer/src/layouts/editor/CheckSelector.js @@ -9,6 +9,7 @@ import { ReferenceContext } from '@/components/context/ReferenceContext'; import localForage from 'localforage'; import * as logger from '../../logger'; import { convertUsfmToUsj } from '@/components/EditorPage/TextEditor/conversionUtils.js'; +// const { Worker } = require('worker_threads'); const CheckSelector = ({ showResourcesPanel, @@ -23,6 +24,29 @@ const CheckSelector = ({ const [theProjectName, setTheProjectName] = useState(''); const [firstSelection, setFirstSelection] = useState(true); + // function runConversionInWebWorker(dataSrcBook, pathInstance) { + // return new Promise((resolve, reject) => { + + // const workerPath = pathInstance.resolve(__dirname, 'usfmWorker.js'); + // console.log("workerPath",workerPath); + // const workerUrl = `file://${workerPath}`; + // const worker = new Worker(workerUrl); + // worker.postMessage(dataSrcBook); + + // worker.onmessage = (event) => { + // if (event.data.success) { + // resolve(event.data.result); + // } else { + // reject(new Error(event.data.error)); + // } + // }; + + // worker.onerror = (error) => { + // reject(error); + // }; + // }); + // } + useEffect(() => { let dataSrcBook = null; @@ -60,20 +84,25 @@ const CheckSelector = ({ let trg_usfm_bookId = localStorage.getItem('trg_usfm_bookId'); let refName = localStorage.getItem('ref_name'); - if(!refName) { + if (!refName) { localStorage.setItem('ref_name', projectName); refName = projectName; } - + // return; + if (firstSelection || projectName != refName || !trg_usfm_bookId || (dataSrcBook && trg_usfm_bookId.toUpperCase() !== currentBook.bookId)) { - convertUsfmToUsj(dataSrcBook).then((usfmToUsj) => { - let strUsj = JSON.stringify(usfmToUsj.usj); - localStorage.setItem('trg_usj', strUsj); - localStorage.setItem('trg_usfm_bookId', usfmToUsj.usj?.content[0]?.code); - localStorage.setItem('ref_name', projectName); - setReferenceSourceData(strUsj); - }).catch((e) => console.error("Error while loading source file", e)); - setFirstSelection(false); + if (!openResourcePopUp) { + convertUsfmToUsj(dataSrcBook) + .then((usfmToUsj) => { + const strUsj = JSON.stringify(usfmToUsj.usj); + localStorage.setItem('trg_usj', strUsj); + localStorage.setItem('trg_usfm_bookId', usfmToUsj.usj?.content[0]?.code); + localStorage.setItem('ref_name', projectName); + setReferenceSourceData(strUsj); + }) + .catch((e) => console.error('Error while loading source file', e)); + setFirstSelection(false); + } } }).catch((e) => console.error("Error while loading source file", e)); }, [bookId, openResourcePopUp, referenceResources.refName]); diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index f9c06ccca..d50935e1d 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -505,14 +505,6 @@ export default function EditorSection({ const [currentBook] = _books.filter((bookObj) => bookObj.bookId === bookId?.toUpperCase()); // const projectCachePath = path.join(newpath, packageInfo.name, 'users', userName, 'project_cache', projectName); if (currentBook) { - // const fileData = await readFile({ projectname: projectName, filename: currentBook.fileName, username: userName }); - // const book = { - // selectors: { org: 'unfoldingWord', lang: 'en', abbr: 'ult' }, - // bookCode: currentBook.bookId?.toLowerCase(), - // data: fileData, - // }; - - let response = null; const USJ = localStorage.getItem('usj'); // console.log("SOURCE ==",JSON.parse(referenceSourceData)); diff --git a/yarn.lock b/yarn.lock index d465d7b2f..fa38d161e 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.0.3.tgz#f14859ae4919b5707e3025b10152b21e1fd625bd" - integrity sha512-xGIOg5Nn41+wjURzDb4yxo8z/VkVv1Wk3+TxWuQE741u1dejpDYNai1izkdXC9l1Zz6ZcoNcg2uBT9J3AlK5xA== +bible-checker@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.1.0.tgz#e638957b2c266e9d127e480703d2d98b8800dd5e" + integrity sha512-XTnhljOnJM942VIEI8w7EUkA/TnT2S5xitIFwfdRJ21Iws6vxsZgAJ3E+f4COk4hiVb+5GPfG72bAUp6uNKHRA== bible-reference-range@^1.1.0: version "1.1.1" From fea49d8c681da7585681623fb4fa72b1a4100b0d Mon Sep 17 00:00:00 2001 From: danielc-n Date: Thu, 2 Jan 2025 11:58:52 +0100 Subject: [PATCH 13/16] fix for : https://github.com/bible-technology/scribe-scripture-editor/pull/389#issuecomment-2566331519 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f74423902..cd83c31be 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "^0.1.0", + "bible-checker": "^0.1.2", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", diff --git a/yarn.lock b/yarn.lock index fa38d161e..81a99ce07 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.1.0.tgz#e638957b2c266e9d127e480703d2d98b8800dd5e" - integrity sha512-XTnhljOnJM942VIEI8w7EUkA/TnT2S5xitIFwfdRJ21Iws6vxsZgAJ3E+f4COk4hiVb+5GPfG72bAUp6uNKHRA== +bible-checker@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.1.2.tgz#1974d337b5ded4ebad27675b4b166ed4069c99fe" + integrity sha512-AkUFwQbd08B706bm8XTDPL6/GkmbzV/GQ1fH9xIGT/fDoE56LRLBLCbxYmj7Q8Tu18K4qHTt+MmFp89NN45wxg== bible-reference-range@^1.1.0: version "1.1.1" From 5d32affffb58427f0339d2f5111a36ace149b84d Mon Sep 17 00:00:00 2001 From: danielc-n Date: Fri, 3 Jan 2025 11:51:20 +0100 Subject: [PATCH 14/16] updated bible-check with number checking --- package.json | 2 +- renderer/src/layouts/editor/EditorSection.js | 9 +++++++-- yarn.lock | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index cd83c31be..651aba6d3 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "^0.1.2", + "bible-checker": "^0.2.0", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index d50935e1d..19e31d363 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -436,7 +436,7 @@ export default function EditorSection({ } - const onReferenceClick = (source_ref, source_chapter, source_verse, text = '') => { + const onReferenceClick = async (source_ref, source_chapter, source_verse, text = '') => { let ref = null; if (source_ref) { ref = source_ref; @@ -466,9 +466,14 @@ export default function EditorSection({ elementToScrollTo.push(highlightVerse(clicked_chapter, clicked_verse)); elementToScrollTo.push(scrollToChapterVerse(clicked_chapter, clicked_verse)); + function delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + for(const elem of elementToScrollTo) { if(elem) { - elem.scrollIntoView({ top: elem.offsetTop, behavior: "smooth", block: 'center' }); + elem.scrollIntoView({ top: elem.offsetTop, behavior: "auto", block: 'center' }); + await delay(500); } } } diff --git a/yarn.lock b/yarn.lock index 81a99ce07..511e84096 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.1.2.tgz#1974d337b5ded4ebad27675b4b166ed4069c99fe" - integrity sha512-AkUFwQbd08B706bm8XTDPL6/GkmbzV/GQ1fH9xIGT/fDoE56LRLBLCbxYmj7Q8Tu18K4qHTt+MmFp89NN45wxg== +bible-checker@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.2.0.tgz#294dad2c9826892564f5f09463c103593756d14f" + integrity sha512-DiCTeAkqF4WmcLm9tOKxjHIKvaHuIOOwwvjP/uOPWoxVks6OxRcVllc7emP6vyiDsClApHJaaclArggOlWVN3g== bible-reference-range@^1.1.0: version "1.1.1" From 63f71fb42e5459a181ea40d7459251c72743a890 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Sat, 4 Jan 2025 13:35:47 +0100 Subject: [PATCH 15/16] update for few fixes : https://github.com/bible-technology/scribe-scripture-editor/pull/389#issuecomment-2571276002 --- package.json | 2 +- .../components/EditorPage/TextEditor/ChecksContent.jsx | 7 +++++-- renderer/src/layouts/editor/CheckSelector.js | 6 +++--- yarn.lock | 8 ++++---- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 651aba6d3..76ce5fb9b 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "^0.2.0", + "bible-checker": "0.2.1", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", diff --git a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx index 4750bfadd..0e0f7112a 100644 --- a/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx +++ b/renderer/src/components/EditorPage/TextEditor/ChecksContent.jsx @@ -41,7 +41,7 @@ export default function ChecksContent({ content, updateContent, onReferenceClick return (
-
+

Checks

+ {issue.verse_text && (
+ Source verse: {issue.verse_text} +
)}
Reference:{' '}
); }; diff --git a/yarn.lock b/yarn.lock index 511e84096..f634a2cb2 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.2.0.tgz#294dad2c9826892564f5f09463c103593756d14f" - integrity sha512-DiCTeAkqF4WmcLm9tOKxjHIKvaHuIOOwwvjP/uOPWoxVks6OxRcVllc7emP6vyiDsClApHJaaclArggOlWVN3g== +bible-checker@0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.2.1.tgz#ba6f69102cd55acee2c5de2f8d9d53b4b3d477b6" + integrity sha512-PanCdbaOx9AziMPm3o6gYYEjcZzuuDJndxqjafTNwJ4OwQn96sdRjuT5/I56IyWk+uA2FsBqACF5/hFHY5W5Pw== bible-reference-range@^1.1.0: version "1.1.1" From f8708fe8b6277e10f71b1e159b9b59f871eb2865 Mon Sep 17 00:00:00 2001 From: danielc-n Date: Thu, 16 Jan 2025 09:01:41 +0100 Subject: [PATCH 16/16] final fixes for bible-checks --- package.json | 2 +- renderer/src/layouts/editor/EditorSection.js | 13 +------------ yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 76ce5fb9b..ac396550b 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "@xelah/type-perf-html": "^1.0.1", "adm-zip": "^0.5.9", "audiobuffer-to-wav": "^1.0.0", - "bible-checker": "0.2.1", + "bible-checker": "1.0.0", "bible-reference-rcl": "1.1.0", "clsx": "1.1.1", "crypto-js": "^4.1.1", diff --git a/renderer/src/layouts/editor/EditorSection.js b/renderer/src/layouts/editor/EditorSection.js index 19e31d363..61882f444 100644 --- a/renderer/src/layouts/editor/EditorSection.js +++ b/renderer/src/layouts/editor/EditorSection.js @@ -489,16 +489,7 @@ export default function EditorSection({ 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 filePath = path.join(newpath, packageInfo.name, 'config_checks.json'); - let spec = {}; - try { - spec = fse.readJsonSync(filePath); - } catch (error) { - logger.error( - 'EditorSection.js', - 'Unable to open config_checks.json', - ); - } + const _books = []; Object.entries(metaData.ingredients).forEach(async ([key, _ingredients]) => { if (_ingredients.scope) { @@ -508,7 +499,6 @@ export default function EditorSection({ } }); const [currentBook] = _books.filter((bookObj) => bookObj.bookId === bookId?.toUpperCase()); - // const projectCachePath = path.join(newpath, packageInfo.name, 'users', userName, 'project_cache', projectName); if (currentBook) { let response = null; const USJ = localStorage.getItem('usj'); @@ -522,7 +512,6 @@ export default function EditorSection({ } if (response) { setContentChecks(response.checks); - // console.log("response ==", response.checks); } } } diff --git a/yarn.lock b/yarn.lock index f634a2cb2..4c945462c 100755 --- a/yarn.lock +++ b/yarn.lock @@ -6745,10 +6745,10 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" -bible-checker@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-0.2.1.tgz#ba6f69102cd55acee2c5de2f8d9d53b4b3d477b6" - integrity sha512-PanCdbaOx9AziMPm3o6gYYEjcZzuuDJndxqjafTNwJ4OwQn96sdRjuT5/I56IyWk+uA2FsBqACF5/hFHY5W5Pw== +bible-checker@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/bible-checker/-/bible-checker-1.0.0.tgz#8ac5b1d2f054bf704bb866ad0287455c4c63d7d3" + integrity sha512-XdvhxjNE1Sli6Rrqfb//jvTEqBHeZwg93CxoQA59/sc9wzm6ztzxv7UQFm70eXEVoEHNXCLJrCsFc7CIw+1hbA== bible-reference-range@^1.1.0: version "1.1.1"