Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 22 additions & 152 deletions src/lib/components/LexiconEntryView.svelte
Original file line number Diff line number Diff line change
@@ -1,146 +1,9 @@
<script>
import config from '$lib/data/config';
import { lexicon } from '$lib/data/lexicon.svelte';
import { convertStyle } from '$lib/data/stores';
import { initializeDatabase } from '$lib/data/stores/lexicon';
import {
selectedLanguageStore,
vernacularLanguageStore,
vernacularWordsStore
} from '$lib/data/stores/lexicon.ts';
import { afterUpdate, onMount } from 'svelte';
import { get } from 'svelte/store';
export let wordIds;
export let onSelectWord;
export let removeNewLines = false;
let xmlData = '';
async function queryXmlByWordId(wordIds) {
try {
let db = await initializeDatabase({ fetch });
let results;
const dynamicQuery = wordIds.map(() => `id = ?`).join(' OR ');
const dynamicParams = wordIds.map((id) => id);
results = db.exec(`SELECT xml FROM entries WHERE ${dynamicQuery}`, dynamicParams);
console.log('results:', results[0].values);
return results[0].values;
} catch (error) {
console.error(`Error querying XML for word IDs ${wordIds}:`, error);
return null;
}
}
function formatXmlByClass(xmlString) {
if (!xmlString) return '';
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');
const parseError = xmlDoc.querySelector('parsererror');
if (parseError) {
console.error('XML parsing error:', parseError.textContent);
return `<span class="text-error" style="background-color: var(--BackgroundColor);">Error parsing XML: Invalid format</span>`;
}
function processNode(node, parentHasSenseNumber = false) {
let output = '';
if (node.nodeType === Node.TEXT_NODE) {
return node.nodeValue.trim() ? node.nodeValue + ' ' : '';
}
if (node.nodeType === Node.ELEMENT_NODE) {
let className = node.getAttribute('class') || '';
let isSenseNumber = className.includes('sensenumber');
let parentContainsSenseNumber =
parentHasSenseNumber ||
[...node.parentNode.children].some(
(child) =>
child.getAttribute &&
(child.getAttribute('class') || '').includes('sensenumber')
);
const addStyle =
node.tagName === 'span' ||
className === 'clickable cursor-pointer' ||
(node.tagName === 'div' && className === 'entry');
if (node.tagName === 'a' && node.hasAttribute('href')) {
const href = node.getAttribute('href');
const match = href.match(/E-(\d+)/);
if (match) {
const index = parseInt(match[1], 10);
const wordObject = get(vernacularWordsStore).find(
(item) => item.id === index
);
const word = wordObject ? wordObject.name : 'Unknown';
const homonymIndex = wordObject ? wordObject.homonym_index : 1;
let linkText = node.textContent.trim();
if (linkText === String(homonymIndex)) {
linkText = homonymIndex.toString();
}
output += `<span class="clickable cursor-pointer" style="background-color: var(--BackgroundColor);" data-word="${word}" data-index="${index}" data-homonym="${homonymIndex}">${linkText}</span>`;
}
} else {
output += `<${node.tagName}`;
for (let attr of node.attributes) {
output += ` ${attr.name}="${attr.value}"`;
}
// Add appropriate styling based on class name
if (className.includes('sensenumber')) {
output += ` style="color: var(--TextColor); font-weight: bold;"`;
} else if (className.includes('vernacular')) {
output += ` style="color: var(--TextColor2);"`;
} else if (className.includes('example')) {
output += ` style="color: var(--TextColor3); font-style: italic;"`;
} else if (className.includes('definition')) {
output += ` style="color: var(--TextColor); font-weight: normal;"`;
}
if (addStyle) {
output += ` style="background-color: var(--BackgroundColor); color: var(--TextColor);"`;
}
output += '>';
for (let child of node.childNodes) {
output += processNode(child, parentContainsSenseNumber || isSenseNumber);
}
output += `</${node.tagName}>`;
}
}
return output;
}
return processNode(xmlDoc.documentElement);
}
async function updateXmlData() {
if (!wordIds) {
xmlData = '';
return;
}
let xmlResults = await queryXmlByWordId(wordIds);
// Insert an `<hr>` tag or a visible separator between entries
xmlData =
xmlResults
.filter((xml) => xml) // Ensure no null values are included
.map(formatXmlByClass)
.join('\n<hr style="border-color: var(--SettingsSeparatorColor);">\n') +
'\n<hr style="border-color: var(--SettingsSeparatorColor);">\n';
}
let { wordIds, onSelectWord, removeNewLines = false } = $props();
function attachEventListeners() {
const spans = document.querySelectorAll('.clickable');
Expand All @@ -153,7 +16,7 @@
const freshSpans = document.querySelectorAll('.clickable');
freshSpans.forEach((span) => {
span.addEventListener('click', () => {
selectedLanguageStore.set(get(vernacularLanguageStore));
lexicon.setLanguage();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing parameter in lexicon.setLanguage() call

The lexicon.setLanguage() method is called without any parameters. Based on the context, it should likely receive the language from the clicked element.

Consider passing the appropriate language parameter:

-                lexicon.setLanguage();
+                const language = span.getAttribute('data-language');
+                if (language) lexicon.setLanguage(language);

If the setLanguage method doesn't require parameters, please verify its implementation in the lexicon store.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/lib/components/LexiconEntryView.svelte at line 19, the call to
lexicon.setLanguage() is missing a required language parameter. Update the call
to pass the language value obtained from the clicked element or relevant
context. If setLanguage does not require parameters, verify its implementation
in the lexicon store to confirm and adjust usage accordingly.

const word = span.getAttribute('data-word');
const index = parseInt(span.getAttribute('data-index'), 10);
const homonym_index = parseInt(span.getAttribute('data-homonym'), 10);
Expand Down Expand Up @@ -195,7 +58,9 @@
.replace(/margin-left:\s*4em;?/g, '')
.trim();
if (cleaned && !cleaned.endsWith(';')) cleaned += ';';
if (cleaned && !cleaned.endsWith(';')) {
cleaned += ';';
}
cleaned += ' margin-left: -1.1em;';
style = cleaned;
Expand All @@ -209,17 +74,22 @@
});
}
onMount(updateXmlData);
let xmlData = $derived(lexicon.data());
$: if (wordIds) {
(async () => {
await updateXmlData();
applyStyles();
attachEventListeners();
})();
}
const updateDOM = (_element) => {
applyStyles();
attachEventListeners();
};
</script>

<pre
class="p-4 whitespace-pre-wrap break-words"
style="background-color: var(--BackgroundColor); color: var(--TextColor);">{@html xmlData}</pre>
{#await lexicon.search(wordIds) then}
<!-- prettier-ignore-attribute -->
<pre
class="p-4 whitespace-pre-wrap break-words"
style="background-color: var(--BackgroundColor); color: var(--TextColor);">

<div {@attach updateDOM}>
{@html xmlData}
</div>
</pre>
{/await}
13 changes: 5 additions & 8 deletions src/lib/components/LexiconLanguageTabs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@
import { expoInOut } from 'svelte/easing';
import { fly } from 'svelte/transition';

export let reversalLanguage;
export let selectedLanguage;
export let onSwitchLanguage;
export let vernacularLanguage;
let { reversalLanguage, selectedLanguage, onSwitchLanguage, vernacularLanguage } = $props();
</script>

<div class="flex w-full" style="background-color: var(--TabBackgroundColor);">
<div
role="button"
tabindex="0"
aria-pressed={selectedLanguage === vernacularLanguage}
on:click={() => onSwitchLanguage(vernacularLanguage)}
on:keydown={(e) => e.key === 'Enter' && onSwitchLanguage(vernacularLanguage)}
onclick={() => onSwitchLanguage(vernacularLanguage)}
onkeydown={(e) => e.key === 'Enter' && onSwitchLanguage(vernacularLanguage)}
class="py-2.5 px-3.5 text-sm uppercase text-center relative dy-tabs dy-tabs-bordered mb-1"
>
{vernacularLanguage}
Expand All @@ -29,8 +26,8 @@
role="button"
tabindex="0"
aria-pressed={selectedLanguage === reversalLanguage}
on:click={() => onSwitchLanguage(reversalLanguage)}
on:keydown={(e) => e.key === 'Enter' && onSwitchLanguage(reversalLanguage)}
onclick={() => onSwitchLanguage(reversalLanguage)}
onkeydown={(e) => e.key === 'Enter' && onSwitchLanguage(reversalLanguage)}
class="py-2.5 px-3.5 text-sm uppercase text-center relative dy-tabs dy-tabs-bordered mb-1"
>
{reversalLanguage}
Expand Down
14 changes: 8 additions & 6 deletions src/lib/components/LexiconListViewHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
import LexiconAlphabetStrip from './LexiconAlphabetStrip.svelte';
import LexiconLanguageTabs from './LexiconLanguageTabs.svelte';

export let alphabet = [];
export let selectedLanguage;
export let vernacularLanguage;
export let reversalLanguage;
export let onSwitchLanguage;
export let onLetterChange;
let {
alphabet,
selectedLanguage,
vernacularLanguage,
reversalLanguage,
onSwitchLanguage,
onLetterChange
} = $props();

async function handleLetterSelect(letter) {
onLetterChange(letter);
Expand Down
35 changes: 0 additions & 35 deletions src/lib/components/LexiconReversalListView.svelte

This file was deleted.

35 changes: 0 additions & 35 deletions src/lib/components/LexiconVernacularListView.svelte

This file was deleted.

1 change: 0 additions & 1 deletion src/lib/components/TextSelectionToolbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ TODO:
let showHighlightPens = $state(false);

let { oncopy } = $props();

const isCopyEnabled = $derived(
config.bookCollections.find((x) => x.id === $refs.collection).features['bc-allow-copy-text']
);
Expand Down
Loading
Loading