Avatar

rayman

8 public vals
Joined July 23, 2023

Quill.js WYSIWYG

Basic WYSIWYG rich text editor, using quill.js.

Press the "Get HTML" button to show the HTML in an alert window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
export default async function(req: Request) {
if (req.method === "POST") {
const name = (await req.formData()).get("name");
return new Response("Hello World");
}
return new Response(
`<html>
<head>
<title>Title</title>
<style>{"html { font-family: sans-serif; }"}</style>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
<script>htmx.logAll()</script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.js"></script>
</head>
<body>
<div>
<button hx-on:click="alert(quill.getSemanticHTML())">Get HTML</button>
</div>
<br />
<div id="editor" hx-on:click="console.log(quill.getSemanticHTML())">
<div id="editor-container"></div>
<p>Hello World!</p>
<p>
Some initial <strong>bold</strong> text
</p>
<p>
<br />
</p>
</div>
<script>
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // toggled buttons
["blockquote", "code-block"],
["link", "image", "video", "formula"],
[{ "header": 1 }, { "header": 2 }], // custom button values
[{ "list": "ordered" }, { "list": "bullet" }, { "list": "check" }],
[{ "script": "sub" }, { "script": "super" }], // superscript/subscript
[{ "indent": "-1" }, { "indent": "+1" }], // outdent/indent
[{ "size": ["small", false, "large", "huge"] }], // custom dropdown
[{ "header": [1, 2, 3, 4, 5, 6, false] }],
[{ "color": [] }, { "background": [] }], // dropdown with defaults from theme
[{ "font": [] }],
[{ "align": [] }],
["clean"], // remove formatting button
];
let options = {
debug: 'info',
modules: {
toolbar: toolbarOptions,
},
theme: 'snow',
};
let quill = new Quill('#editor', options)
const container = quill.addContainer('ql-custom');
</script>
</body>
</html>`,
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}

Quill.js WYSIWYG

Basic WYSIWYG rich text editor, using quill.js.

Press the "Get HTML" button to show the HTML in an alert window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
export default async function(req: Request) {
if (req.method === "POST") {
const name = (await req.formData()).get("name");
return new Response("Hello World");
}
return new Response(
`<html>
<head>
<title>Quill Editor</title>
<style>{"html { font-family: sans-serif; }"}</style>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
<script>htmx.logAll()</script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.snow.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.js"></script>
</head>
<body>
<div id="editor-view" style="width:100vw">
<div id="outer-buttons">
<button hx-on:click="alert(quill.getSemanticHTML())">Get HTML</button>
</div>
<br />
<div id="editor" hx-on:click="console.log(quill.getSemanticHTML())">
<div id="editor-container"></div>
<p>Hello World!</p>
<p>
Some initial <strong>bold</strong> text
</p>
<p>
<br />
</p>
</div>
</div>
<script>
const toolbarOptions = [
["bold", "italic", "underline", "strike"], // toggled buttons
["blockquote", "code-block"],
["link", "image", "video", "formula"],
[{ "header": 1 }, { "header": 2 }], // custom button values
[{ "list": "ordered" }, { "list": "bullet" }, { "list": "check" }],
[{ "script": "sub" }, { "script": "super" }], // superscript/subscript
[{ "indent": "-1" }, { "indent": "+1" }], // outdent/indent
[{ "size": ["small", false, "large", "huge"] }], // custom dropdown
[{ "header": [1, 2, 3, 4, 5, 6, false] }],
[{ "color": [] }, { "background": [] }], // dropdown with defaults from theme
[{ "font": [] }],
[{ "align": [] }],
["clean"], // remove formatting button
];
let options = {
debug: 'info',
modules: {
toolbar: toolbarOptions,
},
theme: 'snow',
};
let quill = new Quill('#editor', options)
const container = quill.addContainer('ql-custom');
</script>
</body>
</html>`,
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/** @jsxImportSource https://esm.sh/preact */
import { render } from "npm:preact-render-to-string";
// import Quill from "npm:quill";
export default async function(req: Request) {
if (req.method === "POST") {
const name = (await req.formData()).get("name");
return new Response(render(<>Hello {name || "World"}!</>));
}
return new Response(
render(
<html>
<head>
<title>Title</title>
<style>{"html { font-family: sans-serif; }"}</style>
<script src="https://unpkg.com/htmx.org@1.9.9"></script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.core.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.0/dist/quill.core.js"></script>
</head>
<body>
<div id="editor" hx-on:load='let quill = new Quill("#editor")'>
<p>Hello World!</p>
<p>
Some initial <strong>bold</strong> text
</p>
<p>
<br />
</p>
</div>
</body>
</html>,
),
{
headers: {
"Content-Type": "text/html; charset=utf-8",
},
},
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import { createCanvas } from "https://deno.land/x/canvas/mod.ts";
import { formatTitle } from "https://esm.town/v/rayman/FormatTitle";
// Dimensions for the image
const width = 1200;
const height = 626;
const post = {
title: "Draw and save images with Canvas",
};
// Instantiate the canvas object
const canvas = createCanvas(width, height);
const context = canvas.getContext("2d");
// Extract the starting Y value for the title's position, which
// we'll move if we add a second line.
const titleY = 170;
// Set the line height of the text, which varies based on the
// font size and family.
const lineHeight = 80;
// Fill the rectangle with purple
context.fillStyle = "#764abc";
context.fillRect(0, 0, width, height);
context.font = "bold 40pt 'Sans serif'";
context.textAlign = "center";
context.fillStyle = "#fff";
// Format the title and render to the canvas.
const text = formatTitle(post.title);
context.fillText(text[0], 300, titleY);
// If we need a second line, we move use the titleY and lineHeight
// to find the appropriate Y value.
if (text[1]) context.fillText(text[1], 300, titleY + lineHeight);
// Send back as a response
const buffer = canvas.toBuffer("image/png");
export default () => {
return new Response(buffer, { headers: { "Content-Type": "image/png" } });
};
1
2
3
4
5
6
7
8
import { text2png } from "https://esm.town/v/nilslice/libtext2png";
export default async function(req: Request): Promise<Response> {
const img = await text2png("Just give me the PNG", "magenta", 30); // returns a `Blob`
return new Response(img, {
headers: { "Content-type": "image/png" },
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** @jsxImportSource https://esm.sh/solid-jsx */
import StlViewer from "npm:react-stl-viewer";
import { renderToString } from "npm:solid-js/web";
function StlViewer() {
return (
<StlViewer
url="http://www.example.com/example-url.stl"
width={400}
height={400}
modelColor="#B92C2C"
backgroundColor="#EAEAEA"
rotate={true}
orbitControls={true}
/>
);
}
export const solidExample = async () =>
new Response(
await renderToString(() => (
<html>
<div>Test {1 + 1}</div>
</html>
)),
{
headers: {
"Content-Type": "text/html",
},
},
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { verify_discord_signature } from "https://esm.town/v/mattx/verify_discord_signature?v=8";
import { insertIntoDiscordQueue } from "https://esm.town/v/rayman/insertIntoDiscordQueue1";
import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
import { example1 } from "https://esm.town/v/stevekrouse/example1?v=3";
import process from "node:process";
export let valBotEndpoint = async (
req: express.Request,
res: express.Response,
) => {
if (!req.get("X-Signature-Timestamp") || !req.get("X-Signature-Ed25519")) {
res.status(400);
res.end("Signature headers missing");
}
const verified = await verify_discord_signature(
process.env.valbot_pubkey,
JSON.stringify(req.body),
req.get("X-Signature-Ed25519"),
req.get("X-Signature-Timestamp"),
);
if (!verified) {
res.status(401);
res.end("signature invalid");
return;
}
res.set("Content-type", "application/json");
console.log(req);
console.log(res);
switch (req.body.type) {
case 1: // PING interaction
res.json({ type: 1 }); // PONG
break;
case 2: // APPLICATION_COMMAND interactions
// TODO: Probably don't use a nested switch here
// This switch uses the name of your commands. The code below is based on a registered
// slash command called 'ping'
switch (req.body.data.name) {
case "ping":
res.json({
channel_id: "1142405377896497183",
type: 4,
data: {
channel_id: "1142405377896497183",
content: `Hello World! example1 is: ${example1}`,
},
});
break;
case "poke":
console.log(req.body);
let targetID = req.body.data.target_id;
let poker = `<@${req.body.member.user.id}>`;
let pokee = `<@${req.body.data.resolved.users[targetID].id}>`;
console.log([pokee, poker]);
res.json({
type: 4,
channel_id: "1142405377896497183",
data: {
// Tells the recipient who made this gesture to them.
type: 0,
channel_id: "1142405377896497183",
flags: 2,
content: `${pokee} has been poked by ${poker}`,
},
});
break;
case "queue":
// console.log(req.body);
let queueMember = [req.body.member.user.id, req.body.member.user.username];
let queueList = await sqlite.execute(`SELECT
*
FROM
discord_q;`);
// console.log(queueMember);
console.log(queueList.rows);
insertIntoDiscordQueue(queueMember[1], queueMember[0], 1200);
res.json({
type: 4,
channel_id: "1142405377896497183",
data: {
// type: 0,
channel_id: "1142405377896497183",
flags: 2,
content: "",
// <@&1174180748203405433>
"embeds": [
{
"type": "rich",
"title": `Ranked Ladder Queue`,
"description": `Players looking for games or currently playing:
${
[...queueList.rows].map(e => `
**Player:** <@${e[1]}> **Rating:** ${e[2]}
`).join(" ")
}
`,
"color": 0xafa825,
},
],
"allowed_mentions": {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { verify_discord_signature } from "https://esm.town/v/mattx/verify_discord_signature";
import { formatInput } from "https://esm.town/v/rayman/formatInput";
import { fetch } from "https://esm.town/v/std/fetch";
import { example1 } from "https://esm.town/v/stevekrouse/example1?v=3";
import process from "node:process";
export let mgsrBotEndpoint = async (
req: express.Request,
res: express.Response,
) => {
console.log(req.get("X-Signature-Timestamp"));
console.log(req.get("X-Signature-Ed25519"));
if (!req.get("X-Signature-Timestamp") || !req.get("X-Signature-Ed25519")) {
res.status(400);
res.end("Signature headers missing!");
}
const verified = await verify_discord_signature(
process.env.discord_pubkey,
JSON.stringify(req.body),
req.get("X-Signature-Ed25519"),
req.get("X-Signature-Timestamp"),
);
if (!verified) {
res.status(401);
res.end("signature invalid");
return;
}
res.set("Content-type", "application/json");
switch (req.body.type) {
case 1: // PING interaction
res.json({ type: 1 }); // PONG
break;
case 2: // APPLICATION_COMMAND interactions
// TODO: Probably don't use a nested switch here
switch (req.body.data.name) {
case "ping":
res.json({
type: 4,
data: {
content: `Hello World! example1 is: ${example1}`,
},
});
break;
case "eval":
res.end(JSON.stringify({
type: 4,
data: {
content: `${
JSON.stringify(
await (await fetch(
"https://api.val.town/v1/eval/"
+ encodeURIComponent(req.body.data.options[0].value),
{
"headers": { "Content-Type": "application/json" },
},
)).text(),
)
}`,
},
}));
break;
// Helper function to show the user an ephemeral message how to undo a recorded game.
case "Undo Help":
res.json({
type: 4,
data: {
content: `\`/undo-record leaderboard:mgsr2 versus:1\``,
flags: 64, // 1 << 6, EPHEMERAL
},
});
break;
case "Result Formatter":
console.log(req.body.data.name);
let messagekey = req.body.data.target_id;
let content = req.body.data.resolved.messages[messagekey].content;
let resultString = formatInput(content);
console.log(resultString);
res.json({
type: 4,
data: {
content: `/game record leaderboard: mgsr2 result: ${resultString}`,
flags: 64, // 1 << 6, EPHEMERAL
},
});
break;
case "Result Formatter (PC Compatible)":
console.log(req.body.data.name);
let messagekeyPC = req.body.data.target_id;
let contentPC = req.body.data.resolved.messages[messagekeyPC].content;
let resultStringPC = formatInput(contentPC);
console.log(resultStringPC);
res.json({
type: 4,
data: {
content: `\`/game record leaderboard: mgsr2 result: ${resultStringPC}\``,
flags: 64, // 1 << 6, EPHEMERAL
},
});
break;
}
Next