From a9c0d87dfb3154a07f4e92adc7d9d1746d6b695d Mon Sep 17 00:00:00 2001 From: Lea Verou Date: Wed, 31 Jan 2024 11:47:22 -0500 Subject: [PATCH] Slowly limit dependence on Bliss --- inspire.mjs | 38 +++++++++++------------------ src/bliss.js | 10 ++++++++ src/plugins/details-notes/plugin.js | 4 ++- src/plugins/docs/plugin.js | 4 ++- src/plugins/grid-layouts/plugin.js | 2 ++ src/plugins/iframe/plugin.js | 6 +++-- src/plugins/live-demo/live-demo.js | 6 +---- src/plugins/live-demo/plugin.js | 11 +++++---- src/plugins/markdown/plugin.js | 2 ++ src/plugins/mavo/plugin.js | 5 +++- src/plugins/media/plugin.js | 10 ++++---- src/plugins/prism/meta.js | 4 +-- src/plugins/prism/plugin.js | 5 ++-- src/plugins/visible-keys/plugin.js | 17 +++++++------ src/util.js | 8 +++--- 15 files changed, 73 insertions(+), 59 deletions(-) create mode 100644 src/bliss.js diff --git a/inspire.mjs b/inspire.mjs index 34ca725..51e0489 100755 --- a/inspire.mjs +++ b/inspire.mjs @@ -7,6 +7,9 @@ import * as plugins from "./src/plugins.js"; import * as util from "./src/util.js"; +import * as Bliss from "./src/bliss.js"; + +const { $, $$, create, ready, bind, Hooks } = Bliss; let _ = { // Plugin ids and selectors @@ -51,13 +54,13 @@ let _ = { _.hooks.run("init-start"); // Create slide indicator - _.indicator = $.create({ + _.indicator = create({ id: "indicator", inside: document.body }); // Add on screen navigation - let onscreen = $.create("nav", { + let onscreen = create("nav", { id: "onscreen-nav", className: "hidden", inside: document.body, @@ -212,7 +215,7 @@ let _ = { // If there"s already a hash, update current slide number _.goto(location.hash.substr(1) || 0); - $.bind(window, { + bind(window, { // Adjust the font-size when the window is resized "load resize": evt => _.adjustFontSize(), /** @@ -486,7 +489,7 @@ let _ = { // Run the slidechange event and hook requestAnimationFrame(() => { let evt = new CustomEvent("slidechange", {"bubbles": true}); - $.extend(evt, {prevSlide, firstTime}); + Object.assign(evt, {prevSlide, firstTime}); slide.dispatchEvent(evt); _.hooks.run("slidechange-async", env); @@ -645,7 +648,7 @@ let _ = { let doc = info.doc; // Make sure local links in the import resolve correctly - doc.head.append($.create(doc.createElement("base"), {href: link.href})); + doc.head.append(create(doc.createElement("base"), {href: link.href})); // Go through all linked resources and absolutize their URLs let attributes = ["src", "data-src", "href"]; @@ -690,7 +693,7 @@ let _ = { import(script.src); } else { - $.create("script", { + create("script", { src: script.src, inside: document.head }); @@ -753,21 +756,7 @@ if (!window.Inspire || !window.Inspire.loaded) { (async () => { // Setup Inspire iif it has not already been loaded - if (!window.Bliss) { - // Load Bliss if not loaded - console.log("Bliss not loaded. Loading remotely from blissfuljs.com"); - - let bliss = document.createElement("script"); - bliss.src = "https://blissfuljs.com/bliss.shy.min.js"; - document.head.appendChild(bliss); - - await new Promise(resolve => bliss.onload = resolve); - } - - window.$ = Bliss; - window.$$ = $.$; - - _.hooks = new $.Hooks(); + _.hooks = new Hooks(); _.loaded.resolve(true); const url = new URL(location); @@ -778,7 +767,7 @@ if (!window.Inspire || !window.Inspire.loaded) { document.documentElement.dataset.profile = profile; } - await $.ready(); + await ready(); // Commenting slides out works sometimes, but fails if the slides you're commenting also have comments. // These classes work with nesting too @@ -787,13 +776,14 @@ if (!window.Inspire || !window.Inspire.loaded) { await _.loadImports(); _.setup(); })(); - - } else { // If Inspire has already been loaded, export that and discard this one _ = window.Inspire; } +_.util = {}; +Object.assign(_.util, util, Bliss); + export default _; diff --git a/src/bliss.js b/src/bliss.js new file mode 100644 index 0000000..c30915e --- /dev/null +++ b/src/bliss.js @@ -0,0 +1,10 @@ + + + +export { default as $ } from "../../bliss/src/$.js"; +export { default as $$ } from "../../bliss/src/$$.js"; +export { default as create } from "../../bliss/src/dom/create.js"; +export { default as bind } from "../../bliss/src/events/bind.js"; +export { default as load } from "../../bliss/src/async/load.js"; +export { default as ready } from "../../bliss/src/ready.js"; +export { default as Hooks } from "../../bliss/src/Hooks.js"; \ No newline at end of file diff --git a/src/plugins/details-notes/plugin.js b/src/plugins/details-notes/plugin.js index 96ef9f3..4077fe3 100644 --- a/src/plugins/details-notes/plugin.js +++ b/src/plugins/details-notes/plugin.js @@ -2,6 +2,8 @@ import Inspire from "../../../inspire.mjs"; export const hasCSS = true; +import { $, $$, create } from "../../bliss.js"; + $$("details.notes").forEach(details => { let div = document.createElement("div"); div.append(...details.childNodes); @@ -15,7 +17,7 @@ $$("details.notes").forEach(details => { let summary = $("summary", details); if (!summary) { - summary = $.create("summary", {textContent: "Notes"}); + summary = create("summary", {textContent: "Notes"}); } details.prepend(summary); diff --git a/src/plugins/docs/plugin.js b/src/plugins/docs/plugin.js index ff76e23..0810972 100644 --- a/src/plugins/docs/plugin.js +++ b/src/plugins/docs/plugin.js @@ -3,6 +3,8 @@ import Inspire from "../../../inspire.mjs"; export const hasCSS = true; +import { $, $$, create } from "../../bliss.js"; + let processDocsLinks = (root = document) => { $$(Inspire.plugins.registry.docs, root).forEach(code => { @@ -42,7 +44,7 @@ let processDocsLinks = (root = document) => { code.textContent += "()"; } - $.create("a", { + create("a", { className: "docs-link", href: `https://developer.mozilla.org/en-US/docs/Web/${path}/${text}`, around: code, diff --git a/src/plugins/grid-layouts/plugin.js b/src/plugins/grid-layouts/plugin.js index bda5ee3..d7dc2cb 100644 --- a/src/plugins/grid-layouts/plugin.js +++ b/src/plugins/grid-layouts/plugin.js @@ -1,5 +1,7 @@ export const hasCSS = true; +import { $$ } from "../../bliss.js"; + $$('[class*="heading-"]').forEach(el => { let [, m, n] = el.className.match(/\bheading-(\d)x(\d)/) || []; diff --git a/src/plugins/iframe/plugin.js b/src/plugins/iframe/plugin.js index bdbf623..b323f1c 100644 --- a/src/plugins/iframe/plugin.js +++ b/src/plugins/iframe/plugin.js @@ -2,13 +2,15 @@ import Inspire from "../../../inspire.mjs"; export const hasCSS = true; +import { $$, create } from "../../bliss.js"; + Inspire.hooks.add({ "slidechange": function(env) { var slide = env.slide; if (slide.matches(".slide[data-src]:empty")) { // Uninitialized iframe slide - var iframe = $.create("iframe", { + var iframe = create("iframe", { "data-src": slide.getAttribute("data-src"), inside: slide, loading: "lazy" @@ -31,7 +33,7 @@ Inspire.hooks.add({ title = url.hostname + url.pathname.replace(/\/$/, ""); } - $.create("h1", { + create("h1", { contents: { tag: "a", href: src, diff --git a/src/plugins/live-demo/live-demo.js b/src/plugins/live-demo/live-demo.js index 2a9f7ea..e34877b 100644 --- a/src/plugins/live-demo/live-demo.js +++ b/src/plugins/live-demo/live-demo.js @@ -1,10 +1,6 @@ import * as prismMeta from "../prism/meta.js"; -import $ from "https://v2.blissfuljs.com/src/$.js"; -import $$ from "https://v2.blissfuljs.com/src/$$.js"; -import create from "https://v2.blissfuljs.com/src/dom/create.js"; -import load from "https://v2.blissfuljs.com/src/async/load.js"; import Hooks from "https://v2.blissfuljs.com/src/Hooks.js"; - +import {$, $$, create, load} as $ from "../../bliss.js"; /* Requirements: - HTML, CSS, or both diff --git a/src/plugins/live-demo/plugin.js b/src/plugins/live-demo/plugin.js index 92a5872..b6501ef 100644 --- a/src/plugins/live-demo/plugin.js +++ b/src/plugins/live-demo/plugin.js @@ -1,5 +1,6 @@ import Inspire from "../../../inspire.mjs"; import * as prism from "../prism/plugin.js"; +import { $, $$, create, load, ready } from "../../bliss.js"; import LiveDemo from "./live-demo.js"; export const hasCSS = true; @@ -37,7 +38,7 @@ input[type="number"] { LiveDemo.hooks.add("after-init", function() { if (this.isolated) { // Next & previous slide buttons - $.create("button", { + create("button", { className: "prev", textContent: "◂", title: "Previous slide", @@ -47,7 +48,7 @@ LiveDemo.hooks.add("after-init", function() { } }); - $.create("button", { + create("button", { className: "next", textContent: "Next ▸", inside: this.controls, @@ -62,7 +63,7 @@ LiveDemo.hooks.add("after-init", function() { // Trigger play automatically when you hit next for (let i = 0; i < pauses + 1; i++) { - $.create("inspire-action", { + create("inspire-action", { attributes: { "target": "button.replay", "once": "" @@ -96,7 +97,7 @@ if (!Prism.Live) { } } - await $.load(`https://live.prismjs.com/src/prism-live.js?load=${languages.join(",")}`); + await load(`https://live.prismjs.com/src/prism-live.js?load=${languages.join(",")}`); await Prism.Live.ready; // Move Prism Live CSS before ours @@ -124,7 +125,7 @@ document.addEventListener("slidechange", evt => { } }); -$.ready().then(async _ => { +ready().then(async _ => { await Inspire.slideshowCreated; if (Inspire.currentSlide?.classList.contains("demo")){ diff --git a/src/plugins/markdown/plugin.js b/src/plugins/markdown/plugin.js index 13d9531..6af4e5e 100644 --- a/src/plugins/markdown/plugin.js +++ b/src/plugins/markdown/plugin.js @@ -1,3 +1,5 @@ +import { $$ } from "../../bliss.js"; + export const hasCSS = false; let selectors = $$("[data-markdown-elements]").map(e => e.getAttribute("data-markdown-elements")); diff --git a/src/plugins/mavo/plugin.js b/src/plugins/mavo/plugin.js index 51da3cd..9110c7a 100644 --- a/src/plugins/mavo/plugin.js +++ b/src/plugins/mavo/plugin.js @@ -3,7 +3,10 @@ import Inspire from "../../../inspire.mjs"; export const hasCSS = false; if (!window.Mavo) { - await Promise.all(["js", "css"].map(ext => $.load(`https://dev.mavo.io/dist/mavo.${ext}`))); + document.head.insertAdjacentHTML("beforeend", ` + + + `); // Nothing more needs to be done, Mavo will automatically run after any imports } else if (Inspire.imports.length) { diff --git a/src/plugins/media/plugin.js b/src/plugins/media/plugin.js index 931ee64..088de4c 100644 --- a/src/plugins/media/plugin.js +++ b/src/plugins/media/plugin.js @@ -8,25 +8,25 @@ export const hasCSS = true; -var $ = Bliss, $$ = $.$; +import { $$, create } from "../../bliss.js"; $$(".slide[data-video]").forEach(slide => slide.classList.add("dont-resize")); -$.events(document, "slidechange", evt => { - var slide = evt.target; +document.addEventListener("slidechange", evt => { + let slide = evt.target; // Create the videos for slides with a data-video attribute if (slide.matches(".slide[data-video]")) { if (!slide.matches(".initialized")) { // Initialization code - let container = slide.classList.contains("cover")? slide : $.create("div", { + let container = slide.classList.contains("cover")? slide : create("div", { className: "video-container " + (slide.hasAttribute("data-frame-class")? slide.getAttribute("data-frame-class") : "media-frame"), inside: slide }); let timedAnnotations = new Map(); - let video = $.create("video", { + let video = create("video", { src: slide.getAttribute("data-video"), loop: slide.classList.contains("looping"), inside: container, diff --git a/src/plugins/prism/meta.js b/src/plugins/prism/meta.js index fc01beb..751d0e0 100644 --- a/src/plugins/prism/meta.js +++ b/src/plugins/prism/meta.js @@ -41,10 +41,10 @@ export async function loadPlugin(id) { } if (!plugins[id].noCSS) { - $.include(`${PRISM_ROOT}/plugins/${id}/prism-${id}.css`); + document.head.insertAdjacentHTML("beforeend", ``); } - await $.include(`${PRISM_ROOT}/plugins/${id}/prism-${id}.js`) + await import(`${PRISM_ROOT}/plugins/${id}/prism-${id}.js`) } return Prism.plugins[CamelCase]; diff --git a/src/plugins/prism/plugin.js b/src/plugins/prism/plugin.js index 9935c7f..659e570 100644 --- a/src/plugins/prism/plugin.js +++ b/src/plugins/prism/plugin.js @@ -3,6 +3,7 @@ */ import Inspire from "../../../inspire.mjs"; +import { $$ } from "../../bliss.js"; import * as util from "../../util.js"; import * as meta from "./meta.js"; @@ -33,7 +34,7 @@ if (ids.size) { } } else { - await $.include(`${PRISM_ROOT}/components/prism-core.js`); + await import(`${PRISM_ROOT}/components/prism-core.js`); } } @@ -80,7 +81,7 @@ var loadLanguage = async id => { await Promise.all(deps.map(loadLanguage)); - await $.include(`${PRISM_ROOT}/components/prism-${id}.js`); + await import(`${PRISM_ROOT}/components/prism-${id}.js`); ok[id].resolve(id); }; diff --git a/src/plugins/visible-keys/plugin.js b/src/plugins/visible-keys/plugin.js index 92c5876..2ddde3b 100644 --- a/src/plugins/visible-keys/plugin.js +++ b/src/plugins/visible-keys/plugin.js @@ -1,5 +1,8 @@ // Display certain keys pressed import Inspire from "../../../inspire.mjs"; +import { create } from "../../bliss.js"; +import transition from "../../../../bliss/src/dom/transition.js"; +import { timeout } from "../../util.js"; export const symbols = { Tab: "⇥", @@ -23,10 +26,10 @@ Inspire.hooks.add("slidechange", env => { } if (env.slide.matches("[data-visible-keys]")) { - var keys = new Set(env.slide.dataset.visibleKeys.split(/\s+/)); - var delay = +env.slide.dataset.visibleKeysDelay || 600; + let keys = new Set(env.slide.dataset.visibleKeys.split(/\s+/)); + let delay = +env.slide.dataset.visibleKeysDelay || 600; - document.addEventListener("keyup", listener = function(evt) { + document.addEventListener("keyup", listener = async evt => { if (keys.has(evt.key) && evt.target.nodeName != "TEXTAREA") { label = evt.key; @@ -39,15 +42,15 @@ Inspire.hooks.add("slidechange", env => { + (evt.metaKey? symbols.Meta : "") + (evt.altKey? symbols.Alt : "") + label; - var key = $.create("kbd", { + let key = create("kbd", { textContent: label, inside: env.slide, className: "visible-key" }); - setTimeout(() => { - $.transition(key, {opacity: 0}).then($.remove); - }, delay); + await timeout(delay); + await transition(key, {opacity: 0}); + key.remove(); } }); } diff --git a/src/util.js b/src/util.js index 0ae9f65..4fcdb31 100644 --- a/src/util.js +++ b/src/util.js @@ -23,12 +23,12 @@ export function timeout (ms, {reject, value} = {}) { // Get attribute value, from the first element it's defined on // Useful for things like global settings where we don't care where the attribute is on -export function getAttribute(attribute) { +export function getAttribute (attribute) { let element = document.querySelector(`[${attribute}]`); return element && element.getAttribute(attribute); } -export async function importCJS(src) { +export async function importCJS (src) { let prevModule = window.module; window.module = { exports: {} }; await import(src); @@ -37,11 +37,11 @@ export async function importCJS(src) { return ret; } -export function toArray(arr) { +export function toArray (arr) { return arr === undefined? [] : Array.isArray(arr)? arr : [arr]; } -export function deduplicateId(element) { +export function deduplicateId (element) { // The first element with an id gets to keep it // Otherwise we'd end up with foo-2 before foo let firstWithId = document.getElementById(element.id);