widetorah-embed 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/embed.esm.js +39 -0
- package/dist/embed.min.js +36 -36
- package/package.json +1 -1
package/dist/embed.esm.js
CHANGED
|
@@ -518,6 +518,31 @@ function bindCopyButton(btn, text) {
|
|
|
518
518
|
});
|
|
519
519
|
}
|
|
520
520
|
|
|
521
|
+
// src/rich-snippets.ts
|
|
522
|
+
function injectQuotation(data, domain, siteName) {
|
|
523
|
+
if (document.querySelector("script[data-wide-snippet]")) return;
|
|
524
|
+
const jsonLd = {
|
|
525
|
+
"@context": "https://schema.org",
|
|
526
|
+
"@type": "Quotation",
|
|
527
|
+
text: data.text,
|
|
528
|
+
spokenByCharacter: data.reference,
|
|
529
|
+
isPartOf: {
|
|
530
|
+
"@type": "Book",
|
|
531
|
+
name: data.book
|
|
532
|
+
},
|
|
533
|
+
contributor: {
|
|
534
|
+
"@type": "Organization",
|
|
535
|
+
name: siteName,
|
|
536
|
+
url: `https://${domain}`
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
const script = document.createElement("script");
|
|
540
|
+
script.type = "application/ld+json";
|
|
541
|
+
script.setAttribute("data-wide-snippet", "true");
|
|
542
|
+
script.textContent = JSON.stringify(jsonLd);
|
|
543
|
+
document.head.appendChild(script);
|
|
544
|
+
}
|
|
545
|
+
|
|
521
546
|
// src/widgets/verse.ts
|
|
522
547
|
function parseRef(ref) {
|
|
523
548
|
const withBook = ref.match(/^(.+?)\s+(\d+):(\d+)$/);
|
|
@@ -595,6 +620,20 @@ function initVerseWidget(el, config) {
|
|
|
595
620
|
const verse = "results" in data && Array.isArray(data.results) ? data.results[0] : data;
|
|
596
621
|
if (!verse || !verse.text) throw new Error("No verse found");
|
|
597
622
|
renderVerseWidget(container, verse, el, config);
|
|
623
|
+
if (el.dataset.noSnippet !== "true") {
|
|
624
|
+
const parsed = parseRef(verse.reference || ref);
|
|
625
|
+
const bookName = (parsed == null ? void 0 : parsed.book) || verse.book || config.scriptureLabel;
|
|
626
|
+
injectQuotation(
|
|
627
|
+
{
|
|
628
|
+
text: verse.text,
|
|
629
|
+
reference: verse.reference || ref,
|
|
630
|
+
translation: verse.translation || config.defaultTranslation,
|
|
631
|
+
book: bookName
|
|
632
|
+
},
|
|
633
|
+
config.domain,
|
|
634
|
+
config.name
|
|
635
|
+
);
|
|
636
|
+
}
|
|
598
637
|
}).catch(() => {
|
|
599
638
|
renderError(
|
|
600
639
|
container,
|
package/dist/embed.min.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* widetorah-embed v1.0.0 | MIT | https://widget.widetorah.com */
|
|
2
|
-
"use strict";(()=>{var
|
|
2
|
+
"use strict";(()=>{var f={site:"widetorah",name:"WideTorah",domain:"widetorah.com",apiBase:"https://widetorah.com/api/v1/torah",votdEndpoint:"https://widetorah.com/api/v1/verse-of-the-day/",searchPath:"/search/",accent:"#2563EB",attribute:"data-widetorah",religion:"judaism",scriptureLabel:"Torah",defaultTranslation:"jps"};function C(t){return`
|
|
3
3
|
:host {
|
|
4
4
|
display: block;
|
|
5
5
|
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
@@ -441,42 +441,42 @@
|
|
|
441
441
|
color: var(--muted);
|
|
442
442
|
margin: 2px 0 0 0;
|
|
443
443
|
}
|
|
444
|
-
`}function
|
|
444
|
+
`}function u(t,e){let r=t.attachShadow({mode:"open"}),n=document.createElement("style");return n.textContent=C(e.accent),r.appendChild(n),r}function m(t,e,r){let n=e.dataset.theme||"light",o=e.dataset.size||"default",s=document.createElement("div");return s.className=["wide-widget",r].filter(Boolean).join(" "),s.setAttribute("data-theme",n),s.setAttribute("data-size",o),t.appendChild(s),s}function h(t){t.innerHTML=`
|
|
445
445
|
<div class="wide-loading">
|
|
446
446
|
<span class="wide-spinner"></span>
|
|
447
447
|
Loading\u2026
|
|
448
448
|
</div>
|
|
449
|
-
`}function
|
|
449
|
+
`}function p(t,e,r){t.innerHTML=`
|
|
450
450
|
<div class="wide-error">
|
|
451
451
|
<p>${e}</p>
|
|
452
452
|
<a href="https://${r.domain}" target="_blank" rel="noopener">
|
|
453
453
|
Visit ${r.name}
|
|
454
454
|
</a>
|
|
455
455
|
</div>
|
|
456
|
-
`}var
|
|
457
|
-
<div class="wide-ribbon${
|
|
458
|
-
<p class="wide-verse-text${
|
|
459
|
-
${
|
|
456
|
+
`}var b='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>',w='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>',E='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>',L='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>';function g(t){return`<span class="wide-powered">Powered by <a href="https://${t.domain}" target="_blank" rel="noopener">${t.name}</a></span>`}function k(t,e){t.addEventListener("click",()=>{var r;(r=navigator.clipboard)==null||r.writeText(e).then(()=>{t.innerHTML=`${E} Copied!`,setTimeout(()=>{t.innerHTML=`${w} Copy`},2e3)}).catch(()=>{let n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n),t.innerHTML=`${E} Copied!`,setTimeout(()=>{t.innerHTML=`${w} Copy`},2e3)})})}function S(t,e,r){if(document.querySelector("script[data-wide-snippet]"))return;let n={"@context":"https://schema.org","@type":"Quotation",text:t.text,spokenByCharacter:t.reference,isPartOf:{"@type":"Book",name:t.book},contributor:{"@type":"Organization",name:r,url:`https://${e}`}},o=document.createElement("script");o.type="application/ld+json",o.setAttribute("data-wide-snippet","true"),o.textContent=JSON.stringify(n),document.head.appendChild(o)}function M(t){let e=t.match(/^(.+?)\s+(\d+):(\d+)$/);if(e)return{book:e[1],chapter:e[2],verse:e[3]};let r=t.match(/^(\d+):(\d+)$/);return r?{book:"",chapter:r[1],verse:r[2]}:null}function N(t,e,r){let n=M(e);if(!n)return"";let o=new URLSearchParams;return n.book&&o.set("book",n.book),o.set("chapter",n.chapter),o.set("verse",n.verse),r&&o.set("translation",r),`${t.apiBase}/verses/?${o.toString()}`}function O(t,e,r,n){let o=r.dataset.size==="compact",s=r.dataset.showOriginal==="true",a=e.reference||r.dataset.ref||"",i=e.translation||n.defaultTranslation,d=e.url||`https://${n.domain}`,c=s&&e.original_text?`<p class="wide-original" lang="${e.original_language||""}">${e.original_text}</p>`:"";t.innerHTML=`
|
|
457
|
+
<div class="wide-ribbon${o?" compact":""}">
|
|
458
|
+
<p class="wide-verse-text${o?" compact":""}">${e.text}</p>
|
|
459
|
+
${c}
|
|
460
460
|
</div>
|
|
461
|
-
<div class="wide-body${
|
|
461
|
+
<div class="wide-body${o?" compact":""}">
|
|
462
462
|
<div class="wide-meta">
|
|
463
463
|
<span class="wide-ref">${a}</span>
|
|
464
|
-
<span class="wide-badge">${
|
|
464
|
+
<span class="wide-badge">${i.toUpperCase()}</span>
|
|
465
465
|
</div>
|
|
466
466
|
</div>
|
|
467
|
-
<div class="wide-actions${
|
|
467
|
+
<div class="wide-actions${o?" compact":""}">
|
|
468
468
|
<a class="wide-link" href="${d}" target="_blank" rel="noopener">
|
|
469
|
-
Read on ${n.name} ${
|
|
469
|
+
Read on ${n.name} ${b}
|
|
470
470
|
</a>
|
|
471
471
|
<button class="wide-copy-btn" type="button">
|
|
472
|
-
${
|
|
472
|
+
${w} Copy
|
|
473
473
|
</button>
|
|
474
474
|
</div>
|
|
475
475
|
${g(n)}
|
|
476
|
-
`;let
|
|
476
|
+
`;let l=t.querySelector(".wide-copy-btn");l&&k(l,`${e.text} \u2014 ${a}`)}function H(t,e){let r=u(t,e),n=m(r,t);h(n);let o=t.dataset.ref||"",s=t.dataset.translation||e.defaultTranslation;if(!o){p(n,"Missing data-ref attribute.",e);return}let a=N(e,o,s);if(!a){p(n,`Could not parse reference: "${o}"`,e);return}fetch(a).then(i=>{if(!i.ok)throw new Error(`HTTP ${i.status}`);return i.json()}).then(i=>{let d="results"in i&&Array.isArray(i.results)?i.results[0]:i;if(!d||!d.text)throw new Error("No verse found");if(O(n,d,t,e),t.dataset.noSnippet!=="true"){let c=M(d.reference||o),l=(c==null?void 0:c.book)||d.book||e.scriptureLabel;S({text:d.text,reference:d.reference||o,translation:d.translation||e.defaultTranslation,book:l},e.domain,e.name)}}).catch(()=>{p(n,`Could not load "${o}". Visit ${e.name} to read scripture.`,e)})}function U(t){let e=t.match(/^(.+?)\s+(\d+)$/);if(e)return{book:e[1],chapter:e[2]};let r=t.match(/^(\d+)$/);return r?{book:"",chapter:r[1]}:null}function A(t,e){let r=t.split(/\s+/);return r.length<=e?t:r.slice(0,e).join(" ")+"\u2026"}function B(t,e){let r=u(t,e),n=m(r,t);h(n);let o=t.dataset.ref||"";if(!o){p(n,"Missing data-ref attribute.",e);return}let s=U(o);if(!s){p(n,`Could not parse chapter reference: "${o}"`,e);return}let a=s.book?`${e.apiBase}/chapters/${encodeURIComponent(s.book)}/${s.chapter}/`:`${e.apiBase}/chapters/${s.chapter}/`;fetch(a).then(i=>{if(!i.ok)throw new Error(`HTTP ${i.status}`);return i.json()}).then(i=>{var v;let d=i.title||i.name||o,c=i.book_name||i.book||"",l=i.summary||i.description||"",y=(v=i.verse_count)!=null?v:Array.isArray(i.verses)?i.verses.length:null,$=i.url||`https://${e.domain}`,x=l?A(l,100):"";n.innerHTML=`
|
|
477
477
|
<div class="wide-body">
|
|
478
478
|
<div class="wide-meta">
|
|
479
|
-
${
|
|
479
|
+
${c?`<span class="wide-badge">${c}</span>`:""}
|
|
480
480
|
${y!=null?`<span class="wide-stat">${y} verses</span>`:""}
|
|
481
481
|
</div>
|
|
482
482
|
<h3 class="wide-title">${d}</h3>
|
|
@@ -484,81 +484,81 @@
|
|
|
484
484
|
</div>
|
|
485
485
|
<div class="wide-actions">
|
|
486
486
|
<a class="wide-link" href="${$}" target="_blank" rel="noopener">
|
|
487
|
-
Read full chapter on ${e.name} ${
|
|
487
|
+
Read full chapter on ${e.name} ${b}
|
|
488
488
|
</a>
|
|
489
489
|
</div>
|
|
490
490
|
${g(e)}
|
|
491
|
-
`}).catch(()=>{
|
|
491
|
+
`}).catch(()=>{p(n,`Could not load chapter "${o}". Visit ${e.name} to read scripture.`,e)})}function q(t,e){let r=t.split(/\s+/);return r.length<=e?t:r.slice(0,e).join(" ")+"\u2026"}function V(t,e){let r=u(t,e),n=m(r,t);h(n);let o=t.dataset.slug||"";if(!o){p(n,"Missing data-slug attribute.",e);return}let s=`${e.apiBase}/people/${encodeURIComponent(o)}/`;fetch(s).then(a=>{if(!a.ok)throw new Error(`HTTP ${a.status}`);return a.json()}).then(a=>{var x,v;let i=a.name||a.full_name||o,d=a.era||a.period||"",c=a.bio||a.description||"",l=(v=(x=a.verse_count)!=null?x:a.mentioned_verses)!=null?v:null,y=a.url||`https://${e.domain}/people/${o}/`,$=c?q(c,150):"";n.innerHTML=`
|
|
492
492
|
<div class="wide-person-header">
|
|
493
493
|
<div class="wide-person-icon">${L}</div>
|
|
494
494
|
<div>
|
|
495
|
-
<p class="wide-person-name">${
|
|
495
|
+
<p class="wide-person-name">${i}</p>
|
|
496
496
|
${d?`<p class="wide-person-era">${d}</p>`:""}
|
|
497
497
|
</div>
|
|
498
498
|
</div>
|
|
499
499
|
<div class="wide-body">
|
|
500
500
|
<div class="wide-meta">
|
|
501
|
-
${
|
|
501
|
+
${l!=null?`<span class="wide-stat">${l} verses</span>`:""}
|
|
502
502
|
</div>
|
|
503
503
|
${$?`<p class="wide-summary">${$}</p>`:""}
|
|
504
504
|
</div>
|
|
505
505
|
<div class="wide-actions">
|
|
506
506
|
<a class="wide-link" href="${y}" target="_blank" rel="noopener">
|
|
507
|
-
Learn more on ${e.name} ${
|
|
507
|
+
Learn more on ${e.name} ${b}
|
|
508
508
|
</a>
|
|
509
509
|
</div>
|
|
510
510
|
${g(e)}
|
|
511
|
-
`}).catch(()=>{
|
|
511
|
+
`}).catch(()=>{p(n,`Could not load "${o}". Visit ${e.name} for biblical figures.`,e)})}function Q(t){let e=new URLSearchParams,r=t.match(/^(.+?)\s+(\d+):(\d+)$/);if(r)return e.set("book",r[1]),e.set("chapter",r[2]),e.set("verse",r[3]),e;let n=t.match(/^(\d+):(\d+)$/);return n&&(e.set("chapter",n[1]),e.set("verse",n[2])),e}async function D(t,e){var i,d;let r=Q(e),n=`${t.apiBase}/verses/?${r.toString()}`,o=await fetch(n);if(!o.ok)throw new Error(`HTTP ${o.status}`);let s=await o.json(),a=(d=(i=s.results)==null?void 0:i[0])!=null?d:s;if(!(a!=null&&a.text))throw new Error("No verse data");return{text:a.text,reference:a.reference||e,url:a.url}}function z(t,e){let r=u(t,e),n=m(r,t);h(n);let o=t.dataset.a||"",s=t.dataset.b||"";if(!o||!s){p(n,"Missing data-a or data-b attributes.",e);return}Promise.all([D(e,o),D(e,s)]).then(([a,i])=>{let d=`https://${e.domain}/compare/`;n.innerHTML=`
|
|
512
512
|
<div class="wide-compare-grid">
|
|
513
513
|
<div class="wide-compare-col">
|
|
514
514
|
<p class="wide-compare-label">${a.reference}</p>
|
|
515
515
|
<p class="wide-compare-text">${a.text}</p>
|
|
516
516
|
</div>
|
|
517
517
|
<div class="wide-compare-col">
|
|
518
|
-
<p class="wide-compare-label">${
|
|
519
|
-
<p class="wide-compare-text">${
|
|
518
|
+
<p class="wide-compare-label">${i.reference}</p>
|
|
519
|
+
<p class="wide-compare-text">${i.text}</p>
|
|
520
520
|
</div>
|
|
521
521
|
</div>
|
|
522
522
|
<div class="wide-actions">
|
|
523
523
|
<a class="wide-link" href="${d}" target="_blank" rel="noopener">
|
|
524
|
-
Compare on ${e.name} ${
|
|
524
|
+
Compare on ${e.name} ${b}
|
|
525
525
|
</a>
|
|
526
526
|
</div>
|
|
527
527
|
${g(e)}
|
|
528
|
-
`}).catch(()=>{
|
|
528
|
+
`}).catch(()=>{p(n,`Could not load comparison. Visit ${e.name} to compare scripture.`,e)})}var _="wide_votd_";function W(){return new Date().toISOString().slice(0,10)}function G(t){try{let e=`${_}${t}`,r=localStorage.getItem(e);if(!r)return null;let n=JSON.parse(r);return n.date!==W()?(localStorage.removeItem(e),null):n.data}catch(e){return null}}function F(t,e){try{let r=`${_}${t}`;localStorage.setItem(r,JSON.stringify({date:W(),data:e}))}catch(r){}}function R(t,e){let r=u(t,e),n=m(r,t);h(n);let o=t.dataset.size==="compact";function s(i){let d=i.translation||e.defaultTranslation,c=i.url||`https://${e.domain}`;n.innerHTML=`
|
|
529
529
|
<div class="wide-accent-bar"></div>
|
|
530
|
-
<div class="wide-ribbon${
|
|
531
|
-
<p class="wide-verse-text${
|
|
530
|
+
<div class="wide-ribbon${o?" compact":""}">
|
|
531
|
+
<p class="wide-verse-text${o?" compact":""}">${i.text}</p>
|
|
532
532
|
</div>
|
|
533
|
-
<div class="wide-body${
|
|
533
|
+
<div class="wide-body${o?" compact":""}">
|
|
534
534
|
<div class="wide-meta">
|
|
535
|
-
<span class="wide-ref">${
|
|
535
|
+
<span class="wide-ref">${i.reference}</span>
|
|
536
536
|
<span class="wide-badge">${d.toUpperCase()}</span>
|
|
537
537
|
<span class="wide-badge">Verse of the Day</span>
|
|
538
538
|
</div>
|
|
539
539
|
</div>
|
|
540
|
-
<div class="wide-actions${
|
|
541
|
-
<a class="wide-link" href="${
|
|
542
|
-
More at ${e.name} ${
|
|
540
|
+
<div class="wide-actions${o?" compact":""}">
|
|
541
|
+
<a class="wide-link" href="${c}" target="_blank" rel="noopener">
|
|
542
|
+
More at ${e.name} ${b}
|
|
543
543
|
</a>
|
|
544
544
|
<button class="wide-copy-btn" type="button">
|
|
545
|
-
${
|
|
545
|
+
${w} Copy
|
|
546
546
|
</button>
|
|
547
547
|
</div>
|
|
548
548
|
${g(e)}
|
|
549
|
-
`;let
|
|
549
|
+
`;let l=n.querySelector(".wide-copy-btn");l&&k(l,`${i.text} \u2014 ${i.reference}`)}let a=G(e.site);if(a){s(a);return}fetch(e.votdEndpoint).then(i=>{if(!i.ok)throw new Error(`HTTP ${i.status}`);return i.json()}).then(i=>{if(!(i!=null&&i.text))throw new Error("No VOTD data");F(e.site,i),s(i)}).catch(()=>{p(n,`Could not load verse of the day. Visit ${e.name} for daily scripture.`,e)})}function I(t,e){let r=u(t,e),n=m(r,t),o=t.dataset.placeholder||`Search ${e.scriptureLabel}\u2026`;n.innerHTML=`
|
|
550
550
|
<div class="wide-search-wrap">
|
|
551
551
|
<form class="wide-search-form" action="https://${e.domain}${e.searchPath}" method="get" target="_blank">
|
|
552
552
|
<input
|
|
553
553
|
class="wide-search-input"
|
|
554
554
|
type="search"
|
|
555
555
|
name="q"
|
|
556
|
-
placeholder="${
|
|
557
|
-
aria-label="${
|
|
556
|
+
placeholder="${o}"
|
|
557
|
+
aria-label="${o}"
|
|
558
558
|
autocomplete="off"
|
|
559
559
|
/>
|
|
560
560
|
<button class="wide-search-btn" type="submit">Search</button>
|
|
561
561
|
</form>
|
|
562
562
|
</div>
|
|
563
563
|
${g(e)}
|
|
564
|
-
`}function T(t,e,r){switch(e){case"verse":
|
|
564
|
+
`}function T(t,e,r){switch(e){case"verse":H(t,r);break;case"chapter":B(t,r);break;case"person":V(t,r);break;case"compare":z(t,r);break;case"votd":R(t,r);break;case"search":I(t,r);break;default:break}}function P(t){document.querySelectorAll(`[${t.attribute}]`).forEach(r=>{if(r.shadowRoot)return;let n=r.dataset[t.attribute.replace("data-","")];n&&T(r,n,t)})}(function(){let e=f;document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>P(e)):P(e),new MutationObserver(n=>{n.forEach(o=>{o.addedNodes.forEach(s=>{var i;if(s.nodeType!==Node.ELEMENT_NODE)return;let a=s;if(a.hasAttribute(e.attribute)&&!a.shadowRoot){let d=a.dataset[e.attribute.replace("data-","")];d&&T(a,d,e)}(i=a.querySelectorAll)==null||i.call(a,`[${e.attribute}]`).forEach(d=>{if(!d.shadowRoot){let c=d.dataset[e.attribute.replace("data-","")];c&&T(d,c,e)}})})})}).observe(document.body||document.documentElement,{childList:!0,subtree:!0})})();})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "widetorah-embed",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Embed WideTorah scripture widgets on any website. Lightweight (~5KB gzipped), zero dependencies, Shadow DOM isolation, 3 themes (light/dark/sepia).",
|
|
5
5
|
"main": "dist/embed.min.js",
|
|
6
6
|
"module": "dist/embed.esm.js",
|