From 65abea20939de7632254c92055a76512c458edad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Fri, 5 Dec 2025 04:31:03 +0300 Subject: [PATCH] port to bitty 7.0.0-rc1 --- app/templates/base.html | 6 ++-- data/static/css/style.css | 2 +- data/static/css/theme-otomotone.css | 2 +- data/static/css/theme-peachy.css | 2 +- data/static/js/bitties/pyrom-bitty.js | 40 +++++++++++------------ data/static/js/vnd/bitty-6.0.0-rc3.min.js | 1 - data/static/js/vnd/bitty-7.0.0-rc1.min.js | 1 + sass/_default.scss | 2 +- sass/peachy.scss | 2 ++ 9 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 data/static/js/vnd/bitty-6.0.0-rc3.min.js create mode 100644 data/static/js/vnd/bitty-7.0.0-rc1.min.js diff --git a/app/templates/base.html b/app/templates/base.html index fc1ea87..6792ad8 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -10,10 +10,10 @@ {% endif %} - + - + {% include 'common/topnav.html' %} {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} @@ -24,6 +24,6 @@ {% endwith %} {% block content %}{% endblock %} {% include 'common/footer.html' %} - + diff --git a/data/static/css/style.css b/data/static/css/style.css index 0dd1278..f60b0f4 100644 --- a/data/static/css/style.css +++ b/data/static/css/style.css @@ -1382,7 +1382,7 @@ footer { mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat; width: 24px; height: 24px; - padding: 0 10px; + padding: 0 20px; flex-shrink: 0; } .bookmark-dropdown-item.selected { diff --git a/data/static/css/theme-otomotone.css b/data/static/css/theme-otomotone.css index 3ada347..98a7fb3 100644 --- a/data/static/css/theme-otomotone.css +++ b/data/static/css/theme-otomotone.css @@ -1382,7 +1382,7 @@ footer { mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat; width: 24px; height: 24px; - padding: 0 10px; + padding: 0 20px; flex-shrink: 0; } .bookmark-dropdown-item.selected { diff --git a/data/static/css/theme-peachy.css b/data/static/css/theme-peachy.css index 579a1ea..e6e8dd0 100644 --- a/data/static/css/theme-peachy.css +++ b/data/static/css/theme-peachy.css @@ -1382,7 +1382,7 @@ footer { mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat; width: 24px; height: 24px; - padding: 0 6px; + padding: 0 24px; flex-shrink: 0; } .bookmark-dropdown-item.selected { diff --git a/data/static/js/bitties/pyrom-bitty.js b/data/static/js/bitties/pyrom-bitty.js index 285486e..c5312e2 100644 --- a/data/static/js/bitties/pyrom-bitty.js +++ b/data/static/js/bitties/pyrom-bitty.js @@ -6,12 +6,12 @@ const delay = ms => {return new Promise(resolve => setTimeout(resolve, ms))} export default class { async showBookmarkMenu(ev, el) { - if ((ev.sender.dataset.bookmarkId === el.getString('bookmarkId')) && el.childElementCount === 0) { + if ((el.sender.dataset.bookmarkId === el.ds('bookmarkId')) && el.childElementCount === 0) { const searchParams = new URLSearchParams({ - 'id': ev.sender.dataset.conceptId, + 'id': el.sender.dataset.conceptId, 'require_reload': el.dataset.requireReload, }); - const bookmarkMenuHref = `${bookmarkMenuHrefTemplate}/${ev.sender.dataset.bookmarkType}?${searchParams}`; + const bookmarkMenuHref = `${bookmarkMenuHrefTemplate}/${el.sender.dataset.bookmarkType}?${searchParams}`; const res = await this.api.getHTML(bookmarkMenuHref); if (res.error) { return; @@ -49,9 +49,9 @@ export default class { } selectBookmarkCollection(ev, el) { - const clicked = ev.sender; + const clicked = el.sender; - if (ev.sender === el) { + if (el.sender === el) { if (clicked.classList.contains('selected')) { clicked.classList.remove('selected'); } else { @@ -63,7 +63,7 @@ export default class { } async saveBookmarks(ev, el) { - const bookmarkHref = el.getString('bookmarkEndpoint'); + const bookmarkHref = el.ds('bookmarkEndpoint'); const collection = el.querySelector('.bookmark-dropdown-item.selected'); let data = {}; if (collection) { @@ -72,7 +72,7 @@ export default class { data['memo'] = el.querySelector('.bookmark-memo-input').value; } else { data['operation'] = 'remove'; - data['collection_id'] = el.getString('originallyContainedIn'); + data['collection_id'] = el.ds('originallyContainedIn'); } const options = { @@ -82,7 +82,7 @@ export default class { 'Content-Type': 'application/json', }, } - const requireReload = el.getInt('requireReload') !== 0; + const requireReload = el.dsInt('requireReload') !== 0; el.remove(); await fetch(bookmarkHref, options); if (requireReload) { @@ -103,10 +103,10 @@ export default class { toggleAccordion(ev, el) { const accordion = el; const header = accordion.querySelector('.accordion-header'); - if (!header.contains(ev.sender)){ + if (!header.contains(el.sender)){ return; } - const btn = ev.sender; + const btn = el.sender; const content = el.querySelector('.accordion-content'); // these are all meant to be in sync accordion.classList.toggle('hidden'); @@ -116,15 +116,15 @@ export default class { toggleTab(ev, el) { const tabButtonsContainer = el.querySelector('.tab-buttons'); - if (!el.contains(ev.sender)) { + if (!el.contains(el.sender)) { return; } - if (ev.sender.classList.contains('active')) { + if (el.sender.classList.contains('active')) { return; } - const targetId = ev.sender.getString('targetId'); + const targetId = el.senderDs('targetId'); const contents = el.querySelectorAll('.tab-content'); for (let content of contents) { if (content.id === targetId) { @@ -144,7 +144,7 @@ export default class { #previousMarkup = null; async babycodePreview(ev, el) { - if (ev.sender.classList.contains('active')) { + if (el.sender.classList.contains('active')) { return; } @@ -199,9 +199,9 @@ export default class { } insertBabycodeTag(ev, el) { - const tagStart = ev.sender.getString('tag'); - const breakLine = 'breakLine' in ev.sender.dataset; - const prefill = 'prefill' in ev.sender.dataset ? ev.sender.dataset.prefill : ''; + const tagStart = el.senderDs('tag'); + const breakLine = 'breakLine' in el.sender.dataset; + const prefill = 'prefill' in el.sender.dataset ? el.sender.dataset.prefill : ''; const hasAttr = tagStart[tagStart.length - 1] === '='; let tagEnd = tagStart; @@ -249,13 +249,13 @@ export default class { } addQuote(ev, el) { - el.value += ev.sender.value; + el.value += el.sender.value; el.scrollIntoView(); el.focus(); } convertTimestamps(ev, el) { - const timestamp = el.getInt('utc'); + const timestamp = el.dsInt('utc'); if (!isNaN(timestamp)) { const date = new Date(timestamp * 1000); el.textContent = date.toLocaleString(); @@ -272,7 +272,7 @@ export default class { this.#currentUsername = userInfo.value.user.username; } - if (el.getString('username') === this.#currentUsername) { + if (el.ds('username') === this.#currentUsername) { el.classList.add('me'); } } diff --git a/data/static/js/vnd/bitty-6.0.0-rc3.min.js b/data/static/js/vnd/bitty-6.0.0-rc3.min.js deleted file mode 100644 index e55eeaf..0000000 --- a/data/static/js/vnd/bitty-6.0.0-rc3.min.js +++ /dev/null @@ -1 +0,0 @@ -const t=[6,0,0],e=`bitty-${t[0]}-${t[1]}`;class n extends Error{constructor(t){super(),Error.captureStackTrace&&Error.captureStackTrace(this,n),this.name="BittyError";for(let[e,n]of Object.entries(t))this[e]=n}}class i extends Event{constructor(){super("bittybittyinit",{bubbles:!0})}}class s extends Event{constructor(){super("bittybittyready",{bubbles:!0})}}class a extends Event{constructor(t,e){super("bittydatainit",{bubbles:!0}),this.signal=t,this.el=e}}class r extends Event{constructor(t,e){super("bittyforward",{bubbles:!0}),this.forwardedEvent=t,this.forwardedSignal=e}}class o extends Event{constructor(t){super("bittylocaltrigger",{bubbles:!0}),this.signal=t}}class l extends Event{constructor(t){super("bittytrigger",{bubbles:!0}),this.signal=t}}function c(t,e){return void 0!==t.dataset[e]?t.dataset[e]:t.parentNode?c(t.parentNode,e):null}class d extends HTMLElement{constructor(){super(),this.config={listeners:["click","input"],license:"CC0",version:t}}async connectedCallback(){this.dataset.bittyid=self.crypto.randomUUID(),await this.makeConnection(),this.conn&&(this.conn.api=this,this.handleEventBridge=this.handleEvent.bind(this),this.setIds(this),this.addEventListeners(),await this.runBittyInit(),this.runDataInits(),await this.runBittyReady())}addEventListeners(){const t=["bittybittyinit","bittybittyready","bittydatainit","bittyforward","bittylocaltrigger","bittytrigger"];this.dataset.listeners?this.trimInput(this.dataset.listeners).forEach(e=>{t.push(e)}):(t.push("click"),t.push("input")),t.forEach(t=>{window.addEventListener(t,t=>{this.handleEventBridge.call(this,t)})})}connectedMoveCallback(){}doSubs(t,e){return e.forEach(e=>{const n=typeof e[1],i=Object.prototype.toString.call(e[1]);if("object"===n&&"[object Array]"===i){const n=e[1].map(t=>{const e=typeof t,n=Object.prototype.toString.call(t);return"object"===e&&"[object DocumentFragment]"===n?[...t.childNodes].map(t=>"[object Text]"===Object.prototype.toString.call(t)?t.wholeText:t.outerHTML).join(""):"object"===e?t.outerHTML:t}).join("");t=t.replaceAll(e[0],n)}else if("object"===n&&"[object DocumentFragment]"===i){const n=[];[...e[1].childNodes].forEach(t=>{"[object Text]"===Object.prototype.toString.call(t)?n.push(t.wholeText):n.push(t.outerHTML)}),t=t.replaceAll(e[0],n.join(""))}else t="object"==typeof e[1]?t.replaceAll(e[0],e[1].outerHTML):t.replaceAll(e[0],e[1])}),t}forward(t,e){const n=new r(t,e);this.dispatchEvent(n)}getBittyParent(t){return t.localName.toLowerCase()===e?t:t.parentNode?this.getBittyParent(t.parentNode):null}async getElement(t,e=[],n={}){const i=await this.getHTML(t,e,n,"getElement");if(i.value){return{value:i.value.firstChild}}return i}async getHTML(t,e=[],n={}){const i=await this.getTXT(t,e,n,"getHTML");return i.error?i:{value:this.makeHTML(i.value,e)}}async getJSON(t,e=[],i={}){const s=await this.getTXT(t,e,i,"getJSON");if(s.error)return s;try{const t=JSON.parse(s.value);return{value:t}}catch(t){return{error:new n({type:"parsing"})}}}async getSVG(t,e=[],n={}){const i=await this.getTXT(t,e,n,"getSVG");if(i.error)return i;{const t=document.createElement("template");t.innerHTML=i.value;return{value:t.content.cloneNode(!0).querySelector("svg")}}}async getTXT(t,e=[],i={},s="getTXT"){let a=await fetch(t,i);try{if(a.ok){return{value:this.doSubs(await a.text(),e)}}throw new n({type:"fetching",message:`${s}() returned ${a.status} [${a.statusText}] in:\n${s}(${a.url}, ${JSON.stringify(e)}, ${JSON.stringify(i)})`,statusText:a.statusText,status:a.status,url:a.url,incomingMethod:s,subs:e,options:i})}catch(t){return console.error(`BittyError: ${t.message}`),{error:t}}}findSender(t,e){e.dataset&&e.dataset.send?t.sender=e:e.parentNode&&this.findSender(t,e.parentNode)}async handleEvent(t){if(t.target.value&&(t.target.stringValue=t.target.value,t.target.intValue=parseInt(t.target.value,10),t.target.floatValue=parseFloat(t.target.value)),"bittybittyinit"===t.type)this.dataset.bittyid===t.target.dataset.bittyid&&"function"==typeof this.conn.bittyInit&&("AsyncFunction"===this.conn.bittyInit[Symbol.toStringTag]?await this.conn.bittyInit():this.conn.bittyInit());else if("bittybittyready"===t.type)this.dataset.bittyid===t.target.dataset.bittyid&&"function"==typeof this.conn.bittyReady&&("AsyncFunction"===this.conn.bittyReady[Symbol.toStringTag]?await this.conn.bittyReady():this.conn.bittyReady());else if("bittylocaltrigger"===t.type){t.sender=t.target;const e=this.trimInput(t.signal),n=this.querySelectorAll("[data-receive]");for(let i of e){let e=!1;const s=i.split(":");if(2===s.length&&"await"===s[0]&&(e=!0,i=s[1]),this.conn[i]){const s=this.getBittyParent(t.target);let a=!1;for(let r of n){const n=this.getBittyParent(r);if(s.dataset.bittyid===n.dataset.bittyid){const n=this.trimInput(r.dataset.receive);for(let s of n){const n=s.split(":");2===n.length&&"await"===n[0]&&(e=!0,s=n[1]),s===i&&(a=!0,this.prepElements(t,r),e?await this.conn[i](t,r):this.conn[i](t,r))}}}!1===a&&s.dataset.bittyid===this.dataset.bittyid&&(e?await this.conn[i](t,null):this.conn[i](t,null))}}}else if("bittytrigger"===t.type){t.sender=t.target;const e=this.trimInput(t.signal),n=this.querySelectorAll("[data-receive]");for(let i of e){let e=!1;const s=i.split(":");if(2===s.length&&"await"===s[0]&&(e=!0,i=s[1]),this.conn[i]){let s=!1;for(let a of n){const n=this.trimInput(a.dataset.receive);for(let r of n){const n=r.split(":");2===n.length&&"await"===n[0]&&(e=!0,r=n[1]),r===i&&(s=!0,this.prepElements(t,a),e?await this.conn[i](t,a):this.conn[i](t,a))}}!1===s&&(e?await this.conn[i](t,null):this.conn[i](t,null))}}}else if("bittydatainit"===t.type){if(t.sender=t.target,this.prepElements(t,t.el),this.dataset.bittyid===t.el.bittyParentId){const e=this.trimInput(t.signal);for(const n of e)this.conn[n]&&this.conn[n](t,t.el)}}else if("bittyforward"===t.type){const e=this.trimInput(t.forwardedSignal);t=t.forwardedEvent;const n=this.querySelectorAll("[data-receive]");for(let i of n){this.prepElements(t,i);const n=this.trimInput(i.dataset.receive);for(let s of n)e.includes(s)&&this.conn[s]&&this.conn[s](t,i)}}else if(this.findSender(t,t.target),t.sender){t.sender.getString=e=>c.call(null,t.sender,e),t.sender.getInt=e=>parseInt(c.call(null,t.sender,e)),t.sender.getFloat=e=>parseFloat(c.call(null,t.sender,e));const e=this.trimInput(t.sender.dataset.send),n=this.querySelectorAll("[data-receive]");for(let i of e){let e=!1;const s=i.split(":");if(2===s.length&&"await"===s[0]&&(e=!0,i=s[1]),this.conn[i]){let s=!1;for(let a of n){const n=this.trimInput(a.dataset.receive);for(const r of n){const n=r.split(":");2===n.length&&"await"===n[0]&&(r=n[1]),r===i&&(s=!0,this.prepElements(t,a),e?await this.conn[i](t,a):this.conn[i](t,a))}}!1===s&&(e?await this.conn[i](t,null):this.conn[i](t,null))}}}}localTrigger(t){const e=new o(t);this.dispatchEvent(e)}async loadCSS(t,e,n){const i=await this.getTXT(t,e,n,"loadCSS");if(i.error)return i;{const t=new CSSStyleSheet;return t.replaceSync(i.value),document.adoptedStyleSheets.push(t),{value:i.value}}}async makeConnection(){try{if(this.dataset.connect){let t=this.trimInput(this.dataset.connect);if(void 0!==window[t[0]])this.conn=new window[t[0]];else{if("/"===t[0].substring(0,1)){const e=new URL(window.location.href);t[0]=new URL(t[0],e.origin).toString()}if("http"===t[0].substring(0,4)){const e=await import(t[0]);void 0===t[1]?this.conn=new e.default:this.conn=new e[t[1]]}else console.error("The value of 'data-connect' must start with 'http' or '/'. Other URLs are not currently supported")}}else window.BittyClass?this.conn=new window.BittyClass:console.error(`${e} error: No class to connect to.`)}catch(t){console.error(`${e} error: ${t} - ${this.dataset.connect}`)}}makeElement(t,e=[]){return this.makeHTML(t,e).firstChild}makeHTML(t,e=[]){const n=document.createElement("template");n.innerHTML=this.makeTXT(t,e).trim();const i=n.content.cloneNode(!0);return this.setIds(i),i}makeTXT(t,e=[]){return this.doSubs(t,e)}prepElements(t,e){e.isTarget=t.target.dataset.bittyid===e.dataset.bittyid,e.isSender=t.sender.dataset.bittyid===e.dataset.bittyid,e.bittyParent=this.getBittyParent(e),e.bittyParentId=e.bittyParent.dataset.bittyid,e.bittyId=e.dataset.bittyid,e.getString=t=>c.call(null,e,t),e.getInt=t=>parseInt(c.call(null,e,t)),e.getFloat=t=>parseFloat(c.call(null,e,t)),e.matchTarget=n=>c.call(null,t.target,n)===c.call(null,e,n),e.matchSender=n=>c.call(null,t.sender,n)===c.call(null,e,n)}async runBittyInit(){if("function"==typeof this.conn.bittyInit){const t=new i;this.dispatchEvent(t)}}async runBittyReady(){if("function"==typeof this.conn.bittyReady){const t=new s;this.dispatchEvent(t)}}runDataInits(){if(this.dataset.init){const t=new a(this.dataset.init,this);this.dispatchEvent(t)}else this.querySelectorAll("[data-init]").forEach(t=>{const e=new a(t.dataset.init,t);this.dispatchEvent(e)})}setProp(t,e){document.documentElement.style.setProperty(t,e)}setIds(t){t.querySelectorAll("*").forEach(t=>{t.dataset.bittyid||(t.dataset.bittyid=self.crypto.randomUUID())})}trigger(t){const e=new l(t);this.dispatchEvent(e)}trimInput(t){return t.trim().split(/\s+/m).map(t=>t.trim())}}customElements.define(e,d); \ No newline at end of file diff --git a/data/static/js/vnd/bitty-7.0.0-rc1.min.js b/data/static/js/vnd/bitty-7.0.0-rc1.min.js new file mode 100644 index 0000000..2fc4b9b --- /dev/null +++ b/data/static/js/vnd/bitty-7.0.0-rc1.min.js @@ -0,0 +1 @@ +const t=[7,0,0],e=`bitty-${t[0]}-${t[1]}`;function n(t,e){null!==t&&(e.isTarget=t.target.dataset.bittyid===e.dataset.bittyid,e.isSender=e.sender.dataset.bittyid===e.dataset.bittyid),e.bittyParent=s(e),e.bittyParentBittyId=e.bittyParent.dataset.bittyid,e.bittyId=e.dataset.bittyid,e.ds=t=>c.call(null,e,t),e.dsInt=t=>parseInt(c.call(null,e,t)),e.dsFloat=t=>parseFloat(c.call(null,e,t)),null!==t&&(e.targetBittyId=t.target.dataset.bittyid),e.targetDs=e=>c.call(null,t.target,e),e.targetDsInt=e=>parseInt(c.call(null,t.target,e)),e.targetDsFloat=e=>parseFloat(c.call(null,t.target,e)),null!==t&&(e.senderBittyId=e.sender.dataset.bittyid),e.senderDs=t=>c.call(null,e.sender,t),e.senderDsInt=t=>parseInt(c.call(null,e.sender,t)),e.senderDsFloat=t=>parseFloat(c.call(null,e.sender,t)),e.value&&(e.val=e.value,e.valInt=parseInt(e.value,10),e.valFloat=parseFloat(e.value)),null!==t&&t.target.value&&(e.targetVal=t.target.value,e.targetValInt=parseInt(t.target.value,10),e.targetValFloat=parseFloat(t.target.value)),null!==t&&e.sender.value&&(e.senderVal=e.sender.value,e.senderValInt=parseInt(e.sender.value,10),e.senderValFloat=parseFloat(e.sender.value)),e.matchTargetDs=n=>{const a=c.call(null,t.target,n),s=c.call(null,e,n);return void 0!==a&&void 0!==s&&a===s},e.matchSenderDs=t=>{const n=c.call(null,e.sender,t),a=c.call(null,e,t);return void 0!==n&&void 0!==a&&n===a}}function a(t){return t.dataset&&t.dataset.send||t.dataset&&t.dataset.use?t:t.parentNode?a(t.parentNode):void 0}function s(t){return t.localName.toLowerCase()===e?t:t.parentNode?s(t.parentNode):null}class i extends Error{constructor(t){super(),Error.captureStackTrace&&Error.captureStackTrace(this,i),this.name="BittyError";for(let[e,n]of Object.entries(t))this[e]=n}}class r extends Event{constructor(t,e){super("bittyforward",{bubbles:!0}),this.forwardedEvent=t,this.forwardedSignal=e}}class o extends Event{constructor(t){super("bittylocaltrigger",{bubbles:!0}),this.signal=t}}class l extends Event{constructor(t){super("bittytrigger",{bubbles:!0}),this.signal=t}}function c(t,e){if(void 0!==t.dataset)return void 0!==t.dataset[e]?t.dataset[e]:t.parentNode?c(t.parentNode,e):void 0}class d extends HTMLElement{constructor(){super(),this.config={listeners:["click","input"],license:"CC0",version:t}}async connectedCallback(){this.dataset.bittyid=self.crypto.randomUUID(),await this.makeConnection(),this.conn&&(this.conn.api=this,this.handleEventBridge=this.handleEvent.bind(this),this.setIds(this),this.addEventListeners(),await this.runBittyInit(),await this.runDataInits(),await this.runBittyReady())}addEventListeners(){const t=["bittyforward","bittylocaltrigger","bittytrigger"];this.dataset.listeners?this.trimInput(this.dataset.listeners).forEach(e=>{t.push(e)}):(t.push("click"),t.push("input")),t.forEach(t=>{window.addEventListener(t,t=>{this.handleEventBridge.call(this,t)})})}connectedMoveCallback(){}doSubs(t,e){return e.forEach(e=>{const n=typeof e[1],a=Object.prototype.toString.call(e[1]);if("object"===n&&"[object Array]"===a){const n=e[1].map(t=>{const e=typeof t,n=Object.prototype.toString.call(t);return"object"===e&&"[object DocumentFragment]"===n?[...t.childNodes].map(t=>"[object Text]"===Object.prototype.toString.call(t)?t.wholeText:t.outerHTML).join(""):"object"===e?t.outerHTML:t}).join("");t=t.replaceAll(e[0],n)}else if("object"===n&&"[object DocumentFragment]"===a){const n=[];[...e[1].childNodes].forEach(t=>{"[object Text]"===Object.prototype.toString.call(t)?n.push(t.wholeText):n.push(t.outerHTML)}),t=t.replaceAll(e[0],n.join(""))}else t="object"==typeof e[1]?t.replaceAll(e[0],e[1].outerHTML):t.replaceAll(e[0],e[1])}),t}forward(t,e){const n=new r(t,e);this.dispatchEvent(n)}getBittyParent(t){return t.localName.toLowerCase()===e?t:t.parentNode?this.getBittyParent(t.parentNode):null}async getElement(t,e=[],n={}){const a=await this.getHTML(t,e,n,"getElement");if(a.value){return{value:a.value.firstChild}}return a}async getHTML(t,e=[],n={}){const a=await this.getTXT(t,e,n,"getHTML");return a.error?a:{value:this.makeHTML(a.value,e)}}async getJSON(t,e=[],n={}){const a=await this.getTXT(t,e,n,"getJSON");if(a.error)return a;try{const t=JSON.parse(a.value);return{value:t}}catch(t){return{error:new i({type:"parsing"})}}}async getSVG(t,e=[],n={}){const a=await this.getTXT(t,e,n,"getSVG");if(a.error)return a;{const t=document.createElement("template");t.innerHTML=a.value;return{value:t.content.cloneNode(!0).querySelector("svg")}}}async getTXT(t,e=[],n={},a="getTXT"){let s=await fetch(t,n);try{if(s.ok){return{value:this.doSubs(await s.text(),e)}}throw new i({type:"fetching",message:`${a}() returned ${s.status} [${s.statusText}] in:\n${a}(${s.url}, ${JSON.stringify(e)}, ${JSON.stringify(n)})`,statusText:s.statusText,status:s.status,url:s.url,incomingMethod:a,subs:e,options:n})}catch(t){return console.error(`BittyError: ${t.message}`),{error:t}}}async handleEvent(t){if(function(t){void 0!==t.target.value&&(t.val=t.target.value,t.valInt=parseInt(t.target.value,10),t.valFloat=parseFloat(event.target.value)),t.ds=e=>c.call(null,t.target,e),t.dsInt=e=>parseInt(c.call(null,t.target,e)),t.dsFloat=e=>parseFloat(c.call(null,t.target,e))}(t),"bittylocaltrigger"===t.type){const e=this.trimInput(t.signal),a=this.querySelectorAll("[data-receive]");for(let i of e){let e=!1;const r=i.split(":");if(2===r.length&&"await"===r[0]&&(e=!0,i=r[1]),this.conn[i]){const r=s(t.target);let o=!1;for(let l of a){l.sender=t.target;const a=s(l);if(r.dataset.bittyid===a.dataset.bittyid){const a=this.trimInput(l.dataset.receive);for(let s of a){const a=s.split(":");2===a.length&&"await"===a[0]&&(e=!0,s=a[1]),s===i&&(o=!0,n(t,l),e?await this.conn[i](t,l):this.conn[i](t,l))}}}!1===o&&r.dataset.bittyid===this.dataset.bittyid&&(e?await this.conn[i](t,null):this.conn[i](t,null))}}}else if("bittytrigger"===t.type){const e=this.trimInput(t.signal),a=this.querySelectorAll("[data-receive]");for(let s of e){let e=!1;const i=s.split(":");if(2===i.length&&"await"===i[0]&&(e=!0,s=i[1]),this.conn[s]){let i=!1;for(let r of a){r.sender=t.target;const a=this.trimInput(r.dataset.receive);for(let o of a){const a=o.split(":");2===a.length&&"await"===a[0]&&(e=!0,o=a[1]),o===s&&(i=!0,n(t,r),e?await this.conn[s](t,r):this.conn[s](t,r))}}!1===i&&(e?await this.conn[s](t,null):this.conn[s](t,null))}}}else if("bittyforward"===t.type){const e=this.trimInput(t.forwardedSignal);t=t.forwardedEvent;const a=this.querySelectorAll("[data-receive]");for(let s of a){s.sender=t.target,n(t,s);const a=this.trimInput(s.dataset.receive);for(let n of a)e.includes(n)&&this.conn[n]&&this.conn[n](t,s)}}else{const e=a(t.target);if(e){const a=this.querySelectorAll("[data-use]");if(e.dataset.use){const s=this.trimInput(e.dataset.use);if(a.length>0)for(let i of s){let s=!1;const r=i.split(":");if(2===r.length&&"await"===r[0]&&(s=!0,i=r[1]),this.conn[i])for(let r of a)r.sender=e,n(t,r),r.bittyId===r.senderBittyId&&(s?await this.conn[i](t,r):this.conn[i](t,r))}}if(e.dataset.send){const a=this.trimInput(e.dataset.send),s=this.querySelectorAll("[data-receive]");for(let i of a){let a=!1;const r=i.split(":");if(2===r.length&&"await"===r[0]&&(a=!0,i=r[1]),this.conn[i]){let r=!1;for(let o of s){o.sender=e;const s=this.trimInput(o.dataset.receive);for(const e of s){const s=e.split(":");2===s.length&&"await"===s[0]&&(e=s[1]),e===i&&(r=!0,n(t,o),a?await this.conn[i](t,o):this.conn[i](t,o))}}!1===r&&(a?await this.conn[i](t,null):this.conn[i](t,null))}}}}}}localTrigger(t){const e=new o(t);this.dispatchEvent(e)}async loadCSS(t,e,n){const a=await this.getTXT(t,e,n,"loadCSS");if(a.error)return a;{const t=new CSSStyleSheet;return t.replaceSync(a.value),document.adoptedStyleSheets.push(t),{value:a.value}}}async makeConnection(){try{if(this.dataset.connect){let t=this.trimInput(this.dataset.connect);if(void 0!==window[t[0]])this.conn=new window[t[0]];else{if("/"===t[0].substring(0,1)){const e=new URL(window.location.href);t[0]=new URL(t[0],e.origin).toString()}if("http"===t[0].substring(0,4)){const e=await import(t[0]);void 0===t[1]?this.conn=new e.default:this.conn=new e[t[1]]}else console.error(`Tried to use 'data-connect="${this.dataset.connect}" which did not match a class on the page which means an attempt to use it as a URL was made. It failed becasue the URL version of 'data-connect' must start with 'http' or '/'. Other URLs are not currently supported`)}}else window.BittyClass?this.conn=new window.BittyClass:console.error(`${e} error: No class to connect to.`)}catch(t){console.error(`${e} error: ${t} - ${this.dataset.connect}`)}}makeElement(t,e=[]){return this.makeHTML(t,e).firstChild}makeHTML(t,e=[]){const n=document.createElement("template");n.innerHTML=this.makeTXT(t,e).trim();const a=n.content.cloneNode(!0);return this.setIds(a),a}makeSVG(t,e=[]){const n=document.createElement("template");n.innerHTML=this.makeTXT(t,e).trim();return n.content.cloneNode(!0).querySelector("svg")}makeTXT(t,e=[]){return this.doSubs(t,e)}async runBittyInit(){"function"==typeof this.conn.bittyInit&&("AsyncFunction"===this.conn.bittyInit[Symbol.toStringTag]?await this.conn.bittyInit():this.conn.bittyInit())}async runBittyReady(){"function"==typeof this.conn.bittyReady&&("AsyncFunction"===this.conn.bittyReady[Symbol.toStringTag]?await this.conn.bittyReady():this.conn.bittyReady())}async runDataInits(){if(this.dataset.init){const t=this.trimInput(this.dataset.init);for(let e of t)"function"==typeof this.conn[e]&&("AsyncFunction"===this.conn[e][Symbol.toStringTag]?await this.conn[e](null,this):this.conn[e](null,this))}for(let t of this.querySelectorAll("[data-init]"))if(t.dataset.init){n(null,t);const e=this.trimInput(t.dataset.init);for(let n of e)"function"==typeof this.conn[n]&&("AsyncFunction"===this.conn[n][Symbol.toStringTag]?await this.conn[n](null,t):this.conn[n](null,t))}}setProp(t,e){document.documentElement.style.setProperty(t,e)}setIds(t){t.querySelectorAll("*").forEach(t=>{t.dataset.bittyid||(t.dataset.bittyid=self.crypto.randomUUID())})}trigger(t){const e=new l(t);this.dispatchEvent(e)}trimInput(t){return t.trim().split(/\s+/m).map(t=>t.trim())}}customElements.define(e,d); \ No newline at end of file diff --git a/sass/_default.scss b/sass/_default.scss index cc6b772..707510f 100644 --- a/sass/_default.scss +++ b/sass/_default.scss @@ -1306,7 +1306,7 @@ $bookmark_dropdown_item_background_hover: $BUTTON_COLOR_HOVER !default; $bookmark_dropdown_item_background_selected: $BUTTON_COLOR_2 !default; $bookmark_dropdown_item_background_selected_hover: $BUTTON_COLOR_2_HOVER !default; $bookmark_dropdown_item_icon_size: 24px !default; -$bookmark_dropdown_item_icon_padding: 0 $MEDIUM_PADDING !default; +$bookmark_dropdown_item_icon_padding: 0 $BIG_PADDING !default; .bookmark-dropdown-item { display: flex; justify-content: space-between; diff --git a/sass/peachy.scss b/sass/peachy.scss index 34fabe3..619b5fd 100644 --- a/sass/peachy.scss +++ b/sass/peachy.scss @@ -63,6 +63,8 @@ $br: 16px; $pagebutton_min_width: 36px, $quote_background_color: #0002, + + $bookmark_dropdown_item_icon_padding: 0 24px, ); #topnav {