diff --git a/convert/convertBooks.ts b/convert/convertBooks.ts
index cabbf31aa..2a4821f29 100644
--- a/convert/convertBooks.ts
+++ b/convert/convertBooks.ts
@@ -10,6 +10,7 @@ import { queries, postQueries, freeze } from '../sab-proskomma-tools';
import { convertMarkdownsToMilestones } from './convertMarkdown';
import { verifyGlossaryEntries } from './verifyGlossaryEntries';
import { hasAudioExtension, hasImageExtension } from './stringUtils';
+import { convertStorybookElements } from './storybook';
/**
* Loops through bookCollections property of configData.
@@ -22,10 +23,16 @@ function replaceVideoTags(text: string, _bcId: string, _bookId: string): string
return text.replace(/\\video (.*)/g, '\\zvideo-s |id="$1"\\*\\zvideo-e\\*');
}
-// This is the start of supporting story books, but it still fails if there is no chapter.
-function replacePageTags(text: string, _bcId: string, _bookId: string): string {
- return text.replace(/\\page (.*)/g, '\\zpage-s |id="$1"\\*\\zpage-e\\*');
+/**
+ * Replace the USFM book ID with the given book ID.
+ *
+ * While uncommon, it is possible to use the same USFM for multiple books.
+ * In this case, we must use the unique ID specified in config.
+ */
+function replaceId(text: string, _bcId: string, bookId: string): string {
+ return text.replace(/\\id \w+/, `\\id ${bookId}`);
}
+
function loadGlossary(collection: any, dataDir: string): string[] {
const glossary: string[] = [];
for (const book of collection.books) {
@@ -101,16 +108,23 @@ function isImageMissing(imageSource: string): boolean {
const filterFunctions: ((text: string, bcId: string, bookId: string) => string)[] = [
removeStrongNumberReferences,
replaceVideoTags,
- replacePageTags,
convertMarkdownsToMilestones,
- removeMissingFigures
+ removeMissingFigures,
+ replaceId
];
-function applyFilters(text: string, bcId: string, bookId: string): string {
+function applyFilters(text: string, bcId: string, bookId: string, bookType?: string): string {
let filteredText = text;
for (const filterFn of filterFunctions) {
filteredText = filterFn(filteredText, bcId, bookId);
}
+ if (bookType === 'story') {
+ filteredText = convertStorybookElements(filteredText);
+ }
+ // Debugging
+ // if (bcId == 'C01') {
+ // console.log(filteredText.slice(0, 1000));
+ // }
return filteredText;
}
@@ -204,7 +218,6 @@ export async function convertBooks(
for (const book of collection.books) {
let bookConverted = false;
switch (book.type) {
- case 'story':
case 'songs':
case 'audio-only':
case 'bloom-player':
@@ -490,7 +503,7 @@ function convertScriptureBook(
function processBookContent(resolve: () => void, err: any, content: string) {
//process.stdout.write(`processBookContent: bookId:${book.id}, error:${err}\n`);
if (err) throw err;
- content = applyFilters(content, context.bcId, book.id);
+ content = applyFilters(content, context.bcId, book.id, book.type);
if (context.configData.traits['has-glossary']) {
content = verifyGlossaryEntries(content, bcGlossary);
}
@@ -567,7 +580,23 @@ function convertScriptureBook(
fileContents.push(fs.readFileSync(filePath, 'utf-8'));
});
- processBookContent(resolve, null, fileContents.join(''));
+ // Collect the file contents into a single document
+ let usfm: string;
+
+ if (book.type == 'story') {
+ // The first file contains meta-content (id, title, etc)
+ usfm = fileContents[0];
+
+ // Subsequent files represent storybook pages.
+ // SAB deletes the \page tags. Replace them with chapter tags.
+ for (let i = 1; i < fileContents.length; i++) {
+ usfm += `\\c ${i} ${fileContents[i]}`;
+ }
+ } else {
+ usfm = fileContents.join('');
+ }
+
+ processBookContent(resolve, null, usfm);
}
})
);
diff --git a/convert/convertConfig.ts b/convert/convertConfig.ts
index 6b1f32189..d91b4163d 100644
--- a/convert/convertConfig.ts
+++ b/convert/convertConfig.ts
@@ -22,6 +22,12 @@ type BookCollectionAudio = {
timingFile: string;
};
+type StorybookImage = {
+ page: string;
+ filename: string;
+ // TODO: Add motion parameters
+};
+
type Style = {
font: string;
textSize: number;
@@ -49,6 +55,7 @@ export type Book = {
audio: BookCollectionAudio[];
features: any;
quizFeatures?: any;
+ storybookImages?: StorybookImage[];
footer?: HTML;
style?: Style;
styles?: {
@@ -419,6 +426,109 @@ function convertCollectionFooter(collectionTag: Element, document: Document) {
return footer;
}
+function shortenBookCode(id: string, allIds: string[]): string | null {
+ const short = id.replace(/^(\w)0(\d\d)$/, '$1$2');
+ return id === short || allIds.includes(short) ? null : short;
+}
+
+function lengthenBookCode(id: string, allIds: string[]): string | null {
+ if (id.length === 1) {
+ id = '00' + id;
+ } else if (id.length === 2) {
+ id = '0' + id;
+ }
+ return allIds.includes(id) ? null : id;
+}
+
+function convertBookCodes(books: Element[]) {
+ for (const bk of books) {
+ bk.setAttribute('fullId', bk.id);
+ const ids = books.map((b) => b.id);
+ const shortened = shortenBookCode(bk.id, ids);
+ const lengthened = lengthenBookCode(bk.id, ids);
+ if (shortened) {
+ console.log(` shortening book code: ${bk.id} => ${shortened}`);
+ bk.id = shortened;
+ } else if (lengthened) {
+ console.log(` lengthening book code: ${bk.id} => ${lengthened}`);
+ bk.id = lengthened;
+ }
+ }
+ checkBookCodes(books);
+}
+
+function checkBookCodes(books: Element[]) {
+ const invalid = books.map((b) => b.id).filter((id) => id.length !== 3);
+ if (invalid.length) {
+ console.log(
+ '\n WARNING: The following book codes are not 3 characters. Some may not load properly:'
+ );
+ console.log(` ${invalid.join(' ')}`);
+ }
+}
+
+function getBookAudio(book: Element, verbose: number) {
+ const audio: BookCollectionAudio[] = [];
+ for (const page of book.getElementsByTagName('page')) {
+ if (verbose >= 2) console.log(`.. page: ${page.attributes[0].value}`);
+ const audioTag = page.getElementsByTagName('audio')[0];
+ if (!audioTag) continue;
+ if (audioTag.attributes.getNamedItem('background')?.value === 'continue') {
+ // Happens when a storybook uses a single audio file for multiple pages.
+ // TODO: Implement this feature
+ continue;
+ }
+ const fTag = audioTag.getElementsByTagName('f')[0];
+ if (verbose >= 2)
+ console.log(`... audioTag: ${audioTag.outerHTML}, fTag:${fTag.outerHTML}`);
+ audio.push({
+ num: parseInt(page.attributes.getNamedItem('num')!.value),
+ filename: fTag.innerHTML,
+ len: fTag.hasAttribute('len')
+ ? parseInt(fTag.attributes.getNamedItem('len')!.value)
+ : undefined,
+ size: fTag.hasAttribute('size')
+ ? parseInt(fTag.attributes.getNamedItem('size')!.value)
+ : undefined,
+ src: fTag.attributes.getNamedItem('src')!.value,
+ timingFile: audioTag.getElementsByTagName('y')[0]?.innerHTML
+ });
+ if (verbose >= 3) console.log(`.... audio: `, JSON.stringify(audio[0]));
+ }
+ return audio;
+}
+
+function imageFromPage(
+ page: Element,
+ collection: string,
+ book: string,
+ imageFiles: string[]
+): StorybookImage | null {
+ const filenameElement = page.getElementsByTagName('image-filename')[0];
+
+ // In testing, the image filename took one of the following two forms
+ const filename1 = filenameElement?.textContent;
+ const filename2 = `${collection}-${book}-${filename1}`;
+ const file = imageFiles.find((f) => [filename1, filename2].includes(f));
+
+ const num = page.getAttribute('num');
+ return file && num
+ ? {
+ filename: file,
+ page: num
+ }
+ : null;
+}
+
+function getStorybookImages(book: Element, collection: string, dataDir: string): StorybookImage[] {
+ const id = book.getAttribute('fullId') ?? book.id;
+ const pages = Array.from(book.getElementsByTagName('page'));
+ const imageFiles = readdirSync(path.join(dataDir, 'illustrations'));
+ return pages
+ .map((page) => imageFromPage(page, collection, id, imageFiles))
+ .filter((image) => image) as StorybookImage[];
+}
+
function convertConfig(dataDir: string, verbose: number) {
const dom = new jsdom.JSDOM(readFileSync(path.join(dataDir, 'appdef.xml')).toString(), {
contentType: 'text/xml'
@@ -578,30 +688,9 @@ function convertConfig(dataDir: string, verbose: number) {
}
const books: BookCollection['books'] = [];
const bookTags = tag.getElementsByTagName('book');
+ convertBookCodes(Array.from(bookTags));
for (const book of bookTags) {
if (verbose >= 2) console.log(`. book: ${book.id}`);
- const audio: BookCollectionAudio[] = [];
- for (const page of book.getElementsByTagName('page')) {
- if (verbose >= 2) console.log(`.. page: ${page.attributes[0].value}`);
- const audioTag = page.getElementsByTagName('audio')[0];
- if (!audioTag) continue;
- const fTag = audioTag.getElementsByTagName('f')[0];
- if (verbose >= 2)
- console.log(`... audioTag: ${audioTag.outerHTML}, fTag:${fTag.outerHTML}`);
- audio.push({
- num: parseInt(page.attributes.getNamedItem('num')!.value),
- filename: fTag.innerHTML,
- len: fTag.hasAttribute('len')
- ? parseInt(fTag.attributes.getNamedItem('len')!.value)
- : undefined,
- size: fTag.hasAttribute('size')
- ? parseInt(fTag.attributes.getNamedItem('size')!.value)
- : undefined,
- src: fTag.attributes.getNamedItem('src')!.value,
- timingFile: audioTag.getElementsByTagName('y')[0]?.innerHTML
- });
- if (verbose >= 3) console.log(`.... audio: `, JSON.stringify(audio[0]));
- }
const bookFeaturesTag = book
.querySelector('features[type=book]')
?.getElementsByTagName('e');
@@ -658,7 +747,8 @@ function convertConfig(dataDir: string, verbose: number) {
section: book.getElementsByTagName('sg')[0]?.innerHTML,
testament: book.getElementsByTagName('g')[0]?.innerHTML,
abbreviation: book.getElementsByTagName('v')[0]?.innerHTML,
- audio,
+ audio: getBookAudio(book, verbose),
+ storybookImages: getStorybookImages(book, tag.id, dataDir),
file: book.getElementsByTagName('f')[0]?.innerHTML.replace(/\.\w*$/, '.usfm'),
features: bookFeatures,
quizFeatures,
diff --git a/convert/storybook.test.ts b/convert/storybook.test.ts
new file mode 100644
index 000000000..f223d1e6e
--- /dev/null
+++ b/convert/storybook.test.ts
@@ -0,0 +1,270 @@
+import { expect, test } from 'vitest';
+import {
+ transformLists,
+ replacePageTags,
+ removeImageTags,
+ transformHeadings,
+ convertPTags
+} from './storybook';
+
+function tokensOf(str: string) {
+ return str.split(/\s+/).filter((token) => token.length);
+}
+
+test('replace page tags', () => {
+ const input = 'abc \\page 41 xyz \\page 45 122';
+ const expected = 'abc \\c 41 xyz \\c 45 122';
+ const result = replacePageTags(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+// For now, get image data from config.js (may change this in the future)
+test('remove img tags', () => {
+ const input = 'abc \\img img1.jpeg efg \\img image-2.jpeg \\img image_with_underscores.jpeg';
+ const expected = 'abc efg';
+ const result = removeImageTags(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convertPTags', () => {
+ const input = 'abc \\p_Normal hello world \\m \\b';
+ const expected = 'abc \\m hello world \\m \\b';
+ const result = convertPTags(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert unordered list to milestones', () => {
+ const input = `
+ \\m Some content
+ \\zuli1 One
+ \\zuli1 Two \\zuli1 Three in a row!
+ \\b
+ `;
+ const expected = `
+ \\m Some content
+ \\m
+ \\zuli1-s |\\* One \\zuli1-e\\*
+ \\zuli1-s |\\* Two \\zuli1-e\\*
+ \\zuli1-s |\\* Three in a row! \\zuli1-e\\*
+ \\b
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert ordered list to milestones', () => {
+ const input = `
+ \\m Some content
+ \\zon1 10
+ \\zoli1 One
+ \\zoli1 Two \\zoli1 Three in a row!
+ \\b
+ `;
+ const expected = `
+ \\m Some content
+ \\m
+ \\zon1-s |start="10"\\*
+ \\zoli1-s |\\* One \\zoli1-e\\*
+ \\zoli1-s |\\* Two \\zoli1-e\\*
+ \\zoli1-s |\\* Three in a row! \\zoli1-e\\*
+ \\zon1-e\\*
+ \\b
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert unordered list with formatting to milestones', () => {
+ const input = `
+ \\m Some content
+ \\zuli1 One
+ \\zuli1 \\bd Two \\bd*
+ \\zuli1 Three in a row!
+ \\b
+ `;
+ const expected = `
+ \\m Some content
+ \\m
+ \\zuli1-s |\\* One \\zuli1-e\\*
+ \\zuli1-s |\\* \\bd Two \\bd* \\zuli1-e\\*
+ \\zuli1-s |\\* Three in a row! \\zuli1-e\\*
+ \\b
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert ordered list with formatting to milestones', () => {
+ const input = `
+ \\m Some content
+ \\zon1 10
+ \\zoli1 One
+ \\zoli1 \\bdit Two \\bdit*
+ \\zoli1 Three in a row!
+ \\b
+ `;
+ const expected = `
+ \\m Some content
+ \\m
+ \\zon1-s |start="10"\\*
+ \\zoli1-s |\\* One \\zoli1-e\\*
+ \\zoli1-s |\\* \\bdit Two \\bdit* \\zoli1-e\\*
+ \\zoli1-s |\\* Three in a row! \\zoli1-e\\*
+ \\zon1-e\\*
+ \\b
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert multilevel unordered list to milestones', () => {
+ const input = `
+ \\c 2
+ \\b
+ \\zuli1 Old Testament
+ \\zuli2 Pentateuch
+ \\zuli3 Genesis
+ \\zuli3 Exodus
+ \\zuli3 Leviticus
+ \\zuli2 Joshua
+ \\zuli2 Judges
+ \\zuli1 New Testament
+ \\zuli2 Matthew
+ \\zuli2 Mark
+ \\zuli2 Luke
+ \\zuli2 John
+ \\zuli1 Glossary
+ `;
+ const expected = `
+ \\c 2
+ \\b
+ \\m
+ \\zuli1-s |\\* Old Testament
+ \\zuli2-s |\\* Pentateuch
+ \\zuli3-s |\\* Genesis \\zuli3-e\\*
+ \\zuli3-s |\\* Exodus \\zuli3-e\\*
+ \\zuli3-s |\\* Leviticus \\zuli3-e\\*
+ \\zuli2-e\\*
+ \\zuli2-s |\\* Joshua \\zuli2-e\\*
+ \\zuli2-s |\\* Judges \\zuli2-e\\*
+ \\zuli1-e\\*
+ \\zuli1-s |\\* New Testament
+ \\zuli2-s |\\* Matthew \\zuli2-e\\*
+ \\zuli2-s |\\* Mark \\zuli2-e\\*
+ \\zuli2-s |\\* Luke \\zuli2-e\\*
+ \\zuli2-s |\\* John \\zuli2-e\\*
+ \\zuli1-e\\*
+ \\zuli1-s |\\* Glossary \\zuli1-e\\*
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert multilevel ordered list to milestones', () => {
+ const input = `
+ \\m My List:
+ \\b
+ \\zon1 1
+ \\zoli1 Food
+ \\zon2 1
+ \\zoli2 Fruit
+ \\zon3 1
+ \\zoli3 Apples
+ \\zoli3 Bananas
+ \\zoli3 Pears
+ \\zoli2 Dessert
+ \\zoli3 Pie
+ \\zoli3 Cake
+ \\zoli3 Ice Cream
+ \\zoli1 Drinks
+ \\zoli2 Coffee
+ \\zoli2 Water
+ \\zoli2 Tea
+ `;
+ const expected = `
+ \\m My List:
+ \\b
+ \\m
+ \\zon1-s |start="1"\\*
+ \\zoli1-s |\\* Food
+ \\zon2-s |start="1"\\*
+ \\zoli2-s |\\* Fruit
+ \\zon3-s |start="1"\\*
+ \\zoli3-s |\\* Apples \\zoli3-e\\*
+ \\zoli3-s |\\* Bananas \\zoli3-e\\*
+ \\zoli3-s |\\* Pears \\zoli3-e\\*
+ \\zon3-e\\*
+ \\zoli2-e\\*
+ \\zoli2-s |\\* Dessert
+ \\zon3-s |start="1"\\*
+ \\zoli3-s |\\* Pie \\zoli3-e\\*
+ \\zoli3-s |\\* Cake \\zoli3-e\\*
+ \\zoli3-s |\\* Ice Cream \\zoli3-e\\*
+ \\zon3-e\\*
+ \\zoli2-e\\*
+ \\zon2-e\\*
+ \\zoli1-e\\*
+ \\zoli1-s |\\* Drinks
+ \\zon2-s |start="1"\\*
+ \\zoli2-s |\\* Coffee \\zoli2-e\\*
+ \\zoli2-s |\\* Water \\zoli2-e\\*
+ \\zoli2-s |\\* Tea \\zoli2-e\\*
+ \\zon2-e\\*
+ \\zoli1-e\\*
+ \\zon1-e\\*
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('convert multilevel ordered list with formatting to milestones', () => {
+ const input = `
+ \\m Some content
+ \\zon1 10
+ \\zoli1 One
+ \\zon2 3
+ \\zoli2 \\it sub-point 1 \\it*
+ \\zoli2 sub-point 2
+ \\zoli1 \\bdit Two \\bdit*
+ \\zoli1 Three in a row!
+ \\b
+ `;
+ const expected = `
+ \\m Some content
+ \\m
+ \\zon1-s |start="10"\\*
+ \\zoli1-s |\\* One
+ \\zon2-s |start="3"\\*
+ \\zoli2-s |\\* \\it sub-point 1 \\it* \\zoli2-e\\*
+ \\zoli2-s |\\* sub-point 2 \\zoli2-e\\*
+ \\zon2-e\\*
+ \\zoli1-e\\*
+ \\zoli1-s |\\* \\bdit Two \\bdit* \\zoli1-e\\*
+ \\zoli1-s |\\* Three in a row! \\zoli1-e\\*
+ \\zon1-e\\*
+ \\b
+ `;
+ const result = transformLists(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
+
+test('converts section headings to milestones', () => {
+ const input = `
+ \\ms1 Hello
+ \\ms2 World
+ \\b
+ \\s Some content
+ \\s2 Some other content
+ \\m
+ `;
+ const expected = `
+ \\m \\zusfm-s |class="ms1"\\* Hello \\zusfm-e
+ \\m \\zusfm-s |class="ms2"\\* World \\zusfm-e
+ \\b
+ \\m \\zusfm-s |class="s"\\* Some content \\zusfm-e
+ \\m \\zusfm-s |class="s2"\\* Some other content \\zusfm-e
+ \\m
+ `;
+ const result = transformHeadings(input);
+ expect(tokensOf(result)).toEqual(tokensOf(expected));
+});
diff --git a/convert/storybook.ts b/convert/storybook.ts
new file mode 100644
index 000000000..ffc6167bf
--- /dev/null
+++ b/convert/storybook.ts
@@ -0,0 +1,143 @@
+/**
+ * A list of inline character format markers
+ */
+const characterMarkers = 'em bd it bdit no sc sup'.split(' ');
+
+/**
+ * Replace page tags with chapters
+ */
+export function replacePageTags(usfm: string): string {
+ return usfm.replace(/\\page\s+(\d+)/g, '\\c $1');
+}
+
+/**
+ * Remove img tags
+ *
+ * For now, get images from config (may change this later)
+ */
+export function removeImageTags(usfm: string): string {
+ return usfm.replace(/\\img\s+\S+/g, '');
+}
+
+/**
+ * Replace \p_Normal paragraphs with \m
+ */
+export function convertPTags(usfm: string) {
+ return usfm.replace(/\\p_Normal/g, '\\m');
+}
+
+/**
+ * Convert list tags to milestones
+ */
+export function transformLists(usfm: string): string {
+ usfm = transformUnorderedLists(usfm);
+ usfm = transformOrderedLists(usfm);
+ return usfm;
+}
+
+function transformUnorderedLists(usfm: string): string {
+ const inlineMarkers = [...characterMarkers, 'zuli'].join('|');
+ const listPattern = new RegExp(`\\\\zuli([^\\\\]|\\\\(${inlineMarkers}))*`, 'g');
+ // Place a paragraph marker (\m) before unordered lists
+ usfm = usfm.replace(listPattern, '\\m $& ');
+ let level = 1;
+ let tag = '\\zuli' + level;
+ while (usfm.includes(tag)) {
+ const inlineMarkers = [...characterMarkers, `zuli[^1-${level}]`].join('|');
+ const pattern = new RegExp(`\\${tag}\\s(([^\\\\]|\\\\(${inlineMarkers}))*)`, 'g');
+ usfm = usfm.replace(pattern, `${tag}-s |\\* $1 ${tag}-e\\* `);
+ level++;
+ tag = '\\zuli' + level;
+ }
+ return usfm;
+}
+
+/**
+ * Get the start number for an ordered list
+ */
+function getStartNumber(usfm: string, level: number) {
+ const startPattern = new RegExp(`\\\\zon${level} (\\d+)`);
+ const startMatch = usfm.match(startPattern);
+ return startMatch ? startMatch[1] : '1';
+}
+
+function transformOrderedListItems(usfm: string, level: number) {
+ // A nested list
+ // * begins with \zon# or \zoli#, where # does not equal the current level
+ // * ends at the first sfm tag that is not \zon#, \zoli#, or a character marker
+ const sublistMarkers = [...characterMarkers, `zon[^${level}]`, `zoli[^${level}]`].join('|');
+ const sublistPattern = `(\\\\zo(n|li)[^${level}])([^\\\\]|\\\\(${sublistMarkers}))*`;
+
+ // A list item consists of the following parts:
+ // * \zoli# tag, where # is the current level
+ // * text that may include only character markers
+ // * a nested list (optional)
+ const textMarkers = characterMarkers.join('|');
+ const itemPattern = new RegExp(
+ `\\\\zoli${level}\\s((?:[^\\\\]|\\\\(?:${textMarkers}))*)(${sublistPattern})?`,
+ 'g'
+ );
+ const items = Array.from(usfm.matchAll(itemPattern));
+ return items
+ .map((item) => {
+ const sublist = item[2] ? transformOrderedSublist(item[2], level + 1) : '';
+ return `\\zoli${level}-s |\\* ${item[1]} ${sublist} \\zoli${level}-e\\*`;
+ })
+ .join(' ');
+}
+
+function transformOrderedSublist(usfm: string, level: number): string {
+ const start = getStartNumber(usfm, level);
+
+ // A list's contents
+ // * begins with \zoli#, where # is the current level
+ // * contains no sfm tags except the following:
+ // - \zoli#, where # is any number
+ // - \zon#, where # is not the current level
+ const allowedMarkers = [...characterMarkers, 'zoli', `zon[^${level}]`].join('|');
+ const contentsPattern = new RegExp(`\\\\zoli${level}\\s([^\\\\]|\\\\(${allowedMarkers}))*`);
+ const contentsMatch = usfm.match(contentsPattern);
+ if (contentsMatch) {
+ const contents = transformOrderedListItems(contentsMatch[0], level);
+ return ` \\zon${level}-s |start="${start}"\\* ${contents} \\zon${level}-e\\* `;
+ }
+ throw new Error(`Invalid USFM list: ${usfm}`);
+}
+
+function transformOrderedLists(usfm: string) {
+ // Each ordered list
+ // * begins with \zon1
+ // * contains no sfm markers except the following:
+ // - inline character markup
+ // - \zoli#, where # is any number
+ // - \zon#, where # is not 1
+ const allowedMarkers = [...characterMarkers, 'zoli', 'zon[^1]'].join('|');
+ const listPattern = new RegExp(`\\\\zon1\\s([^\\\\]|\\\\(${allowedMarkers}))*`, 'g');
+ const lists = usfm.matchAll(listPattern);
+ let transformed = '';
+ let i = 0;
+ for (const list of lists) {
+ transformed += usfm.substring(i, list.index);
+ transformed += ' \\m ';
+ transformed += transformOrderedSublist(list[0], 1);
+ if (list.index === undefined) {
+ throw new Error('Expected regex match index to be defined');
+ } else {
+ i = list.index + list[0].length;
+ }
+ }
+ return transformed + usfm.substring(i);
+}
+
+export function transformHeadings(usfm: string): string {
+ return usfm.replace(/\\(m?s\d?)([^\\]*)/g, '\\m \\zusfm-s |class="$1"\\* $2 \\zusfm-e ');
+}
+
+export function convertStorybookElements(usfm: string) {
+ usfm = replacePageTags(usfm);
+ usfm = removeImageTags(usfm);
+ usfm = convertPTags(usfm);
+ usfm = transformLists(usfm);
+ usfm = transformHeadings(usfm);
+ return usfm;
+}
diff --git a/package-lock.json b/package-lock.json
index 7936f65db..8e70d7505 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,7 +46,7 @@
"ts-node": "^10.8.1",
"typescript": "^5",
"vite": "^4",
- "vitest": "^1.0.0"
+ "vitest": "^1.4.0"
}
},
"convert": {
@@ -3078,9 +3078,9 @@
}
},
"node_modules/@grpc/grpc-js": {
- "version": "1.9.14",
- "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.14.tgz",
- "integrity": "sha512-nOpuzZ2G3IuMFN+UPPpKrC6NsLmWsTqSsm66IRfnBt1D4pwTqE27lmbpcPM+l2Ua4gE7PfjRHI6uedAy7hoXUw==",
+ "version": "1.9.15",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
+ "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
"dev": true,
"dependencies": {
"@grpc/proto-loader": "^0.7.8",
@@ -3445,6 +3445,19 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.20.0.tgz",
+ "integrity": "sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz",
@@ -3471,6 +3484,19 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.20.0.tgz",
+ "integrity": "sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz",
@@ -3484,6 +3510,19 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.20.0.tgz",
+ "integrity": "sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz",
@@ -3935,13 +3974,13 @@
"dev": true
},
"node_modules/@vitest/expect": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.2.1.tgz",
- "integrity": "sha512-/bqGXcHfyKgFWYwIgFr1QYDaR9e64pRKxgBNWNXPefPFRhgm+K3+a/dS0cUGEreWngets3dlr8w8SBRw2fCfFQ==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz",
+ "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==",
"dev": true,
"dependencies": {
- "@vitest/spy": "1.2.1",
- "@vitest/utils": "1.2.1",
+ "@vitest/spy": "1.6.0",
+ "@vitest/utils": "1.6.0",
"chai": "^4.3.10"
},
"funding": {
@@ -3949,12 +3988,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.2.1.tgz",
- "integrity": "sha512-zc2dP5LQpzNzbpaBt7OeYAvmIsRS1KpZQw4G3WM/yqSV1cQKNKwLGmnm79GyZZjMhQGlRcSFMImLjZaUQvNVZQ==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz",
+ "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==",
"dev": true,
"dependencies": {
- "@vitest/utils": "1.2.1",
+ "@vitest/utils": "1.6.0",
"p-limit": "^5.0.0",
"pathe": "^1.1.1"
},
@@ -3978,9 +4017,9 @@
}
},
"node_modules/@vitest/runner/node_modules/yocto-queue": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
- "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz",
+ "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==",
"dev": true,
"engines": {
"node": ">=12.20"
@@ -3990,9 +4029,9 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.2.1.tgz",
- "integrity": "sha512-Tmp/IcYEemKaqAYCS08sh0vORLJkMr0NRV76Gl8sHGxXT5151cITJCET20063wk0Yr/1koQ6dnmP6eEqezmd/Q==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz",
+ "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.5",
@@ -4004,9 +4043,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.2.1.tgz",
- "integrity": "sha512-vG3a/b7INKH7L49Lbp0IWrG6sw9j4waWAucwnksPB1r1FTJgV7nkBByd9ufzu6VWya/QTvQW4V9FShZbZIB2UQ==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz",
+ "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==",
"dev": true,
"dependencies": {
"tinyspy": "^2.2.0"
@@ -4016,12 +4055,12 @@
}
},
"node_modules/@vitest/ui": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.2.1.tgz",
- "integrity": "sha512-5kyEDpH18TB13Keutk5VScWG+LUDfPJOL2Yd1hqX+jv6+V74tp4ZYcmTgx//WDngiZA5PvX3qCHQ5KrhGzPbLg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-1.6.0.tgz",
+ "integrity": "sha512-k3Lyo+ONLOgylctiGovRKy7V4+dIN2yxstX3eY5cWFXH6WP+ooVX79YSyi0GagdTQzLmT43BF27T0s6dOIPBXA==",
"dev": true,
"dependencies": {
- "@vitest/utils": "1.2.1",
+ "@vitest/utils": "1.6.0",
"fast-glob": "^3.3.2",
"fflate": "^0.8.1",
"flatted": "^3.2.9",
@@ -4033,13 +4072,13 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "vitest": "^1.0.0"
+ "vitest": "1.6.0"
}
},
"node_modules/@vitest/utils": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.2.1.tgz",
- "integrity": "sha512-bsH6WVZYe/J2v3+81M5LDU8kW76xWObKIURpPrOXm2pjBniBu2MERI/XP60GpS4PHU3jyK50LUutOwrx4CyHUg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz",
+ "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.6.3",
@@ -4428,12 +4467,12 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -4581,9 +4620,9 @@
]
},
"node_modules/chai": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
- "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==",
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
+ "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==",
"dev": true,
"dependencies": {
"assertion-error": "^1.1.0",
@@ -4592,7 +4631,7 @@
"get-func-name": "^2.0.2",
"loupe": "^2.3.6",
"pathval": "^1.1.1",
- "type-detect": "^4.0.8"
+ "type-detect": "^4.1.0"
},
"engines": {
"node": ">=4"
@@ -5082,9 +5121,9 @@
"dev": true
},
"node_modules/deep-eql": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
- "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz",
+ "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==",
"dev": true,
"dependencies": {
"type-detect": "^4.0.0"
@@ -5867,9 +5906,9 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -7798,9 +7837,9 @@
}
},
"node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
"dev": true
},
"node_modules/picomatch": {
@@ -7845,9 +7884,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "version": "8.4.40",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz",
+ "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==",
"dev": true,
"funding": [
{
@@ -7865,7 +7904,7 @@
],
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
+ "picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
},
"engines": {
@@ -8299,9 +8338,9 @@
]
},
"node_modules/react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"dev": true
},
"node_modules/read-cache": {
@@ -9162,17 +9201,23 @@
}
},
"node_modules/strip-literal": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz",
- "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz",
+ "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==",
"dev": true,
"dependencies": {
- "acorn": "^8.10.0"
+ "js-tokens": "^9.0.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/strip-literal/node_modules/js-tokens": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz",
+ "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==",
+ "dev": true
+ },
"node_modules/sucrase": {
"version": "3.34.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
@@ -9594,18 +9639,18 @@
"dev": true
},
"node_modules/tinypool": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz",
- "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==",
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz",
+ "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==",
"dev": true,
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tinyspy": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz",
- "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz",
+ "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==",
"dev": true,
"engines": {
"node": ">=14.0.0"
@@ -9784,9 +9829,9 @@
}
},
"node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
+ "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
"dev": true,
"engines": {
"node": ">=4"
@@ -10053,9 +10098,9 @@
}
},
"node_modules/vite-node": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.2.1.tgz",
- "integrity": "sha512-fNzHmQUSOY+y30naohBvSW7pPn/xn3Ib/uqm+5wAJQJiqQsU0NBR78XdRJb04l4bOFKjpTWld0XAfkKlrDbySg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz",
+ "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -10074,10 +10119,585 @@
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/vite-node/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz",
+ "integrity": "sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.20.0.tgz",
+ "integrity": "sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.20.0.tgz",
+ "integrity": "sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.20.0.tgz",
+ "integrity": "sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.20.0.tgz",
+ "integrity": "sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.20.0.tgz",
+ "integrity": "sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.20.0.tgz",
+ "integrity": "sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.20.0.tgz",
+ "integrity": "sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.20.0.tgz",
+ "integrity": "sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.20.0.tgz",
+ "integrity": "sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.20.0.tgz",
+ "integrity": "sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.20.0.tgz",
+ "integrity": "sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/vite-node/node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.20.0.tgz",
+ "integrity": "sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/vite-node/node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
"node_modules/vite-node/node_modules/rollup": {
- "version": "4.13.0",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz",
- "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==",
+ "version": "4.20.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz",
+ "integrity": "sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -10090,30 +10710,33 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.13.0",
- "@rollup/rollup-android-arm64": "4.13.0",
- "@rollup/rollup-darwin-arm64": "4.13.0",
- "@rollup/rollup-darwin-x64": "4.13.0",
- "@rollup/rollup-linux-arm-gnueabihf": "4.13.0",
- "@rollup/rollup-linux-arm64-gnu": "4.13.0",
- "@rollup/rollup-linux-arm64-musl": "4.13.0",
- "@rollup/rollup-linux-riscv64-gnu": "4.13.0",
- "@rollup/rollup-linux-x64-gnu": "4.13.0",
- "@rollup/rollup-linux-x64-musl": "4.13.0",
- "@rollup/rollup-win32-arm64-msvc": "4.13.0",
- "@rollup/rollup-win32-ia32-msvc": "4.13.0",
- "@rollup/rollup-win32-x64-msvc": "4.13.0",
+ "@rollup/rollup-android-arm-eabi": "4.20.0",
+ "@rollup/rollup-android-arm64": "4.20.0",
+ "@rollup/rollup-darwin-arm64": "4.20.0",
+ "@rollup/rollup-darwin-x64": "4.20.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.20.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.20.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.20.0",
+ "@rollup/rollup-linux-arm64-musl": "4.20.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.20.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.20.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.20.0",
+ "@rollup/rollup-linux-x64-gnu": "4.20.0",
+ "@rollup/rollup-linux-x64-musl": "4.20.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.20.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.20.0",
+ "@rollup/rollup-win32-x64-msvc": "4.20.0",
"fsevents": "~2.3.2"
}
},
"node_modules/vite-node/node_modules/vite": {
- "version": "5.2.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
- "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
+ "version": "5.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz",
+ "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==",
"dev": true,
"dependencies": {
- "esbuild": "^0.20.1",
- "postcss": "^8.4.38",
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.39",
"rollup": "^4.13.0"
},
"bin": {
@@ -10565,18 +11188,17 @@
}
},
"node_modules/vitest": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.2.1.tgz",
- "integrity": "sha512-TRph8N8rnSDa5M2wKWJCMnztCZS9cDcgVTQ6tsTFTG/odHJ4l5yNVqvbeDJYJRZ6is3uxaEpFs8LL6QM+YFSdA==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz",
+ "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==",
"dev": true,
"dependencies": {
- "@vitest/expect": "1.2.1",
- "@vitest/runner": "1.2.1",
- "@vitest/snapshot": "1.2.1",
- "@vitest/spy": "1.2.1",
- "@vitest/utils": "1.2.1",
+ "@vitest/expect": "1.6.0",
+ "@vitest/runner": "1.6.0",
+ "@vitest/snapshot": "1.6.0",
+ "@vitest/spy": "1.6.0",
+ "@vitest/utils": "1.6.0",
"acorn-walk": "^8.3.2",
- "cac": "^6.7.14",
"chai": "^4.3.10",
"debug": "^4.3.4",
"execa": "^8.0.1",
@@ -10585,11 +11207,11 @@
"pathe": "^1.1.1",
"picocolors": "^1.0.0",
"std-env": "^3.5.0",
- "strip-literal": "^1.3.0",
+ "strip-literal": "^2.0.0",
"tinybench": "^2.5.1",
- "tinypool": "^0.8.1",
+ "tinypool": "^0.8.3",
"vite": "^5.0.0",
- "vite-node": "1.2.1",
+ "vite-node": "1.6.0",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -10604,8 +11226,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "^1.0.0",
- "@vitest/ui": "^1.0.0",
+ "@vitest/browser": "1.6.0",
+ "@vitest/ui": "1.6.0",
"happy-dom": "*",
"jsdom": "*"
},
@@ -11021,9 +11643,9 @@
"dev": true
},
"node_modules/ws": {
- "version": "8.14.2",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
- "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"dev": true,
"engines": {
"node": ">=10.0.0"
diff --git a/package.json b/package.json
index ab9f26393..15b8849de 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"ts-node": "^10.8.1",
"typescript": "^5",
"vite": "^4",
- "vitest": "^1.0.0"
+ "vitest": "^1.4.0"
},
"volta": {
"node": "20.9.0"
diff --git a/src/lib/components/ScriptureViewSofria.svelte b/src/lib/components/ScriptureViewSofria.svelte
index d30079740..72bd026df 100644
--- a/src/lib/components/ScriptureViewSofria.svelte
+++ b/src/lib/components/ScriptureViewSofria.svelte
@@ -39,6 +39,7 @@ LOGGING:
export let bodyFontSize: any;
export let bodyLineHeight: any;
export let bookmarks: any;
+ export let direction: string;
export let notes: any;
export let highlights: any;
export let maxSelections: any;
@@ -1250,8 +1251,11 @@ LOGGING:
const refText = generateHTML(text, 'header-ref');
spanV.innerHTML = refText;
if (workspace.phraseDiv === null) {
- workspace.phraseDiv = startPhrase(workspace, 'keep');
- }
+ workspace.phraseDiv = startPhrase(
+ workspace,
+ 'keep'
+ );
+ }
workspace.phraseDiv.appendChild(spanV);
} else {
addText(workspace, text);
@@ -1896,9 +1900,6 @@ LOGGING:
$: versePerLine = verseLayout === 'one-per-line';
/**list of books in current docSet*/
$: books = $refs.catalog.documents;
- $: direction = config.bookCollections.find((x) => x.id === references.collection).style
- .textDirection;
-
$: (() => {
performance.mark('query-start');
const bookHasIntroduction = books.find((x) => x.bookCode === currentBook).hasIntroduction;
diff --git a/src/lib/components/StorybookImage.svelte b/src/lib/components/StorybookImage.svelte
new file mode 100644
index 000000000..2814dd9ba
--- /dev/null
+++ b/src/lib/components/StorybookImage.svelte
@@ -0,0 +1,21 @@
+
+
+{#if image}
+
+{/if}
diff --git a/src/lib/components/StorybookText.svelte b/src/lib/components/StorybookText.svelte
new file mode 100644
index 000000000..d9ea6349d
--- /dev/null
+++ b/src/lib/components/StorybookText.svelte
@@ -0,0 +1,42 @@
+
+
+{#await loadSofria(references)}
+
+{:then sofria}
+