Move all remote dependencies to be local (#220)
* Experiment with javascript bundling * Experiment with snowpack. Making progress * Success! Uses local js modules and assets and no cdns * Missing local css
This commit is contained in:
parent
e7f39a0113
commit
27a4c8c895
3225
build/javascript/package-lock.json
generated
Normal file
3225
build/javascript/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
build/javascript/package.json
Normal file
40
build/javascript/package.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"name": "owncast-dependencies",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"@joeattardi/emoji-button": "^4.2.0",
|
||||||
|
"@justinribeiro/lite-youtube": "^0.9.0",
|
||||||
|
"@videojs/http-streaming": "^2.2.0",
|
||||||
|
"@videojs/themes": "^1.0.0",
|
||||||
|
"htm": "^3.0.4",
|
||||||
|
"preact": "^10.5.3",
|
||||||
|
"showdown": "^1.9.1",
|
||||||
|
"tailwindcss": "^1.8.10",
|
||||||
|
"video.js": "^7.9.6"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"snowpack": "^2.12.1"
|
||||||
|
},
|
||||||
|
"snowpack": {
|
||||||
|
"install": [
|
||||||
|
"video.js/dist/video.min.js",
|
||||||
|
"@videojs/themes/fantasy/*",
|
||||||
|
"@videojs/http-streaming/dist/videojs-http-streaming.min.js",
|
||||||
|
"video.js/dist/video-js.min.css",
|
||||||
|
"@joeattardi/emoji-button",
|
||||||
|
"@justinribeiro/lite-youtube",
|
||||||
|
"htm",
|
||||||
|
"preact",
|
||||||
|
"showdown",
|
||||||
|
"tailwindcss/dist/tailwind.min.css"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "npm install && npx snowpack install && cp -R web_modules ../../webroot/js"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
@ -3,20 +3,19 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
||||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
<link href="/js/web_modules/tailwindcss/dist/tailwind.min.css" rel="stylesheet" />
|
||||||
<link href="./styles/chat.css" rel="stylesheet" />
|
<link href="./styles/chat.css" rel="stylesheet" />
|
||||||
<link href="./styles/standalone-chat.css" rel="stylesheet" />
|
<link href="./styles/standalone-chat.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
|
||||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@0.6.2/lite-youtube.js"></script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="messages-only"></div>
|
<div id="messages-only"></div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
import { h, render } from '/js/web_modules/preact.js';
|
||||||
|
import htm from '/js/web_modules/htm.js';
|
||||||
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import StandaloneChat from './js/app-standalone-chat.js';
|
import StandaloneChat from './js/app-standalone-chat.js';
|
||||||
render(
|
render(
|
||||||
html`<${StandaloneChat} messagesOnly />`, document.getElementById("messages-only")
|
html`<${StandaloneChat} messagesOnly />`, document.getElementById("messages-only")
|
||||||
|
@ -3,17 +3,13 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
||||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
<link href="/js/web_modules/tailwindcss/dist/tailwind.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
<link href="//unpkg.com/video.js@7.9.3/dist/video-js.css" rel="stylesheet"/>
|
<link href="/js/web_modules/videojs/dist/video-js.min.css" rel="stylesheet"/>
|
||||||
<link href="https://unpkg.com/@videojs/themes@1/dist/fantasy/index.css" rel="stylesheet" />
|
<link href="/js/web_modules/@videojs/themes/fantasy/index.css" rel="stylesheet" />
|
||||||
<script src="//unpkg.com/video.js@7.9.3/dist/alt/video.core.min.js"></script>
|
|
||||||
<script src="//unpkg.com/@videojs/http-streaming@2.1.0/dist/videojs-http-streaming.min.js"></script>
|
|
||||||
|
|
||||||
<link href="./styles/video.css" rel="stylesheet" />
|
<link href="./styles/video.css" rel="stylesheet" />
|
||||||
<link href="./styles/video-only.css" rel="stylesheet" />
|
<link href="./styles/video-only.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="//unpkg.com/showdown/dist/showdown.min.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -21,7 +17,10 @@
|
|||||||
<div id="video-only"></div>
|
<div id="video-only"></div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
import { h, render } from '/js/web_modules/preact.js';
|
||||||
|
import htm from '/js/web_modules/htm.js';
|
||||||
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import VideoOnly from './js/app-video-only.js';
|
import VideoOnly from './js/app-video-only.js';
|
||||||
render(html`<${VideoOnly} />`, document.getElementById("video-only"));
|
render(html`<${VideoOnly} />`, document.getElementById("video-only"));
|
||||||
</script>
|
</script>
|
||||||
|
@ -24,34 +24,25 @@
|
|||||||
<meta name="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png">
|
<meta name="msapplication-TileImage" content="/img/favicon/ms-icon-144x144.png">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"/>
|
<link href="/js/web_modules/tailwindcss/dist/tailwind.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
<link href="//unpkg.com/video.js@7.9.3/dist/video-js.css" rel="stylesheet" />
|
<link href="/js/web_modules/videojs/dist/video-js.min.css" rel="stylesheet"/>
|
||||||
<link href="https://unpkg.com/@videojs/themes@1/dist/fantasy/index.css" rel="stylesheet" />
|
<link href="/js/web_modules/@videojs/themes/fantasy/index.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="//unpkg.com/video.js@7.9.3/dist/alt/video.core.min.js" defer></script>
|
|
||||||
<script src="//unpkg.com/@videojs/http-streaming@2.1.0/dist/videojs-http-streaming.min.js" defer></script>
|
|
||||||
|
|
||||||
<!-- markdown renderer -->
|
|
||||||
<script src="//unpkg.com/showdown/dist/showdown.min.js" defer></script>
|
|
||||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@0.6.2/lite-youtube.js" defer></script>
|
|
||||||
|
|
||||||
<link href="./styles/video.css" rel="stylesheet" />
|
<link href="./styles/video.css" rel="stylesheet" />
|
||||||
<link href="./styles/chat.css" rel="stylesheet" />
|
<link href="./styles/chat.css" rel="stylesheet" />
|
||||||
<link href="./styles/user-content.css" rel="stylesheet" />
|
<link href="./styles/user-content.css" rel="stylesheet" />
|
||||||
<link href="./styles/app.css" rel="stylesheet" />
|
<link href="./styles/app.css" rel="stylesheet" />
|
||||||
|
|
||||||
<!-- Preloads -->
|
|
||||||
<link rel="preconnect" href="https://unpkg.com/@joeattardi/emoji-button@4.2.0/dist/index.js" />
|
|
||||||
<link rel="preconnect" href="https://unpkg.com/preact?module" />
|
|
||||||
<link rel="preconnect" href="https://unpkg.com/htm?module" />
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="scrollbar-hidden bg-gray-300 text-gray-800">
|
<body class="scrollbar-hidden bg-gray-300 text-gray-800">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { render, html } from 'https://unpkg.com/htm/preact/standalone.module.js';
|
import { h, render } from '/js/web_modules/preact.js';
|
||||||
|
import htm from '/js/web_modules/htm.js';
|
||||||
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import App from './js/app.js';
|
import App from './js/app.js';
|
||||||
render(html`<${App} />`, document.getElementById("app"));
|
render(html`<${App} />`, document.getElementById("app"));
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component } from 'https://unpkg.com/preact?module';
|
import { h, Component } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import Chat from './components/chat/chat.js';
|
import Chat from './components/chat/chat.js';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component } from 'https://unpkg.com/preact?module';
|
import { h, Component } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import { OwncastPlayer } from './components/player.js';
|
import { OwncastPlayer } from './components/player.js';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component } from 'https://unpkg.com/preact?module';
|
import { h, Component } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import { OwncastPlayer } from './components/player.js';
|
import { OwncastPlayer } from './components/player.js';
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { h, Component, createRef } from 'https://unpkg.com/preact?module';
|
import { h, Component, createRef } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import { EmojiButton } from 'https://unpkg.com/@joeattardi/emoji-button@4.2.0/dist/index.js';
|
import { EmojiButton } from '/js/web_modules/@joeattardi/emoji-button.js';
|
||||||
|
|
||||||
import ContentEditable, { replaceCaret } from './content-editable.js';
|
import ContentEditable, { replaceCaret } from './content-editable.js';
|
||||||
import { generatePlaceholderText, getCaretPosition, convertToText, convertOnPaste } from '../../utils/chat.js';
|
import { generatePlaceholderText, getCaretPosition, convertToText, convertOnPaste } from '../../utils/chat.js';
|
||||||
import { getLocalStorage, setLocalStorage, classNames } from '../../utils/helpers.js';
|
import { getLocalStorage, setLocalStorage, classNames } from '../../utils/helpers.js';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component, createRef } from 'https://unpkg.com/preact?module';
|
import { h, Component, createRef } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import Message from './message.js';
|
import Message from './message.js';
|
||||||
|
@ -6,7 +6,7 @@ and here:
|
|||||||
https://stackoverflow.com/questions/22677931/react-js-onchange-event-for-contenteditable/27255103#27255103
|
https://stackoverflow.com/questions/22677931/react-js-onchange-event-for-contenteditable/27255103#27255103
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import { Component, createRef, h } from 'https://unpkg.com/preact?module';
|
import { h, Component, createRef } from '/js/web_modules/preact.js';
|
||||||
|
|
||||||
export function replaceCaret(el) {
|
export function replaceCaret(el) {
|
||||||
// Place the caret at the end of the element
|
// Place the caret at the end of the element
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component } from 'https://unpkg.com/preact?module';
|
import { h, Component } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import { messageBubbleColorForString } from '../../utils/user-colors.js';
|
import { messageBubbleColorForString } from '../../utils/user-colors.js';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h, Component, createRef } from 'https://unpkg.com/preact?module';
|
import { h, Component, createRef } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
|
|
||||||
import { generateAvatar, setLocalStorage } from '../../utils/helpers.js';
|
import { generateAvatar, setLocalStorage } from '../../utils/helpers.js';
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// https://docs.videojs.com/player
|
// https://docs.videojs.com/player
|
||||||
|
|
||||||
|
import videojs from '/js/web_modules/videojs/dist/video.min.js';
|
||||||
|
|
||||||
const VIDEO_ID = 'video';
|
const VIDEO_ID = 'video';
|
||||||
// TODO: This directory is customizable in the config. So we should expose this via the config API.
|
// TODO: This directory is customizable in the config. So we should expose this via the config API.
|
||||||
const URL_STREAM = `/hls/stream.m3u8`;
|
const URL_STREAM = `/hls/stream.m3u8`;
|
||||||
@ -52,13 +54,14 @@ class OwncastPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
videojs.Vhs.xhr.beforeRequest = function (options) {
|
this.vjsPlayer = videojs(VIDEO_ID, VIDEO_OPTIONS);
|
||||||
|
|
||||||
|
this.vjsPlayer.beforeRequest = function (options) {
|
||||||
const cachebuster = Math.round(new Date().getTime() / 1000);
|
const cachebuster = Math.round(new Date().getTime() / 1000);
|
||||||
options.uri = `${options.uri}?cachebust=${cachebuster}`;
|
options.uri = `${options.uri}?cachebust=${cachebuster}`;
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.vjsPlayer = videojs(VIDEO_ID, VIDEO_OPTIONS);
|
|
||||||
this.addAirplay();
|
this.addAirplay();
|
||||||
this.vjsPlayer.ready(this.handleReady);
|
this.vjsPlayer.ready(this.handleReady);
|
||||||
}
|
}
|
||||||
@ -75,10 +78,10 @@ class OwncastPlayer {
|
|||||||
// play
|
// play
|
||||||
startPlayer() {
|
startPlayer() {
|
||||||
this.log('Start playing');
|
this.log('Start playing');
|
||||||
const source = { ...VIDEO_SRC }
|
const source = { ...VIDEO_SRC };
|
||||||
this.vjsPlayer.src(source);
|
this.vjsPlayer.src(source);
|
||||||
// this.vjsPlayer.play();
|
// this.vjsPlayer.play();
|
||||||
};
|
}
|
||||||
|
|
||||||
handleReady() {
|
handleReady() {
|
||||||
this.log('on Ready');
|
this.log('on Ready');
|
||||||
@ -117,7 +120,7 @@ class OwncastPlayer {
|
|||||||
|
|
||||||
setPoster() {
|
setPoster() {
|
||||||
const cachebuster = Math.round(new Date().getTime() / 1000);
|
const cachebuster = Math.round(new Date().getTime() / 1000);
|
||||||
const poster = POSTER_THUMB + "?okhi=" + cachebuster;
|
const poster = POSTER_THUMB + '?okhi=' + cachebuster;
|
||||||
|
|
||||||
this.vjsPlayer.poster(poster);
|
this.vjsPlayer.poster(poster);
|
||||||
}
|
}
|
||||||
@ -131,7 +134,6 @@ class OwncastPlayer {
|
|||||||
if (window.WebKitPlaybackTargetAvailabilityEvent) {
|
if (window.WebKitPlaybackTargetAvailabilityEvent) {
|
||||||
var videoJsButtonClass = videojs.getComponent('Button');
|
var videoJsButtonClass = videojs.getComponent('Button');
|
||||||
var concreteButtonClass = videojs.extend(videoJsButtonClass, {
|
var concreteButtonClass = videojs.extend(videoJsButtonClass, {
|
||||||
|
|
||||||
// The `init()` method will also work for constructor logic here, but it is
|
// The `init()` method will also work for constructor logic here, but it is
|
||||||
// deprecated. If you provide an `init()` method, it will override the
|
// deprecated. If you provide an `init()` method, it will override the
|
||||||
// `constructor()` method!
|
// `constructor()` method!
|
||||||
@ -145,8 +147,10 @@ class OwncastPlayer {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
var concreteButtonInstance = this.vjsPlayer.controlBar.addChild(new concreteButtonClass());
|
var concreteButtonInstance = this.vjsPlayer.controlBar.addChild(
|
||||||
concreteButtonInstance.addClass("vjs-airplay");
|
new concreteButtonClass()
|
||||||
|
);
|
||||||
|
concreteButtonInstance.addClass('vjs-airplay');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { h } from 'https://unpkg.com/preact?module';
|
import { h } from '/js/web_modules/preact.js';
|
||||||
import htm from 'https://unpkg.com/htm?module';
|
import htm from '/js/web_modules/htm.js';
|
||||||
const html = htm.bind(h);
|
const html = htm.bind(h);
|
||||||
import { SOCIAL_PLATFORMS } from '../utils/social.js';
|
import { SOCIAL_PLATFORMS } from '../utils/social.js';
|
||||||
import { classNames } from '../utils/helpers.js';
|
import { classNames } from '../utils/helpers.js';
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
CHAT_PLACEHOLDER_OFFLINE,
|
CHAT_PLACEHOLDER_OFFLINE,
|
||||||
} from './constants.js';
|
} from './constants.js';
|
||||||
|
|
||||||
|
import showdown from '/js/web_modules/showdown.js';
|
||||||
export function formatMessageText(message, username) {
|
export function formatMessageText(message, username) {
|
||||||
showdown.setFlavor('github');
|
showdown.setFlavor('github');
|
||||||
let formattedText = new showdown.Converter({
|
let formattedText = new showdown.Converter({
|
||||||
|
3
webroot/js/web_modules/@joeattardi/emoji-button.js
Normal file
3
webroot/js/web_modules/@joeattardi/emoji-button.js
Normal file
File diff suppressed because one or more lines are too long
301
webroot/js/web_modules/@justinribeiro/lite-youtube.js
Normal file
301
webroot/js/web_modules/@justinribeiro/lite-youtube.js
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* The shadowDom / Intersection Observer version of Paul's concept:
|
||||||
|
* https://github.com/paulirish/lite-youtube-embed
|
||||||
|
*
|
||||||
|
* A lightweight YouTube embed. Still should feel the same to the user, just
|
||||||
|
* MUCH faster to initialize and paint.
|
||||||
|
*
|
||||||
|
* Thx to these as the inspiration
|
||||||
|
* https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html
|
||||||
|
* https://autoplay-youtube-player.glitch.me/
|
||||||
|
*
|
||||||
|
* Once built it, I also found these (👍👍):
|
||||||
|
* https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube
|
||||||
|
* https://github.com/Daugilas/lazyYT https://github.com/vb/lazyframe
|
||||||
|
*/
|
||||||
|
class LiteYTEmbed extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.iframeLoaded = false;
|
||||||
|
this.setupDom();
|
||||||
|
}
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ['videoid'];
|
||||||
|
}
|
||||||
|
connectedCallback() {
|
||||||
|
this.addEventListener('pointerover', LiteYTEmbed.warmConnections, {
|
||||||
|
once: true,
|
||||||
|
});
|
||||||
|
this.addEventListener('click', () => this.addIframe());
|
||||||
|
}
|
||||||
|
get videoId() {
|
||||||
|
return encodeURIComponent(this.getAttribute('videoid') || '');
|
||||||
|
}
|
||||||
|
set videoId(id) {
|
||||||
|
this.setAttribute('videoid', id);
|
||||||
|
}
|
||||||
|
get videoTitle() {
|
||||||
|
return this.getAttribute('videotitle') || 'Video';
|
||||||
|
}
|
||||||
|
set videoTitle(title) {
|
||||||
|
this.setAttribute('videotitle', title);
|
||||||
|
}
|
||||||
|
get videoPlay() {
|
||||||
|
return this.getAttribute('videoPlay') || 'Play';
|
||||||
|
}
|
||||||
|
set videoPlay(name) {
|
||||||
|
this.setAttribute('videoPlay', name);
|
||||||
|
}
|
||||||
|
get videoStartAt() {
|
||||||
|
return Number(this.getAttribute('videoStartAt') || '0');
|
||||||
|
}
|
||||||
|
set videoStartAt(time) {
|
||||||
|
this.setAttribute('videoStartAt', String(time));
|
||||||
|
}
|
||||||
|
get autoLoad() {
|
||||||
|
return this.hasAttribute('autoload');
|
||||||
|
}
|
||||||
|
set autoLoad(value) {
|
||||||
|
if (value) {
|
||||||
|
this.setAttribute('autoload', '');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.removeAttribute('autoload');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get params() {
|
||||||
|
return `start=${this.videoStartAt}&${this.getAttribute('params')}`;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Define our shadowDOM for the component
|
||||||
|
*/
|
||||||
|
setupDom() {
|
||||||
|
const shadowDom = this.attachShadow({ mode: 'open' });
|
||||||
|
shadowDom.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
contain: content;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: calc(100% / (16 / 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
#frame, #fallbackPlaceholder, iframe {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#frame {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fallbackPlaceholder {
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
#frame::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==);
|
||||||
|
background-position: top;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
height: 60px;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
width: 100%;
|
||||||
|
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
/* play button */
|
||||||
|
.lty-playbtn {
|
||||||
|
width: 70px;
|
||||||
|
height: 46px;
|
||||||
|
background-color: #212121;
|
||||||
|
z-index: 1;
|
||||||
|
opacity: 0.8;
|
||||||
|
border-radius: 14%; /* TODO: Consider replacing this with YT's actual svg. Eh. */
|
||||||
|
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
#frame:hover .lty-playbtn {
|
||||||
|
background-color: #f00;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
/* play button triangle */
|
||||||
|
.lty-playbtn:before {
|
||||||
|
content: '';
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 11px 0 11px 19px;
|
||||||
|
border-color: transparent transparent transparent #fff;
|
||||||
|
}
|
||||||
|
.lty-playbtn,
|
||||||
|
.lty-playbtn:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate3d(-50%, -50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Post-click styles */
|
||||||
|
.lyt-activated {
|
||||||
|
cursor: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#frame.lyt-activated::before,
|
||||||
|
.lyt-activated .lty-playbtn {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="frame">
|
||||||
|
<picture>
|
||||||
|
<source id="webpPlaceholder" type="image/webp">
|
||||||
|
<source id="jpegPlaceholder" type="image/jpeg">
|
||||||
|
<img id="fallbackPlaceholder" referrerpolicy="origin">
|
||||||
|
</picture>
|
||||||
|
<button class="lty-playbtn"></button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
this.domRefFrame = this.shadowRoot.querySelector('#frame');
|
||||||
|
this.domRefImg = {
|
||||||
|
fallback: this.shadowRoot.querySelector('#fallbackPlaceholder'),
|
||||||
|
webp: this.shadowRoot.querySelector('#webpPlaceholder'),
|
||||||
|
jpeg: this.shadowRoot.querySelector('#jpegPlaceholder'),
|
||||||
|
};
|
||||||
|
this.domRefPlayButton = this.shadowRoot.querySelector('.lty-playbtn');
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse our attributes and fire up some placeholders
|
||||||
|
*/
|
||||||
|
setupComponent() {
|
||||||
|
this.initImagePlaceholder();
|
||||||
|
this.domRefPlayButton.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`);
|
||||||
|
this.setAttribute('title', `${this.videoPlay}: ${this.videoTitle}`);
|
||||||
|
if (this.autoLoad) {
|
||||||
|
this.initIntersectionObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lifecycle method that we use to listen for attribute changes to period
|
||||||
|
* @param {*} name
|
||||||
|
* @param {*} oldVal
|
||||||
|
* @param {*} newVal
|
||||||
|
*/
|
||||||
|
attributeChangedCallback(name, oldVal, newVal) {
|
||||||
|
switch (name) {
|
||||||
|
case 'videoid': {
|
||||||
|
if (oldVal !== newVal) {
|
||||||
|
this.setupComponent();
|
||||||
|
// if we have a previous iframe, remove it and the activated class
|
||||||
|
if (this.domRefFrame.classList.contains('lyt-activated')) {
|
||||||
|
this.domRefFrame.classList.remove('lyt-activated');
|
||||||
|
this.shadowRoot.querySelector('iframe').remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Inject the iframe into the component body
|
||||||
|
*/
|
||||||
|
addIframe() {
|
||||||
|
if (!this.iframeLoaded) {
|
||||||
|
const iframeHTML = `
|
||||||
|
<iframe frameborder="0"
|
||||||
|
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen
|
||||||
|
src="https://www.youtube.com/embed/${this.videoId}?autoplay=1&${this.params}"
|
||||||
|
></iframe>`;
|
||||||
|
this.domRefFrame.insertAdjacentHTML('beforeend', iframeHTML);
|
||||||
|
this.domRefFrame.classList.add('lyt-activated');
|
||||||
|
this.iframeLoaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Setup the placeholder image for the component
|
||||||
|
*/
|
||||||
|
initImagePlaceholder() {
|
||||||
|
// we don't know which image type to preload, so warm the connection
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://i.ytimg.com/');
|
||||||
|
const posterUrlWebp = `https://i.ytimg.com/vi_webp/${this.videoId}/hqdefault.webp`;
|
||||||
|
const posterUrlJpeg = `https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg`;
|
||||||
|
this.domRefImg.webp.srcset = posterUrlWebp;
|
||||||
|
this.domRefImg.jpeg.srcset = posterUrlJpeg;
|
||||||
|
this.domRefImg.fallback.src = posterUrlJpeg;
|
||||||
|
this.domRefImg.fallback.setAttribute('aria-label', `${this.videoPlay}: ${this.videoTitle}`);
|
||||||
|
this.domRefImg.fallback.setAttribute('alt', `${this.videoPlay}: ${this.videoTitle}`);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Setup the Intersection Observer to load the iframe when scrolled into view
|
||||||
|
*/
|
||||||
|
initIntersectionObserver() {
|
||||||
|
if ('IntersectionObserver' in window &&
|
||||||
|
'IntersectionObserverEntry' in window) {
|
||||||
|
const options = {
|
||||||
|
root: null,
|
||||||
|
rootMargin: '0px',
|
||||||
|
threshold: 0,
|
||||||
|
};
|
||||||
|
const observer = new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting && !this.iframeLoaded) {
|
||||||
|
LiteYTEmbed.warmConnections();
|
||||||
|
this.addIframe();
|
||||||
|
observer.unobserve(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, options);
|
||||||
|
observer.observe(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Add a <link rel={preload | preconnect} ...> to the head
|
||||||
|
* @param {*} kind
|
||||||
|
* @param {*} url
|
||||||
|
* @param {*} as
|
||||||
|
*/
|
||||||
|
static addPrefetch(kind, url, as) {
|
||||||
|
const linkElem = document.createElement('link');
|
||||||
|
linkElem.rel = kind;
|
||||||
|
linkElem.href = url;
|
||||||
|
if (as) {
|
||||||
|
linkElem.as = as;
|
||||||
|
}
|
||||||
|
linkElem.crossOrigin = 'true';
|
||||||
|
document.head.append(linkElem);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Begin preconnecting to warm up the iframe load Since the embed's netwok
|
||||||
|
* requests load within its iframe, preload/prefetch'ing them outside the
|
||||||
|
* iframe will only cause double-downloads. So, the best we can do is warm up
|
||||||
|
* a few connections to origins that are in the critical path.
|
||||||
|
*
|
||||||
|
* Maybe `<link rel=preload as=document>` would work, but it's unsupported:
|
||||||
|
* http://crbug.com/593267 But TBH, I don't think it'll happen soon with Site
|
||||||
|
* Isolation and split caches adding serious complexity.
|
||||||
|
*/
|
||||||
|
static warmConnections() {
|
||||||
|
if (LiteYTEmbed.preconnected)
|
||||||
|
return;
|
||||||
|
// Host that YT uses to serve JS needed by player, per amp-youtube
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://s.ytimg.com');
|
||||||
|
// The iframe document and most of its subresources come right off
|
||||||
|
// youtube.com
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube.com');
|
||||||
|
// The botguard script is fetched off from google.com
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com');
|
||||||
|
// TODO: Not certain if these ad related domains are in the critical path.
|
||||||
|
// Could verify with domain-specific throttling.
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net');
|
||||||
|
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net');
|
||||||
|
LiteYTEmbed.preconnected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LiteYTEmbed.preconnected = false;
|
||||||
|
// Register custom element
|
||||||
|
customElements.define('lite-youtube', LiteYTEmbed);
|
||||||
|
|
||||||
|
export { LiteYTEmbed };
|
116
webroot/js/web_modules/@videojs/themes/fantasy/index.css
Normal file
116
webroot/js/web_modules/@videojs/themes/fantasy/index.css
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
.vjs-theme-fantasy {
|
||||||
|
--vjs-theme-fantasy--primary: #9f44b4;
|
||||||
|
--vjs-theme-fantasy--secondary: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-big-play-button {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
background: none;
|
||||||
|
line-height: 70px;
|
||||||
|
font-size: 80px;
|
||||||
|
border: none;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -35px;
|
||||||
|
margin-left: -35px;
|
||||||
|
color: var(--vjs-theme-fantasy--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy:hover .vjs-big-play-button,
|
||||||
|
.vjs-theme-fantasy.vjs-big-play-button:focus {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-control-bar {
|
||||||
|
height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-button > .vjs-icon-placeholder::before {
|
||||||
|
line-height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-time-control {
|
||||||
|
line-height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Play Button */
|
||||||
|
.vjs-theme-fantasy .vjs-play-control {
|
||||||
|
font-size: 1.5em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-volume-panel {
|
||||||
|
order: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-volume-bar {
|
||||||
|
margin-top: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-city .vjs-volume-panel:hover .vjs-volume-control.vjs-volume-horizontal {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-progress-control .vjs-progress-holder {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-progress-control:hover .vjs-progress-holder {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-play-control .vjs-icon-placeholder::before {
|
||||||
|
height: 1.3em;
|
||||||
|
width: 1.3em;
|
||||||
|
margin-top: 0.2em;
|
||||||
|
border-radius: 1em;
|
||||||
|
border: 3px solid var(--vjs-theme-fantasy--secondary);
|
||||||
|
top: 2px;
|
||||||
|
left: 9px;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-play-control:hover .vjs-icon-placeholder::before {
|
||||||
|
border: 3px solid var(--vjs-theme-fantasy--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-play-progress {
|
||||||
|
background-color: var(--vjs-theme-fantasy--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-play-progress::before {
|
||||||
|
height: 0.8em;
|
||||||
|
width: 0.8em;
|
||||||
|
content: '';
|
||||||
|
background-color: var(--vjs-theme-fantasy--primary);
|
||||||
|
border: 4px solid var(--vjs-theme-fantasy--secondary);
|
||||||
|
border-radius: 0.8em;
|
||||||
|
top: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-progress-control {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-fullscreen-control {
|
||||||
|
order: 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy .vjs-remaining-time {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nyan version */
|
||||||
|
.vjs-theme-fantasy.nyan .vjs-play-progress {
|
||||||
|
background: linear-gradient(to bottom, #fe0000 0%, #fe9a01 16.666666667%, #fe9a01 16.666666667%, #ffff00 33.332666667%, #ffff00 33.332666667%, #32ff00 49.999326667%, #32ff00 49.999326667%, #0099fe 66.6659926%, #0099fe 66.6659926%, #6633ff 83.33266%, #6633ff 83.33266%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-theme-fantasy.nyan .vjs-play-progress::before {
|
||||||
|
height: 1.3em;
|
||||||
|
width: 1.3em;
|
||||||
|
background: svg-load('icons/nyan-cat.svg', fill=#fff) no-repeat;
|
||||||
|
border: none;
|
||||||
|
top: -0.35em;
|
||||||
|
}
|
25
webroot/js/web_modules/common/_commonjsHelpers-37fa8da4.js
Normal file
25
webroot/js/web_modules/common/_commonjsHelpers-37fa8da4.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
||||||
|
|
||||||
|
function getDefaultExportFromCjs (x) {
|
||||||
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCommonjsModule(fn, basedir, module) {
|
||||||
|
return module = {
|
||||||
|
path: basedir,
|
||||||
|
exports: {},
|
||||||
|
require: function (path, base) {
|
||||||
|
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
|
||||||
|
}
|
||||||
|
}, fn(module, module.exports), module.exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultExportFromNamespaceIfNotNamed (n) {
|
||||||
|
return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function commonjsRequire () {
|
||||||
|
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
|
||||||
|
}
|
||||||
|
|
||||||
|
export { commonjsGlobal as a, getDefaultExportFromNamespaceIfNotNamed as b, createCommonjsModule as c, getDefaultExportFromCjs as g };
|
44
webroot/js/web_modules/common/window-2f8a9a85.js
Normal file
44
webroot/js/web_modules/common/window-2f8a9a85.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { b as getDefaultExportFromNamespaceIfNotNamed, a as commonjsGlobal } from './_commonjsHelpers-37fa8da4.js';
|
||||||
|
|
||||||
|
var _nodeResolve_empty = {};
|
||||||
|
|
||||||
|
var _nodeResolve_empty$1 = /*#__PURE__*/Object.freeze({
|
||||||
|
__proto__: null,
|
||||||
|
'default': _nodeResolve_empty
|
||||||
|
});
|
||||||
|
|
||||||
|
var minDoc = /*@__PURE__*/getDefaultExportFromNamespaceIfNotNamed(_nodeResolve_empty$1);
|
||||||
|
|
||||||
|
var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
|
||||||
|
typeof window !== 'undefined' ? window : {};
|
||||||
|
|
||||||
|
|
||||||
|
var doccy;
|
||||||
|
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
|
doccy = document;
|
||||||
|
} else {
|
||||||
|
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
|
||||||
|
|
||||||
|
if (!doccy) {
|
||||||
|
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var document_1 = doccy;
|
||||||
|
|
||||||
|
var win;
|
||||||
|
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
win = window;
|
||||||
|
} else if (typeof commonjsGlobal !== "undefined") {
|
||||||
|
win = commonjsGlobal;
|
||||||
|
} else if (typeof self !== "undefined"){
|
||||||
|
win = self;
|
||||||
|
} else {
|
||||||
|
win = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var window_1 = win;
|
||||||
|
|
||||||
|
export { document_1 as d, window_1 as w };
|
3
webroot/js/web_modules/htm.js
Normal file
3
webroot/js/web_modules/htm.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
var n=function(t,s,r,e){var u;s[0]=0;for(var h=1;h<s.length;h++){var p=s[h++],a=s[h]?(s[0]|=p?1:2,r[s[h++]]):s[++h];3===p?e[0]=a:4===p?e[1]=Object.assign(e[1]||{},a):5===p?(e[1]=e[1]||{})[s[++h]]=a:6===p?e[1][s[++h]]+=a+"":p?(u=t.apply(a,n(t,a,r,["",null])),e.push(u),a[0]?s[0]|=2:(s[h-2]=0,s[h]=u)):e.push(a);}return e},t=new Map;function htm_module(s){var r=t.get(this);return r||(r=new Map,t.set(this,r)),(r=n(this,r.get(s)||(r.set(s,r=function(n){for(var t,s,r=1,e="",u="",h=[0],p=function(n){1===r&&(n||(e=e.replace(/^\s*\n\s*|\s*\n\s*$/g,"")))?h.push(0,n,e):3===r&&(n||e)?(h.push(3,n,e),r=2):2===r&&"..."===e&&n?h.push(4,n,0):2===r&&e&&!n?h.push(5,0,!0,e):r>=5&&((e||!n&&5===r)&&(h.push(r,0,e,s),r=6),n&&(h.push(r,n,0,s),r=6)),e="";},a=0;a<n.length;a++){a&&(1===r&&p(),p(a));for(var l=0;l<n[a].length;l++)t=n[a][l],1===r?"<"===t?(p(),h=[h],r=3):e+=t:4===r?"--"===e&&">"===t?(r=1,e=""):e=t+e[0]:u?t===u?u="":e+=t:'"'===t||"'"===t?u=t:">"===t?(p(),r=1):r&&("="===t?(r=5,s=e,e=""):"/"===t&&(r<5||">"===n[a][l+1])?(p(),3===r&&(h=h[0]),r=h,(h=h[0]).push(2,0,r),r=0):" "===t||"\t"===t||"\n"===t||"\r"===t?(p(),r=2):e+=t),3===r&&"!--"===e&&(r=4,h=h[0]);}return p(),h}(s)),r),arguments,[])).length>1?r:r[0]}
|
||||||
|
|
||||||
|
export default htm_module;
|
14
webroot/js/web_modules/import-map.json
Normal file
14
webroot/js/web_modules/import-map.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"@joeattardi/emoji-button": "./@joeattardi/emoji-button.js",
|
||||||
|
"@justinribeiro/lite-youtube": "./@justinribeiro/lite-youtube.js",
|
||||||
|
"@videojs/http-streaming/dist/videojs-http-streaming.min.js": "./@videojs/http-streaming/dist/videojs-http-streaming.min.js",
|
||||||
|
"@videojs/themes/fantasy/index.css": "./@videojs/themes/fantasy/index.css",
|
||||||
|
"htm": "./htm.js",
|
||||||
|
"preact": "./preact.js",
|
||||||
|
"showdown": "./showdown.js",
|
||||||
|
"tailwindcss/dist/tailwind.min.css": "./tailwindcss/dist/tailwind.min.css",
|
||||||
|
"video.js/dist/video-js.min.css": "./videojs/dist/video-js.min.css",
|
||||||
|
"video.js/dist/video.min.js": "./videojs/dist/video.min.js"
|
||||||
|
}
|
||||||
|
}
|
3
webroot/js/web_modules/preact.js
Normal file
3
webroot/js/web_modules/preact.js
Normal file
File diff suppressed because one or more lines are too long
5044
webroot/js/web_modules/showdown.js
Normal file
5044
webroot/js/web_modules/showdown.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user