Skip to content

Commit

Permalink
dweetable, lazy initializing, snippeting
Browse files Browse the repository at this point in the history
  • Loading branch information
colevandersWands committed May 12, 2024
1 parent a65b23c commit 381a92e
Show file tree
Hide file tree
Showing 20 changed files with 7,510 additions and 45 deletions.
8 changes: 8 additions & 0 deletions gather-snippets/interpret/langs/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export const js = ({ title = '', text = '' }) => {
begin: /(\/\/)[\s]*tags[\s]*:/gi,
});

if (title.toLowerCase().endsWith('.dweet.js')) {
tags.push('dweet');
}

let subtext = null;
if (ast && ext(name(title)).replace('.', '') in langs) {
const comments = [];
Expand Down Expand Up @@ -69,5 +73,9 @@ export const js = ({ title = '', text = '' }) => {
}
}

if (title.toLowerCase().endsWith('.dweet.js')) {
text = text.replaceAll(/^\/\/.*/g, '').trim();
}

return { text, forelinks, tags, alt, subtext };
};
2 changes: 1 addition & 1 deletion gather-snippets/interpret/langs/md/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { parse } from 'yaml';

import { langs } from '../index.js';

import { isRelative, name, ext, staticLabels, lang } from '../../utils.js';
import { isRelative, name, ext, lang } from '../../utils.js';

import { interpret } from '../../index.js';

Expand Down
7,201 changes: 7,201 additions & 0 deletions public/bundle/min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/data/links.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/data/snippets.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/data/tags.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
["1-liner","coaithored","esi","frivolous","game","golf","joke","le chat","metappet","minibrary","polyfill","puzzle","quine","reel","remix","sketch","subtext","testing","the fun parts","tribute","useful","useless","variation","wellbeing","wtfjs","wuzzle","yolo","🐰"]
["1-liner","coaithored","dweet","esi","frivolous","game","golf","joke","le chat","metappet","minibrary","polyfill","puzzle","quine","reel","remix","sketch","subtext","testing","the fun parts","tribute","useful","useless","variation","wellbeing","wtfjs","wuzzle","yolo","🐰"]
28 changes: 18 additions & 10 deletions public/src/abstract-snippet-tree/components/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@ export const editor = (snippet) => {
codeContainer.textContent = snippet.text;
editorContainer.appendChild(codeContainer);

// from codeJar
const highlight = (editor) => {
snippet.text = editor.textContent; // side-effect the snippet for danger & copying

// highlight.js does not trims old tags,
// let's do it by this hack.
editor.textContent = editor.textContent;
Prism.highlightElement(editor);
const initializeEditor = (entries, observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.unobserve(editorContainer);

const highlight = (editor) => {
snippet.text = editor.textContent; // side-effect
Prism.highlightElement(editor);
};

const jar = CodeJar(editorContainer.firstChild, highlight, jarConfig(lang));
jar.updateCode(snippet.text);
}
}
};

const jar = CodeJar(editorContainer.firstChild, highlight, jarConfig(lang));
jar.updateCode(snippet.text);
new IntersectionObserver(initializeEditor, {
root: null, // Use the viewport as the root
threshold: 0, // Trigger callback when any part of the target enters the viewport
}).observe(editorContainer);

return editorContainer;
};
21 changes: 21 additions & 0 deletions public/src/abstract-snippet-tree/langs/js/dwitteroot/compress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const compress = (code = '') => {
// replace unicode characters
const codeIn = [...code];
let uniCode = '';
for (let character of codeIn) {
const charCode = character.charCodeAt(0);
if (charCode > 255) character = escape(character).replace(/%u/g, '\\u');
uniCode += character;
}

// 2-1 character compression
let dwitterCompressed = String.fromCharCode(
...[...(uniCode.length % 2 ? uniCode + ';' : uniCode)].map(
(e, i) => e.charCodeAt() | (i % 2 ? 0xdf00 : 0xdb00),
),
);

return 'eval(unescape(escape`' + dwitterCompressed + "`.replace(/u../g,'')))";

// adapted from https://capjs.3d2k.com/
};
135 changes: 135 additions & 0 deletions public/src/abstract-snippet-tree/langs/js/dwitteroot/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { CodeJar } from '../../../../../lib/codejar.min.js';

import { uncompress } from './uncompress.js';
import { compress } from './compress.js';

function dweeterize(s, CodeJar, Prism) {
const dwitterContainer = document.createElement('div');
dwitterContainer.id = s.title + '-dweeting';
dwitterContainer.style =
'display: flex; flex-direction: column; align-items: center; justify-content: center;';
dwitterContainer.innerHTML = `
<canvas id="${s.title}-canvas" width="1920" height="1080" style="width: 75%"> </canvas>
<div style="padding-top: 2em;">
<code style="color: grey">function u(t) {</code>
<pre id="${s.title}-editor" class="editor lang-js"><code>${s.text}</code></pre>
<div style="display: flex; flex-direction: row; justify-content: space-between;">
<div style="display: inline-block;">
<code style="color: grey">} // </code>
<code id="count" style="color: grey"></code>
</div>
<span style="display: inline-block;">
<input id="${s.title}-compress" type="checkbox"/>
<label for="${s.title}-compress" style="margin-left: -0.5em">compress</label>
</span>
</div>
<pre id="${s.title}-out" style="color: red"></pre>
</div>`;

const initializeDweet = (entries, observer) => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.unobserve(dwitterContainer);

let intervalId = 0;
const animationObserver = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) dweeting();
else clearInterval(intervalId);
}
},
{
root: null, // Use the viewport as the root
threshold: 1, // Trigger callback when any part of the target enters the viewport
},
);

animationObserver.observe(dwitterContainer.children[0]);

const editor = dwitterContainer.children[1].children[1];
const out = dwitterContainer.children[1].children[3];
const count = dwitterContainer.children[1].children[2].children[0].children[1];

const dweeting = () => {
Prism.highlightElement(editor);

const dweet = editor.textContent; // side-effect
s.text = dweet;

const dweetLength = [...dweet].length;
count.innerText = dweetLength + '/140';
if (dweetLength > 140) count.style.color = 'red';
else count.style.color = 'grey';

let c = dwitterContainer.children[0];
let x = c.getContext`2d`;
let S = Math.sin;
let C = Math.cos;
let T = Math.tan;
let R = (r = 0, g = 0, b = 0, a = 1) => `rgba(${r},${g},${b},${a})`;

clearInterval(intervalId);

let frame = 0;
let u = () => {};
try {
u = eval(`(t) => {\n\n${dweet}\n\n}`);

x.clearRect(0, 0, c.width, c.height);
out.innerText = '';

intervalId = setInterval(() => {
try {
u(frame++ / 60);
out.innerText = '';
} catch (err) {
console.error(err);
out.innerText = err;
}
}, 16.66666667);
} catch (err) {
u = () => {};
console.error(err);
out.innerText = err;
clearInterval(intervalId);
frame = 0;
}
};

const jar = CodeJar(editor, dweeting);
jar.updateCode(s.text);

const copmryess =
dwitterContainer.children[1].children[2].children[1].children[0];
copmryess.addEventListener('input', (e) => {
if (e.target.checked) {
jar.updateCode(compress(editor.textContent));
} else {
jar.updateCode(uncompress(editor.textContent));
}
editor.setAttribute('contenteditable', !e.target.checked);
});
}
}
};

new IntersectionObserver(initializeDweet, {
root: null, // Use the viewport as the root
threshold: 0, // Trigger callback when any part of the target enters the viewport
}).observe(dwitterContainer);

return dwitterContainer;
}

// some loophole allows this to eval unstrict code in a module
export const dwitteroot = (snippet) =>
new Function(
'snippet',
'CodeJar',
'Prism',
'compress',
'uncompress',
`return (${dweeterize.toString()})(snippet, CodeJar, Prism, compress, uncompress)`,
)(snippet, CodeJar, Prism, compress, uncompress);
25 changes: 25 additions & 0 deletions public/src/abstract-snippet-tree/langs/js/dwitteroot/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, it, expect } from '../../../../../../snippets/testing.mjs';

import { compress } from './compress.js';
import { uncompress } from './uncompress.js';

describe('compressing and uncompressing dweets', () => {
it('should compress code', () => {
expect(compress('const x = 3;')).toEqual(
"eval(unescape(escape`󨽯󫭳󭌠󮌠󟜠󜼻`.replace(/u../g,'')))",
);
});
it('should uncompress code', () => {
expect(uncompress("eval(unescape(escape`󨽯󫭳󭌠󮌠󟜠󜼻`.replace(/u../g,'')))")).toEqual(
'const x = 3;',
);
});
it('should be one identity', () => {
expect(uncompress(compress('const x = 3;'))).toEqual('const x = 3;');
});
it('should be the other identity', () => {
expect(
compress(uncompress("eval(unescape(escape`󨽯󫭳󭌠󮌠󟜠󜼻`.replace(/u../g,'')))")),
).toEqual("eval(unescape(escape`󨽯󫭳󭌠󮌠󟜠󜼻`.replace(/u../g,'')))");
});
});
15 changes: 15 additions & 0 deletions public/src/abstract-snippet-tree/langs/js/dwitteroot/uncompress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const uncompress = (code = '') => {
const i = code.toLowerCase().search(/eval\(unescape\(escape/g);
if (i < 0) return code;

const codeStart = code.slice(0, i);
const codeEnd = code.slice(i);
try {
const newCode = eval(codeEnd.slice(4));
if (newCode) return codeStart + newCode;
} catch (e) {}

return code;

// adapted from https://capjs.3d2k.com/
};
24 changes: 18 additions & 6 deletions public/src/abstract-snippet-tree/langs/js/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { runCode } from './run-code.js';

import { n } from '../../../utils/n.js';

import { revise } from '../../revise.js';

import { txt } from '../txt.js';

import { runCode } from './run-code.js';
import { dwitteroot } from './dwitteroot/index.js';

export const js = {
...txt,
dangerZone: (s = { title: '', text: '' }) => [
n('button', {}, 'run', () => runCode(s)),
n('button', {}, 'debug', () => runCode(s, true)),
],
dangerZone: (s = { title: '', text: '' }) =>
s.title.toLowerCase().endsWith('.dweet.js')
? txt.dangerZone(s)
: [
n('button', {}, 'run', () => runCode(s)),
n('button', {}, 'debug', () => runCode(s, true)),
],
translate: ({ ast, snippet }) =>
snippet.title.toLowerCase().endsWith('.dweet.js')
? revise(ast, (node) =>
node?.attributes?.id?.endsWith('-text') ? dwitteroot(snippet) : node,
)
: ast,
};
2 changes: 1 addition & 1 deletion public/src/abstract-snippet-tree/langs/txt.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const txt = {
}),
],

jarConfig: (lang = '') => ({ tab: '\t' }),
jarConfig: (lang = '') => ({ tab: ' ' }),

translate: ({ ast }) => ast,
};
26 changes: 13 additions & 13 deletions snippets/bunny.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ tags:

# 🐰

If drawing rabbits (🐇) in JavaScript means copying
[patterns out of books](./the-fun-parts.md) or mimicking specific styles from blogs,
drawing bunnies (🐰) is about experimentation and creative expression

To draw a 🐰 is to pervert the conventions of the language. To draw your breath or to get
it all out as fast as possible. It’s an exercise in discovering and pushing the bounds of
your understanding of the language. It’s about reinforcing and challenging JavaScript as a
craft.

In drawing JavaScript 🐰s, you’re always at play. And you’re getting better.

- [Jacob Thornton](https://github.com/fat) from
[_How to draw a Bunny_](https://www.oreilly.com/library/view/beautiful-javascript/9781449371142/ch03.html)
> If drawing rabbits (🐇) in JavaScript means copying
> [patterns out of books](./the-fun-parts.md) or mimicking specific styles from blogs,
> drawing bunnies (🐰) is about experimentation and creative expression
>
> To draw a 🐰 is to pervert the conventions of the language. To draw your breath or to
> get it all out as fast as possible. It’s an exercise in discovering and pushing the
> bounds of your understanding of the language. It’s about reinforcing and challenging
> JavaScript as a craft.
>
> In drawing JavaScript 🐰s, you’re always at play. And you’re getting better.
>
> - [Jacob Thornton](https://github.com/fat) from
> [_How to draw a Bunny_](https://www.oreilly.com/library/view/beautiful-javascript/9781449371142/ch03.html)
7 changes: 6 additions & 1 deletion snippets/coAIthored.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
---
tags:
- metappet
---

# CoAIthored

Co-authored with AI.

<!-- tags: metappet -->

22 changes: 22 additions & 0 deletions snippets/dweet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
tags:
- metappet
---

# Dweet

> Dweeting is a challenge to see what awesomeness you can
> create when limited to only 140 characters of javascript and a canvas. Give it a go!
>
> - [dwitter.net](https://www.dwitter.net/)
Dweets are wrapped in a function named `u` that's called 60 times per second. You can use
these variables:

- `t`: elapsed time in seconds.
- `c`: A 1920x1080 canvas.
- `x`: A 2D context for that canvas.
- `S`: Math.sin
- `C`: Math.cos
- `T`: Math.tan
- `R`: Generates rgba-strings, ex.: R(255, 255, 255, 0.5)
4 changes: 4 additions & 0 deletions snippets/shady-shifter.dweet.draft-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
c.onmousemove=e=>{a=e.clientX;b=e.clientY}
r=c.getBoundingClientRect()
h=(a-r.left)/1920*255*3
c.style.background=R((h+t)%255,(h-t)%255,(h*t)%255,(b-r.top)/1080*3)
3 changes: 3 additions & 0 deletions snippets/shady-shifter.dweet.draft-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
c.onmousemove = e => o = e.clientX
r = c.getBoundingClientRect()
c.style.background = R(t*7%255, t*13%255, t*17%255, ((o-r.left)/1080)*1.8)
5 changes: 5 additions & 0 deletions snippets/shady-shifter.dweet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
t||(d=h=1,o=540)
c.onmousemove=e=>o=e.clientX
c.onclick=_=>d=!d
h=d?t:h
c.style.background=R(h*7%255,h*13%255,h*17%255,((o-c.getBoundingClientRect().left)/1080))
Loading

0 comments on commit 381a92e

Please sign in to comment.