Skip to content

Commit

Permalink
Feature: Reference Parsing (#391)
Browse files Browse the repository at this point in the history
* Implement Footnote Reference Parsing

* Develop utilities for parsing in text references and generating
  respective HTML content.
* Develop tests to evaluate effectiveneess of developed functions
* Develop footnote content display component with stack functionality.

* Fix Tests

- Fix expected phrases that would have failed when encountering non
  standard separators.

* Adjust tests to be of  BDD-style Given/When/Then syntax

* README.md

* format

* package-lock.json
  • Loading branch information
jakedcolbert authored Nov 13, 2023
1 parent bad0407 commit 3b3a517
Show file tree
Hide file tree
Showing 12 changed files with 987 additions and 26 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ jobs:
- name: Build
run: |
npm run build:examples
- name: Test
run: |
npm run test
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ Run `npm run build:examples` to build an app with the example data.
The production build can be viewed by running `npm run preview`.
The production build can be deployed to a public webserver for testing using [Surge](https://surge.sh).

### Testing

Scripture App Builder PWA uses [Vitest](https://vitest.dev/guide/) for unit tests. See that added test files and tests adhere to the [Front End Testing Style Guide](https://github.com/nikeshghimire77/unit-testing-styleguide).

```bash
├── scripts
│   ├── scripture-reference-utils.test.ts
│   └── scripture-reference-utils.ts
```

Run `npm test` to run created test files.

### Deployment

This project is configured by default with the static adaptor, which will allow deployment on any platform that requires a static site.
491 changes: 490 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"convert:examples": "ts-node scripts/index.ts --examples",
"clean": "rimraf .svelte-kit build src/lib/data/book-collections src/config.js static/about.partial.html static/collections static/images static/fonts static/styles static/illustrations static/audio static/timings static/backgrounds static/icons static/borders static/manifest.json && echo 🔔 Reminder: The project cannot be built until the conversion scripts are run again.",
"clean:data": "rimraf --glob data/*",
"clean:all": "npm run clean && npm run clean:data"
"clean:all": "npm run clean && npm run clean:data",
"test": "vitest"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
Expand Down Expand Up @@ -57,7 +58,8 @@
"tailwindcss": "^3.3",
"ts-node": "^10.8.1",
"typescript": "^5",
"vite": "^4"
"vite": "^4",
"vitest": "^0.34.1"
},
"volta": {
"node": "20.9.0"
Expand Down
10 changes: 10 additions & 0 deletions src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,28 @@ declare namespace App {
// interface Platform {}
// interface Session {}
// interface Stuff {}

interface Reference {
docSet: string;
book: string;
chapter: string;
verse: string;
}

interface Paragraph {
[key: number]: {
[key: string]: string;
};
}

interface BibleText {
title: string;
book: string;
chapter: string;
bookmark: string;
paragraphs: Paragraph[];
}

interface Highlight {
id: string;
reference: string;
Expand Down
13 changes: 10 additions & 3 deletions src/lib/components/ScriptureViewSofria.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ TODO:
import { catalog } from '$lib/data/catalog';
import config from '$lib/data/config';
import { footnotes } from '$lib/data/stores';
import { generateHTML } from '$lib/scripts/scripture-reference-utils';
import {
onClickText,
deselectAllElements,
Expand Down Expand Up @@ -191,9 +192,14 @@ TODO:
};
const usfmSpan = (parent: any, spanClass: string, phrase: string) => {
const spanElement = document.createElement('span');
let child;
spanElement.classList.add(spanClass);
const textNode = document.createTextNode(phrase);
spanElement.appendChild(textNode);
if (spanClass === 'xt') {
spanElement.innerHTML = generateHTML(phrase);
} else {
child = document.createTextNode(phrase);
spanElement.appendChild(child);
}
parent.appendChild(spanElement);
return parent;
};
Expand Down Expand Up @@ -277,7 +283,8 @@ TODO:
event.stopPropagation();
const root = event.target.parentNode.parentNode;
const footnote = root.querySelector(`div#${root.getAttribute('data-graft')}`);
footnotes.push(footnote.innerHTML);
const parsed = footnote.innerHTML;
footnotes.push(parsed);
}
}
Expand Down
66 changes: 63 additions & 3 deletions src/lib/components/StackView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,75 @@
-->

<script>
import { footnotes } from '$lib/data/stores';
import { footnotes, getVerseText, refs, themeColors } from '$lib/data/stores';
import config from '$lib/data/config';
let stack;
let listening = false;
$: PrimaryColor = $themeColors['PrimaryColor'];
function clickOutside(event) {
if (!stack.contains(event.target)) {
footnotes.pop();
}
}
function navigate(reference) {
refs.set({
docSet: reference.docSet,
book: reference.book,
chapter: reference.chapter
});
footnotes.reset();
}
const openInNewIcon = () => {
return `<svg fill='${PrimaryColor}' xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"/></svg>`;
};
async function insideClick(event) {
if (event.target.hasAttribute('data-start-ref')) {
let start = JSON.parse(event.target.getAttribute('data-start-ref'));
let end =
event.target.getAttribute('data-end-ref') === 'undefined'
? undefined
: JSON.parse(event.target.getAttribute('data-end-ref'));
if (config.mainFeatures['scripture-refs-display-from-popup'] === 'viewer') {
navigate(start);
} else {
const root = document.createElement('div');
const textDiv = document.createElement('div');
const iconDiv = document.createElement('div');
iconDiv.id = 'icon';
const referenceSpan = document.createElement('span');
const footnoteSpan = document.createElement('span');
const icon = document.createElement('button');
root.classList.add('flex', 'flex-row', 'justify-space-between');
referenceSpan.classList.add('fr');
footnoteSpan.classList.add('ft');
icon.setAttribute('reference', JSON.stringify(start));
icon.classList.add('p-2');
icon.innerHTML = openInNewIcon();
referenceSpan.innerText = `${start.phrase} `;
console.log(start, end);
footnoteSpan.innerText = await getVerseText(start, end);
textDiv.appendChild(referenceSpan);
textDiv.appendChild(footnoteSpan);
iconDiv.appendChild(icon);
root.appendChild(textDiv);
root.appendChild(iconDiv);
footnotes.push(root.outerHTML);
}
// will not work since it does not have a reference to the start object...
} else if (document.getElementById('icon').contains(event.target)) {
let start = JSON.parse(
document.getElementById('icon').firstChild.getAttribute('reference')
);
navigate(start);
}
}
function toggleListener(footnotes) {
if (listening && footnotes.length === 0) {
document.removeEventListener('click', clickOutside);
Expand All @@ -31,11 +89,13 @@
ToDo:
- make width of scripture view
-->
<div bind:this={stack} class="absolute w-full bottom-8 dy-stack">
<div bind:this={stack} class="absolute max-w-screen-md w-5/6 bottom-8 dy-stack">
{#each $footnotes as item}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
id="container"
class="footnote rounded w-1/2 lg:max-w-screen-md h-40 drop-shadow-lg overflow-y-auto"
class="footnote rounded h-40 drop-shadow-lg overflow-y-auto"
on:click|stopPropagation={insideClick}
>
<div id="container" class="footnote">{@html item}</div>
</div>
Expand Down
44 changes: 28 additions & 16 deletions src/lib/data/stores/scripture.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ function createStack() {
},
pop: () => {
external.set(get(external).slice(1));
},
reset: () => {
external.set([]);
}
};
}
Expand Down Expand Up @@ -86,27 +89,36 @@ export function getReference(item) {
return bookName + ' ' + item.chapter + separator + item.verse;
}

export async function getVerseText(item) {
export async function getVerseText(item, item2 = undefined) {
const proskomma = get(pk);
const scriptureCV = `${item.chapter}:${item.verse}`;
const scriptureCV =
item2 !== undefined
? item.chapter === item2.chapter
? `${item.chapter}:${item.verse}-${item2.verse}`
: `${item.chapter}:${item.verse}-${item2.chapter}:${item2.verse}`
: `${item.chapter}:${item.verse}`;
console.log('getVerseText', scriptureCV);
const query = `{
docSet (id: "${item.docSet}") {
document(bookCode:"${item.book}") {
mainSequence {
blocks(withScriptureCV: "${scriptureCV}") {
text(withScriptureCV: "${scriptureCV}" normalizeSpace:true )
}
}
}
}
}`;
docSet (id: "${item.docSet}") {
document(bookCode:"${item.book}") {
mainSequence {
blocks(withScriptureCV: "${scriptureCV}") {
text(withScriptureCV: "${scriptureCV}" normalizeSpace:true )
}
}
}
}
}`;
console.log(query);

const { data } = await proskomma.gqlQuery(query);
const block = data.docSet.document.mainSequence.blocks[0];
if (block === null) {
return '';
let text = [];
for (const block of data.docSet.document.mainSequence.blocks) {
if (block.text) {
text.push(block.text);
}
}
return block.text;
return text.join(' ');
}

export const currentFont = writable(config.fonts[0].family);
Expand Down
Loading

0 comments on commit 3b3a517

Please sign in to comment.