From 8eb4d3833de1fbc7f14bfe7a419367b8fbbd61dd Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 19 Jan 2023 13:55:08 +0700 Subject: [PATCH 1/8] fix: SFM Chapter markers for styling SFM changes: * Use `\toc1` instead of `\toc` * Write paragraph marker after chapter markers so Paratext will style Ch1 correctly. --- src/sfm.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sfm.ts b/src/sfm.ts index 15add71..59b0169 100644 --- a/src/sfm.ts +++ b/src/sfm.ts @@ -34,6 +34,7 @@ export function convertToSFM(bookObj: books.objType, s: sfmConsole.SFMConsole) chapters.forEach(function(chapter) { if(chapter.number != 0){ + // Chapter markers must be followed by paragraph marker for styling in Paratext SFMtext += CHAPTER_MARKER + chapter.number + CRLF; if (chapter.number == 1) { // For Chapter 1, marker must be followed by paragraph marker for styling in Paratext From 2825b7ab8514ec5e8e068b90757554986f55f18f Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 19 Jan 2023 16:19:46 +0700 Subject: [PATCH 2/8] fix: Only add \p on chapter 1 --- src/sfm.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sfm.ts b/src/sfm.ts index 59b0169..15add71 100644 --- a/src/sfm.ts +++ b/src/sfm.ts @@ -34,7 +34,6 @@ export function convertToSFM(bookObj: books.objType, s: sfmConsole.SFMConsole) chapters.forEach(function(chapter) { if(chapter.number != 0){ - // Chapter markers must be followed by paragraph marker for styling in Paratext SFMtext += CHAPTER_MARKER + chapter.number + CRLF; if (chapter.number == 1) { // For Chapter 1, marker must be followed by paragraph marker for styling in Paratext From df94add1437cef01e82f55b898df6af75897b7da Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 02:46:54 +0700 Subject: [PATCH 3/8] chore: export toolbox regex patterns --- src/toolbox.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/toolbox.ts b/src/toolbox.ts index 0fc733d..76065a9 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -45,6 +45,24 @@ export type markerType = "\\ref" | "\\t" ; +/** + * Regex to parse all the variations of \vs marker (along with all the optional punctuation marks) + * \vs (section title) + * \vs (section heading) + * \vs (13-14) b + * \vs [13-14] b + * TODO: \vs 13-14 (b) + */ +export const VS_PATTERN = /\\vs\s+\*?(\d+|\(?section title\)?|\(?section heading\)?|\(\d+-\d+\)|\[\d+-\d+\])\s?([a-z])?\??.*/; + +/** + * Regex to parse all the variations of verse bridges to extract verse ranges + * (13-14) + * [13-14] + * 13-14 + */ +export const VS_BRIDGE_PATTERN = /(\(|\[)(\d+)-(\d+)(\)|\])/; + /** * Information about the Toolbox text file based on the filename */ @@ -220,16 +238,13 @@ export function updateObj(bookObj: books.objType, file: string, currentChapter: let vs_section_header = false, vs_verse_bridge = false, vs_other = false; let bridgeStart = verseNum, bridgeEnd = verseNum; // Start and end of a verse bridge if (marker == '\\vs') { - const vsPattern = /\\vs\s+\*?(\d+|\(?section title\)?|\(?section heading\)?|\(\d+-\d+\)|\[\d+-\d+\])\s?([a-z])?\??.*/; - const vsPatternMatch = line.trim().match(vsPattern); + const vsPatternMatch = line.trim().match(VS_PATTERN); if(vsPatternMatch){ if(vsPatternMatch[1].includes('section')) { vs_section_header = true; } else if (vsPatternMatch[1].includes('-')) { vs_verse_bridge = true; - // Verse bridge could be marked with (x-y) or [x-y] - const vsBridgePattern = /(\(|\[)(\d+)-(\d+)(\)|\])/; - const vsBridgeMatch = vsPatternMatch[1].match(vsBridgePattern); + const vsBridgeMatch = vsPatternMatch[1].match(VS_BRIDGE_PATTERN); if (vsBridgeMatch) { // Determine the start and end of the verse bridge if (vsBridgeMatch[2]) { From e48b8ee8431853b8a06291ea529a6abf65641e85 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 02:47:55 +0700 Subject: [PATCH 4/8] test: Add regex tests * Also make parens optional in VS_BRIDGE_PATTERN --- src/toolbox.ts | 2 +- test/toolbox.test.ts | 108 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 test/toolbox.test.ts diff --git a/src/toolbox.ts b/src/toolbox.ts index 76065a9..e249e3e 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -61,7 +61,7 @@ export const VS_PATTERN = /\\vs\s+\*?(\d+|\(?section title\)?|\(?section heading * [13-14] * 13-14 */ -export const VS_BRIDGE_PATTERN = /(\(|\[)(\d+)-(\d+)(\)|\])/; +export const VS_BRIDGE_PATTERN = /(\(|\[)?(\d+)-(\d+)(\)|\])?/; /** * Information about the Toolbox text file based on the filename diff --git a/test/toolbox.test.ts b/test/toolbox.test.ts new file mode 100644 index 0000000..c06b949 --- /dev/null +++ b/test/toolbox.test.ts @@ -0,0 +1,108 @@ +// Copyright 2023 SIL International +// Trivial unit test for testing toolbox.ts regex +import test from 'ava'; + +import { VS_PATTERN, VS_BRIDGE_PATTERN } from '../dist/toolbox' + + +/* + * VS_PATTERN tests + * \vs (section title) + * \vs (section heading) + * \vs (13-14) b + * \vs [13-14] b + * TODO: \vs 13-14 (b) + */ + +test('VS_PATTERN for section title/heading', t => { + let line = "\\vs (section title)"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs (section title?)"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs (section title) [?]"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs (section heading)"; + t.regex(line.trim(), VS_PATTERN, "line matches"); +}); + +// These do not match +test('VS_PATTERN for ?', t => { + let line = "\\vs ?"; + t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); + + line = "\\vs ? (none)"; + t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); +}); + +test('VS_PATTERN for verse', t => { + let line = "\\vs 9"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 9?" + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 8b [not in draft produced at workshop. do we want to keep this?]"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 9a"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 9a?"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 14"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 14b"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 22b(?)"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + +}); + +test('VS_PATTERN for verse bridge', t => { + let line = "\\vs (13-14) b"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs [13-14] b"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs 13c-14a"; + t.regex(line.trim(), VS_PATTERN, "line matches"); + + line = "\\vs this should not match"; + t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); +}) + + +/** + * VS_BRIDGE_PATTERN + */ +test('VS_BRIDGE_PATTERN for verse ranges', t => { + let line = "(13-14)"; + t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + + line = "[13-14]"; + t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + + line = "13-14"; + t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + let vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); + + /* TODO: validate verse range + t.assert(vsBridgeMatch, 'bridge matches'); + t.is(vsBridgeMatch[2], "13"); + t.is(vsBridgeMatch[3], "14"); + */ + + line = "13-14a"; + t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + + line = "13a-14b"; + t.notRegex(line.trim(), VS_BRIDGE_PATTERN, "line fails to match but should (TODO)"); + vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); +}) From 67b910e3309e28e6085d8fb546d6b2e49dcdcb00 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 03:18:08 +0700 Subject: [PATCH 5/8] chore: clean up message strings --- test/toolbox.test.ts | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/test/toolbox.test.ts b/test/toolbox.test.ts index c06b949..f6a3317 100644 --- a/test/toolbox.test.ts +++ b/test/toolbox.test.ts @@ -16,66 +16,66 @@ import { VS_PATTERN, VS_BRIDGE_PATTERN } from '../dist/toolbox' test('VS_PATTERN for section title/heading', t => { let line = "\\vs (section title)"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "(section title) matches"); line = "\\vs (section title?)"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "(section title?) matches"); line = "\\vs (section title) [?]"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "(section title) [?] matches"); line = "\\vs (section heading)"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "(section heading) matches"); }); // These do not match test('VS_PATTERN for ?', t => { let line = "\\vs ?"; - t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); + t.notRegex(line.trim(), VS_PATTERN, "? fails to match"); line = "\\vs ? (none)"; - t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); + t.notRegex(line.trim(), VS_PATTERN, "? (none) fails to match"); }); test('VS_PATTERN for verse', t => { let line = "\\vs 9"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "vs 9 matches"); line = "\\vs 9?" - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "9? matches"); line = "\\vs 8b [not in draft produced at workshop. do we want to keep this?]"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "long line matches"); line = "\\vs 9a"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "9a matches"); line = "\\vs 9a?"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "9a? matches"); line = "\\vs 14"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "14 matches"); line = "\\vs 14b"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "14b matches"); line = "\\vs 22b(?)"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "22b(?) matches"); }); test('VS_PATTERN for verse bridge', t => { let line = "\\vs (13-14) b"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "(13-14) b matches"); line = "\\vs [13-14] b"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "[13-14] b matches"); line = "\\vs 13c-14a"; - t.regex(line.trim(), VS_PATTERN, "line matches"); + t.regex(line.trim(), VS_PATTERN, "13c-14a matches"); line = "\\vs this should not match"; - t.notRegex(line.trim(), VS_PATTERN, "line fails to match"); + t.notRegex(line.trim(), VS_PATTERN, "this should not match"); }) @@ -84,25 +84,25 @@ test('VS_PATTERN for verse bridge', t => { */ test('VS_BRIDGE_PATTERN for verse ranges', t => { let line = "(13-14)"; - t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + t.regex(line.trim(), VS_BRIDGE_PATTERN, "(13-14) matches"); line = "[13-14]"; - t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + t.regex(line.trim(), VS_BRIDGE_PATTERN, "[13-14] matches"); line = "13-14"; - t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + t.regex(line.trim(), VS_BRIDGE_PATTERN, "13-14 matches"); let vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); - /* TODO: validate verse range - t.assert(vsBridgeMatch, 'bridge matches'); - t.is(vsBridgeMatch[2], "13"); - t.is(vsBridgeMatch[3], "14"); - */ + // validate verse range + /*t.truthy(vsBridgeMatch, 'bridge matches'); + t.truthy(vsBridgeMatch[2]); + t.is(vsBridgeMatch[2], "13", "bridge start matches");*/ + //t.deepEqual(vsBridgeMatch[3], "14", "bridge end matches"); line = "13-14a"; - t.regex(line.trim(), VS_BRIDGE_PATTERN, "line matches"); + t.regex(line.trim(), VS_BRIDGE_PATTERN, "13-14a matches"); line = "13a-14b"; - t.notRegex(line.trim(), VS_BRIDGE_PATTERN, "line fails to match but should (TODO)"); + t.notRegex(line.trim(), VS_BRIDGE_PATTERN, "13a-14b fails to match but should (TODO)"); vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); }) From 667fd1ffc76e0d618ae03e10f3428ef405453101 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 07:18:16 +0700 Subject: [PATCH 6/8] chore: Update Ava version from 5.1.0 to 5.1.1 --- package-lock.json | 44 +++++++++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51c25c0..759fce0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@types/node": "^18.11.16", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", - "ava": "^5.1.0", + "ava": "^5.1.1", "eslint": "^8.30.0", "nodemon": "^2.0.20", "pkg": "^5.8.0", @@ -673,9 +673,9 @@ } }, "node_modules/ava": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ava/-/ava-5.1.0.tgz", - "integrity": "sha512-e5VFrSQ0WBPyZJWRXVrO7RFOizFeNM0t2PORwrPvWtApgkORI6cvGnY3GX1G+lzpd0HjqNx5Jus22AhxVnUMNA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-5.1.1.tgz", + "integrity": "sha512-od1CWgWVIKZSdEc1dhQWhbsd6KBs0EYjek7eqZNGPvy+NyC9Q1bXixcadlgOXwDG9aM0zLMQZwRXfe9gMb1LQQ==", "dev": true, "dependencies": { "acorn": "^8.8.1", @@ -685,10 +685,10 @@ "arrify": "^3.0.0", "callsites": "^4.0.0", "cbor": "^8.1.0", - "chalk": "^5.1.2", + "chalk": "^5.2.0", "chokidar": "^3.5.3", "chunkd": "^2.0.1", - "ci-info": "^3.6.1", + "ci-info": "^3.7.1", "ci-parallel-vars": "^1.0.1", "clean-yaml-object": "^0.1.0", "cli-truncate": "^3.1.0", @@ -700,7 +700,7 @@ "del": "^7.0.0", "emittery": "^1.0.1", "figures": "^5.0.0", - "globby": "^13.1.2", + "globby": "^13.1.3", "ignore-by-default": "^2.1.0", "indent-string": "^5.0.0", "is-error": "^2.2.2", @@ -958,10 +958,16 @@ "dev": true }, "node_modules/ci-info": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", - "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { "node": ">=8" } @@ -5181,9 +5187,9 @@ "dev": true }, "ava": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ava/-/ava-5.1.0.tgz", - "integrity": "sha512-e5VFrSQ0WBPyZJWRXVrO7RFOizFeNM0t2PORwrPvWtApgkORI6cvGnY3GX1G+lzpd0HjqNx5Jus22AhxVnUMNA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-5.1.1.tgz", + "integrity": "sha512-od1CWgWVIKZSdEc1dhQWhbsd6KBs0EYjek7eqZNGPvy+NyC9Q1bXixcadlgOXwDG9aM0zLMQZwRXfe9gMb1LQQ==", "dev": true, "requires": { "acorn": "^8.8.1", @@ -5193,10 +5199,10 @@ "arrify": "^3.0.0", "callsites": "^4.0.0", "cbor": "^8.1.0", - "chalk": "^5.1.2", + "chalk": "^5.2.0", "chokidar": "^3.5.3", "chunkd": "^2.0.1", - "ci-info": "^3.6.1", + "ci-info": "^3.7.1", "ci-parallel-vars": "^1.0.1", "clean-yaml-object": "^0.1.0", "cli-truncate": "^3.1.0", @@ -5208,7 +5214,7 @@ "del": "^7.0.0", "emittery": "^1.0.1", "figures": "^5.0.0", - "globby": "^13.1.2", + "globby": "^13.1.3", "ignore-by-default": "^2.1.0", "indent-string": "^5.0.0", "is-error": "^2.2.2", @@ -5383,9 +5389,9 @@ "dev": true }, "ci-info": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", - "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", + "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", "dev": true }, "ci-parallel-vars": { diff --git a/package.json b/package.json index b5ce153..c3282a7 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@types/node": "^18.11.16", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", - "ava": "^5.1.0", + "ava": "^5.1.1", "eslint": "^8.30.0", "nodemon": "^2.0.20", "pkg": "^5.8.0", From c8f129f788feb3d650235e616504124ab733c840 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 07:45:50 +0700 Subject: [PATCH 7/8] fix: Update regex to handle additional verse bridge notation --- src/toolbox.ts | 7 ++++--- test/toolbox.test.ts | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/toolbox.ts b/src/toolbox.ts index e249e3e..46cf219 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -51,17 +51,18 @@ export type markerType = * \vs (section heading) * \vs (13-14) b * \vs [13-14] b - * TODO: \vs 13-14 (b) + * \vs 13-14 (b) */ -export const VS_PATTERN = /\\vs\s+\*?(\d+|\(?section title\)?|\(?section heading\)?|\(\d+-\d+\)|\[\d+-\d+\])\s?([a-z])?\??.*/; +export const VS_PATTERN = /\\vs\s+\*?(\d+|\(?section title\)?|\(?section heading\)?|\(\d+-\d+\)|\[\d+-\d+\]|\d+-\d+)\s?\(?([a-z])?\)?\??.*/; /** * Regex to parse all the variations of verse bridges to extract verse ranges * (13-14) * [13-14] * 13-14 + * 13a-14b */ -export const VS_BRIDGE_PATTERN = /(\(|\[)?(\d+)-(\d+)(\)|\])?/; +export const VS_BRIDGE_PATTERN = /(\(|\[)?(\d+)[a-z]?-(\d+)[a-z]?(\)|\])?/; /** * Information about the Toolbox text file based on the filename diff --git a/test/toolbox.test.ts b/test/toolbox.test.ts index f6a3317..d877d8b 100644 --- a/test/toolbox.test.ts +++ b/test/toolbox.test.ts @@ -11,7 +11,7 @@ import { VS_PATTERN, VS_BRIDGE_PATTERN } from '../dist/toolbox' * \vs (section heading) * \vs (13-14) b * \vs [13-14] b - * TODO: \vs 13-14 (b) + * \vs 13-14 (b) */ test('VS_PATTERN for section title/heading', t => { @@ -74,6 +74,9 @@ test('VS_PATTERN for verse bridge', t => { line = "\\vs 13c-14a"; t.regex(line.trim(), VS_PATTERN, "13c-14a matches"); + line = "\\vs 8-9 (b)"; + t.regex(line.trim(), VS_PATTERN, "8-9 (b) matches"); + line = "\\vs this should not match"; t.notRegex(line.trim(), VS_PATTERN, "this should not match"); }) @@ -94,15 +97,44 @@ test('VS_BRIDGE_PATTERN for verse ranges', t => { let vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); // validate verse range - /*t.truthy(vsBridgeMatch, 'bridge matches'); - t.truthy(vsBridgeMatch[2]); - t.is(vsBridgeMatch[2], "13", "bridge start matches");*/ - //t.deepEqual(vsBridgeMatch[3], "14", "bridge end matches"); + if (vsBridgeMatch) { + if (vsBridgeMatch[2]) { + t.is(vsBridgeMatch[2], "13", "bridge start matches"); + } + if (vsBridgeMatch[3]) { + t.is(vsBridgeMatch[3], "14", "bridge end matches"); + } + } + + line = "8-9 (b)"; + t.regex(line.trim(), VS_BRIDGE_PATTERN, "8-9 (b) matches"); + vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); + + // validate verse range + if (vsBridgeMatch) { + if (vsBridgeMatch[2]) { + t.is(vsBridgeMatch[2], "8", "bridge start matches"); + } + if (vsBridgeMatch[3]) { + t.is(vsBridgeMatch[3], "9", "bridge end matches"); + } + } line = "13-14a"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "13-14a matches"); line = "13a-14b"; - t.notRegex(line.trim(), VS_BRIDGE_PATTERN, "13a-14b fails to match but should (TODO)"); + t.regex(line.trim(), VS_BRIDGE_PATTERN, "13a-14b matches"); vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); + + // validate verse range + if (vsBridgeMatch) { + if (vsBridgeMatch[2]) { + t.is(vsBridgeMatch[2], "13", "bridge start matches"); + } + if (vsBridgeMatch[3]) { + t.is(vsBridgeMatch[3], "14", "bridge end matches"); + } + } + }) From 7a384c1ac063fca774c9c68cce94effd64da7b8c Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 20 Jan 2023 08:06:23 +0700 Subject: [PATCH 8/8] refactor: getVerseBridge to determine start and stop of verse bridges --- src/toolbox.ts | 55 +++++++++++++++++++++++++--------- test/toolbox.test.ts | 71 ++++++++++++++++++++++---------------------- 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/src/toolbox.ts b/src/toolbox.ts index 46cf219..e572fb0 100644 --- a/src/toolbox.ts +++ b/src/toolbox.ts @@ -46,6 +46,14 @@ export type markerType = "\\t" ; /** + * Verse start and end of a verse bridge + */ +export interface bridgeType { + start: number; + end: number; +} + + /** * Regex to parse all the variations of \vs marker (along with all the optional punctuation marks) * \vs (section title) * \vs (section heading) @@ -72,6 +80,30 @@ export interface fileInfoType { chapterNumber: number; } +/** + * Determine the start and stop of a verse bridge + * @param {string} line - \vs line containing a verse bridge + * @param {number} verseNum - current verse number + */ +export function getVerseBridge(line: string, verseNum: number) : bridgeType { + let bridge: bridgeType = { + start: verseNum, + end: verseNum + }; + const vsBridgeMatch = line.match(VS_BRIDGE_PATTERN); + if (vsBridgeMatch) { + // Determine the start and end of the verse bridge + if (vsBridgeMatch[2]) { + bridge.start = parseInt(vsBridgeMatch[2]); + } + if (vsBridgeMatch[3]) { + bridge.end = parseInt(vsBridgeMatch[3]); + } + } + + return bridge; +} + /** * Extract a book name and chapter number from the filename * @param {string} file - Path to the Toolbox text file @@ -237,7 +269,11 @@ export function updateObj(bookObj: books.objType, file: string, currentChapter: } // Determine if any other \\vs special processing needed let vs_section_header = false, vs_verse_bridge = false, vs_other = false; - let bridgeStart = verseNum, bridgeEnd = verseNum; // Start and end of a verse bridge + // Start and end of a verse bridge + let bridge : bridgeType = { + start: verseNum, + end: verseNum + } if (marker == '\\vs') { const vsPatternMatch = line.trim().match(VS_PATTERN); if(vsPatternMatch){ @@ -245,16 +281,7 @@ export function updateObj(bookObj: books.objType, file: string, currentChapter: vs_section_header = true; } else if (vsPatternMatch[1].includes('-')) { vs_verse_bridge = true; - const vsBridgeMatch = vsPatternMatch[1].match(VS_BRIDGE_PATTERN); - if (vsBridgeMatch) { - // Determine the start and end of the verse bridge - if (vsBridgeMatch[2]) { - bridgeStart = parseInt(vsBridgeMatch[2]); - } - if (vsBridgeMatch[3]) { - bridgeEnd = parseInt(vsBridgeMatch[3]); - } - } + bridge = getVerseBridge(vsPatternMatch[1], verseNum); } if (vsPatternMatch[2] && vsPatternMatch[2] != 'a') { vs_other = true; // verse #-other letter besides "a" @@ -342,17 +369,17 @@ export function updateObj(bookObj: books.objType, file: string, currentChapter: case 'INCREMENT_VERSE_NUM' : // Update verseNum to either after the end of a verse span, or increment //verseNum++ - verseNum = (vs_verse_bridge) ? bridgeEnd + 1 : verseNum + 1; + verseNum = (vs_verse_bridge) ? bridge.end + 1 : verseNum + 1; break; case 'MERGE_VERSES' : { // Complicated task of merging the previous two verses, and assigning number const lastVerse = bookObj.content[currentChapter].content.pop(); contentLength--; bookObj.content[currentChapter].content[contentLength - 1].text += lastVerse.text; - bookObj.content[currentChapter].content[contentLength - 1].number = (vs_verse_bridge) ? bridgeStart : verseNum-1; + bookObj.content[currentChapter].content[contentLength - 1].number = (vs_verse_bridge) ? bridge.start : verseNum-1; if (vs_verse_bridge) { - bookObj.content[currentChapter].content[contentLength - 1].bridgeEnd = bridgeEnd; + bookObj.content[currentChapter].content[contentLength - 1].bridgeEnd = bridge.end; } break; } diff --git a/test/toolbox.test.ts b/test/toolbox.test.ts index d877d8b..57ea3bc 100644 --- a/test/toolbox.test.ts +++ b/test/toolbox.test.ts @@ -2,7 +2,7 @@ // Trivial unit test for testing toolbox.ts regex import test from 'ava'; -import { VS_PATTERN, VS_BRIDGE_PATTERN } from '../dist/toolbox' +import { VS_PATTERN, VS_BRIDGE_PATTERN, bridgeType, getVerseBridge } from '../dist/toolbox' /* @@ -83,58 +83,59 @@ test('VS_PATTERN for verse bridge', t => { /** - * VS_BRIDGE_PATTERN + * Tests VS_BRIDGE_PATTERN matches and determining verse bridges */ test('VS_BRIDGE_PATTERN for verse ranges', t => { let line = "(13-14)"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "(13-14) matches"); + t.deepEqual(getVerseBridge(line, 13), + { + start: 13, + end: 14 + }, "bridge (13, 14)"); line = "[13-14]"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "[13-14] matches"); + t.deepEqual(getVerseBridge(line, 13), + { + start: 13, + end: 14 + }, "bridge [13, 14]"); line = "13-14"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "13-14 matches"); - let vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); - - // validate verse range - if (vsBridgeMatch) { - if (vsBridgeMatch[2]) { - t.is(vsBridgeMatch[2], "13", "bridge start matches"); - } - if (vsBridgeMatch[3]) { - t.is(vsBridgeMatch[3], "14", "bridge end matches"); - } - } + t.deepEqual(getVerseBridge(line, 13), + { + start: 13, + end: 14 + }, "bridge {13, 14}"); line = "8-9 (b)"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "8-9 (b) matches"); - vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); - - // validate verse range - if (vsBridgeMatch) { - if (vsBridgeMatch[2]) { - t.is(vsBridgeMatch[2], "8", "bridge start matches"); - } - if (vsBridgeMatch[3]) { - t.is(vsBridgeMatch[3], "9", "bridge end matches"); - } - } + t.deepEqual(getVerseBridge(line, 8), + { + start: 8, + end: 9 + }, "bridge 8-9 (b)"); line = "13-14a"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "13-14a matches"); line = "13a-14b"; t.regex(line.trim(), VS_BRIDGE_PATTERN, "13a-14b matches"); - vsBridgeMatch = line.trim().match(VS_BRIDGE_PATTERN); - - // validate verse range - if (vsBridgeMatch) { - if (vsBridgeMatch[2]) { - t.is(vsBridgeMatch[2], "13", "bridge start matches"); - } - if (vsBridgeMatch[3]) { - t.is(vsBridgeMatch[3], "14", "bridge end matches"); - } - } + t.deepEqual(getVerseBridge(line, 13), + { + start: 13, + end: 14 + }, "bridge 13a-14b"); + + // These do not match + line = "x15a-y21b"; + t.notRegex(line.trim(), VS_BRIDGE_PATTERN, "x15a-y21b does not match"); + t.deepEqual(getVerseBridge(line, 15), + { + start: 15, + end: 15 + }, "bridge x15a-y21b"); })