various tests

This commit is contained in:
madrilene 2022-10-14 15:00:52 +02:00
parent dfc55aafa9
commit 3bcf6f15af
15 changed files with 139 additions and 380 deletions

View file

@ -7,6 +7,9 @@
* - `src/config/transforms.js`
*/
// get package.json
const pkg = require('./package.json');
// module import filters
const {
wordCount,
@ -109,6 +112,12 @@ module.exports = eleventyConfig => {
// --------------------- Passthrough File Copy -----------------------
// webc js and css dependencies
eleventyConfig.addPassthroughCopy({
'src/_includes/webc/*.css': `assets/components/`,
'src/_includes/webc/*.js': `assets/components/`
});
// node modules
eleventyConfig.addPassthroughCopy({
'node_modules/speedlify-score/speedlify-score.css': `assets/components/speedlify-score.css`,

View file

@ -7,6 +7,12 @@
wcagLevel = 'WCAG2AAA'
[[plugins]]
package = "netlify-plugin-cache"
[plugins.inputs]
paths = [ ".cache" ]
[[headers]]
for = "/*"
[headers.values]

16
package-lock.json generated
View file

@ -27,6 +27,7 @@
"cross-env": "^7.0.3",
"cssnano": "^5.1.7",
"dayjs": "^1.11.5",
"dotenv": "^16.0.3",
"esbuild": "^0.15.10",
"eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",
@ -1628,6 +1629,15 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -8294,6 +8304,12 @@
"domhandler": "^4.2.0"
}
},
"dotenv": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
"dev": true
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",

View file

@ -9,11 +9,11 @@
"scripts": {
"clean": "rimraf dist",
"dev:postcss": "postcss src/assets/css/global.css --o dist/assets/css/global.css --watch --verbose",
"dev:scripts": "esbuild src/assets/scripts/app.js src/assets/scripts/is-land.js --bundle --watch --outdir=dist/assets",
"dev:scripts": "esbuild src/assets/scripts/app.js --bundle --watch --outdir=dist/assets",
"dev:11ty": "eleventy --serve --watch",
"build:postcss": "NODE_ENV=production postcss src/assets/css/global.css -o dist/assets/css/global.css",
"build:11ty": "cross-env ELEVENTY_ENV=production eleventy",
"build:scripts": "esbuild src/assets/scripts/app.js src/assets/scripts/is-land.js --bundle --minify --outdir=dist/assets --platform=node --tree-shaking=true",
"build:scripts": "esbuild src/assets/scripts/app.js --bundle --minify --outdir=dist/assets --platform=node --tree-shaking=true",
"start": "run-p dev:*",
"build": "run-s clean build:*"
},
@ -43,6 +43,7 @@
"cross-env": "^7.0.3",
"cssnano": "^5.1.7",
"dayjs": "^1.11.5",
"dotenv": "^16.0.3",
"esbuild": "^0.15.10",
"eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",

14
src/_data/github.js Normal file
View file

@ -0,0 +1,14 @@
const EleventyFetch = require('@11ty/eleventy-fetch');
module.exports = async function () {
let url = 'https://api.github.com/users/madrilene/repos';
// returning promise
let data = await EleventyFetch(url, {
duration: '1d',
type: 'json'
});
return data;
};

View file

@ -1,3 +1,5 @@
const package = require('../../package.json');
module.exports = {
siteName: 'Lene Saile',
siteDescription:
@ -32,5 +34,6 @@ module.exports = {
menu: {
closedText: 'Menu'
},
env: process.env.ELEVENTY_ENV === 'production'
env: process.env.ELEVENTY_ENV === 'production',
pkv: package.version || 'v1'
};

View file

@ -12,6 +12,10 @@
{
"text": "WebC",
"url": "/test/"
},
{
"text": "Github",
"url": "/github/"
}
]
}

View file

@ -0,0 +1,21 @@
<marquee>Lorem ipsum dolor sit amet, consectetur</marquee>
<style webc:scoped>
:host:defined {
font-size: 3rem;
}
</style>
<script>
customElements.define(
'my-marquee',
class extends HTMLElement {
connectedCallback() {
console.log(this);
this.addEventListener('click', () => {
console.log('clicked');
});
}
}
);
</script>

View file

@ -0,0 +1,14 @@
<speedlify-score
webc:raw
:class="this.class"
:hash="this.hash"
speedlify-url="https://www.speedlify.dev"
:score="this.score"
:weight="this.weight"
:requests="this.requests"
></speedlify-score>
<template>
<link rel="stylesheet" :href="`/components/speedlify-score.css`" />
<script :src="`/components/speedlify-score.js`"></script>
</template>

View file

@ -1,31 +1,21 @@
<is-land
on:visible
:import="`/web/dist/${this.pkg.version}/lite-yt-embed.js`"
class="fluid-width-video-wrapper"
<lite-youtube
:videoid="this.slug"
:params="this.start ? `start=${this.start}` : false"
:playlabel="`Play${this.label ? `: ${this.label}` : ''}`"
:style="`background-image:url('${this.poster || `https://i.ytimg.com/vi/${this.slug}/maxresdefault.jpg`}'); max-width: 100%`"
>
<lite-youtube
:videoid="this.slug"
:params="this.start ? `start=${this.start}` : false"
:playlabel="`Play${this.label ? `: ${this.label}` : ''}`"
:style="`background-image:url('${this.poster || `https://i.ytimg.com/vi/${this.slug}/maxresdefault.jpg`}'); max-width: 100%`"
>
<a
:href="`https://youtube.com/watch?v=${this.slug}`"
class="lty-playbtn"
title="Play Video"
><span
class="lyt-visually-hidden"
@html="`Play Video${this.label ? `: ${this.label}` : ''}`"
></span
></a>
</lite-youtube>
<template data-island>
<style>
/* Plugin bug: clicking the red youtube play icon in the center would navigate to youtube.com */
lite-youtube:defined .lty-playbtn {
pointer-events: none;
}
</style>
<link rel="stylesheet" :href="`/web/dist/${this.pkg.version}/lite-yt-embed.css`" />
</template>
</is-land>
<a
:href="`https://youtube.com/watch?v=${this.slug}`"
class="lty-playbtn"
title="Play Video"
><span
class="lyt-visually-hidden"
@html="`Play Video${this.label ? `: ${this.label}` : ''}`"
></span
></a>
</lite-youtube>
<!-- <template>
<link rel="stylesheet" :href="/assets/components/lite-yt-embed.css" />
<script :src="/assets/components/lite-yt-embed.js"></script>
</template> -->

View file

@ -1,5 +1,3 @@
import {testGSAP} from './components/gsap';
// ------------------- cards redundant click, accessible whole card clickable solution by Heydon Pickering
const cards = [...document.querySelectorAll('.card')];
@ -62,7 +60,3 @@ document.querySelectorAll('img').forEach(img => {
}
img.addEventListener('load', () => img.removeAttribute('data-is-loading'));
});
// GSAP
// testGSAP();

View file

@ -1,341 +0,0 @@
const islandOnceCache = new Map();
class Island extends HTMLElement {
static tagName = 'is-land';
static fallback = {
':not(:defined)': (readyPromise, node, prefix) => {
// remove from document to prevent web component init
let cloned = document.createElement(prefix + node.localName);
for (let attr of node.getAttributeNames()) {
cloned.setAttribute(attr, node.getAttribute(attr));
}
let children = Array.from(node.childNodes);
for (let child of children) {
cloned.append(child); // Keep the *same* child nodes, clicking on a details->summary child should keep the state of that child
}
node.replaceWith(cloned);
return readyPromise.then(() => {
// restore children (not cloned)
for (let child of Array.from(cloned.childNodes)) {
node.append(child);
}
cloned.replaceWith(node);
});
}
};
static autoinit = {
'petite-vue': function (library) {
library.createApp().mount(this);
},
'vue': function (library) {
library.createApp().mount(this);
},
'svelte': function (mod) {
new mod.default({target: this});
},
'svelte-ssr': function (mod) {
new mod.default({target: this, hydrate: true});
},
'preact': function (mod) {
mod.default(this);
}
};
constructor() {
super();
this.attrs = {
autoInitType: 'autoinit',
import: 'import',
template: 'data-island',
ready: 'ready'
};
this.conditionMap = {
'visible': Conditions.visible,
'idle': Conditions.idle,
'interaction': Conditions.interaction,
'media': Conditions.media,
'save-data': Conditions.saveData
};
// Internal promises
this.ready = new Promise((resolve, reject) => {
this.readyResolve = resolve;
this.readyReject = reject;
});
}
static getParents(el, selector, stopAt = false) {
let nodes = [];
while (el) {
if (el.matches && el.matches(selector)) {
if (stopAt && el === stopAt) {
break;
}
nodes.push(el);
}
el = el.parentNode;
}
return nodes;
}
static async ready(el) {
let parents = Island.getParents(el, Island.tagName);
let imports = await Promise.all(parents.map(el => el.wait()));
// return innermost module import
if (imports.length) {
return imports[0];
}
}
async forceFallback() {
let prefix = Island.tagName + '--';
let promises = [];
if (window.Island) {
Object.assign(Island.fallback, window.Island.fallback);
}
for (let selector in Island.fallback) {
// Reverse here as a cheap way to get the deepest nodes first
let components = Array.from(this.querySelectorAll(selector)).reverse();
// with thanks to https://gist.github.com/cowboy/938767
for (let node of components) {
if (!node.isConnected || node.localName === Island.tagName) {
continue;
}
let readyPromise = Island.ready(node);
promises.push(Island.fallback[selector](readyPromise, node, prefix));
}
}
return promises;
}
wait() {
return this.ready;
}
getConditions() {
let map = {};
for (let key of Object.keys(this.conditionMap)) {
if (this.hasAttribute(`on:${key}`)) {
map[key] = this.getAttribute(`on:${key}`);
}
}
return map;
}
async connectedCallback() {
// Keep fallback content without initializing the components
// TODO improvement: only run this for not-eager components?
await this.forceFallback();
await this.hydrate();
}
getTemplates() {
return this.querySelectorAll(`:scope template[${this.attrs.template}]`);
}
replaceTemplates(templates) {
// replace <template> with the live content
for (let node of templates) {
if (Island.getParents(node, Island.tagName, this).length > 0) {
continue;
}
let value = node.getAttribute(this.attrs.template);
// get rid of the rest of the content on the island
if (value === 'replace') {
let children = Array.from(this.childNodes);
for (let child of children) {
this.removeChild(child);
}
this.appendChild(node.content);
break;
} else {
if (value === 'once' && node.innerHTML) {
if (islandOnceCache.has(node.innerHTML)) {
node.remove();
return;
}
islandOnceCache.set(node.innerHTML, true);
}
node.replaceWith(node.content);
}
}
}
async hydrate() {
let conditions = [];
if (this.parentNode) {
// wait for all parents before hydrating
conditions.push(Island.ready(this.parentNode));
}
let attrs = this.getConditions();
for (let condition in attrs) {
if (this.conditionMap[condition]) {
conditions.push(this.conditionMap[condition](attrs[condition], this));
}
}
// Loading conditions must finish before dependencies are loaded
await Promise.all(conditions);
this.replaceTemplates(this.getTemplates());
let mod;
// [dependency="my-component-code.js"]
let importScript = this.getAttribute(this.attrs.import);
if (importScript) {
// we could resolve import maps here manually but youd still have to use the full URL in your scripts import anyway
mod = await import(importScript);
}
if (mod) {
// Use `import=""` for when import maps are available e.g. `import="petite-vue"`
let fn =
Island.autoinit[this.getAttribute(this.attrs.autoInitType) || importScript];
if (fn) {
await fn.call(this, mod);
}
}
this.readyResolve({
import: mod
});
this.setAttribute(this.attrs.ready, '');
}
}
class Conditions {
static visible(noop, el) {
if (!('IntersectionObserver' in window)) {
// runs immediately
return;
}
return new Promise(resolve => {
let observer = new IntersectionObserver(entries => {
let [entry] = entries;
if (entry.isIntersecting) {
observer.unobserve(entry.target);
resolve();
}
});
observer.observe(el);
});
}
// TODO make sure this runs after all of the conditions have finished, otherwise it will
// finish way before the other lazy loaded promises and will be the same as a noop when
// on:interaction or on:visible finishes much later
static idle() {
let onload = new Promise(resolve => {
if (document.readyState !== 'complete') {
window.addEventListener('load', () => resolve(), {once: true});
} else {
resolve();
}
});
if (!('requestIdleCallback' in window)) {
// run immediately
return onload;
}
// both idle and onload
return Promise.all([
new Promise(resolve => {
requestIdleCallback(() => {
resolve();
});
}),
onload
]);
}
static interaction(eventOverrides, el) {
let events = ['click', 'touchstart'];
// event overrides e.g. on:interaction="mouseenter"
if (eventOverrides) {
events = (eventOverrides || '').split(',').map(entry => entry.trim());
}
return new Promise(resolve => {
function resolveFn(e) {
resolve();
// cleanup the other event handlers
for (let name of events) {
el.removeEventListener(name, resolveFn);
}
}
for (let name of events) {
el.addEventListener(name, resolveFn, {once: true});
}
});
}
static media(query) {
let mm = {
matches: true
};
if (query && 'matchMedia' in window) {
mm = window.matchMedia(query);
}
if (mm.matches) {
return;
}
return new Promise(resolve => {
mm.addListener(e => {
if (e.matches) {
resolve();
}
});
});
}
static saveData(expects) {
// return early if API does not exist
if (
!('connection' in navigator) ||
navigator.connection.saveData === (expects !== 'false')
) {
return Promise.resolve();
}
// dangly promise
return new Promise(() => {});
}
}
// Should this auto define? Folks can redefine later using { component } export
if ('customElements' in window) {
window.customElements.define(Island.tagName, Island);
window.Island = Island;
}
export const component = Island;
export const ready = Island.ready;

16
src/pages/github.njk Normal file
View file

@ -0,0 +1,16 @@
---
title: Github
permalink: /github/index.html
description: This is just a testing environment
layout: page
---
<ul>
{% for repository in github %}
<li>
<a href="{{ repository.html_url }}">{{ repository.name }} </a>
</li>
{% else %}
<li>This would display if the 'item' collection were empty</li>
{% endfor %}
</ul>

View file

@ -5,11 +5,23 @@ description: This is just a testing environment
layout: page
---
Version number {{ meta.pkv }}
<!-- sdfg -->
{% renderTemplate "webc" %}
<my-marquee>dsfgdfg</my-marquee>
{% endrenderTemplate %}
<p>
Icing jelly soufflé shortbread chocolate cake muffin gummies cotton candy lemon drops.
Cake gummi bears dragée chocolate sweet croissant sweet croissant.
</p>
{% renderTemplate "webc" %}
<youtube-lite-player @slug="DC5fP_8Q8uQ" @label="{{ title }}"></youtube-lite-player>
{% endrenderTemplate %}
<h2>Testing counter</h2>
<p>counter inside island, activate on interaction</p>