tangled
alpha
login
or
join now
timtinkers.online
/
neocities
1
fork
atom
timconspicuous.neocities.org
1
fork
atom
overview
issues
pulls
pipelines
Lume 3.0 migration
timtinkers.online
6 months ago
b7488599
aed72131
+58
-180
11 changed files
expand all
collapse all
unified
split
.gitignore
_cms.ts
_config.ts
deno.json
mod.ts
plugins.ts
src
_components
Button.tsx
Linktree.tsx
_includes
layout.tsx
index.page.tsx
styles.css
+2
-3
.gitignore
···
1
1
_cache
2
2
-
_site
2
2
+
public/
3
3
deno.lock
4
4
-
.vscode
5
5
-
.env
4
4
+
env
-83
_cms.ts
···
1
1
-
import lumeCMS from "lume/cms/mod.ts";
2
2
-
3
3
-
const cms = lumeCMS();
4
4
-
5
5
-
cms.document(
6
6
-
"home: The profile page",
7
7
-
"src:index.yml",
8
8
-
[
9
9
-
{
10
10
-
type: "hidden",
11
11
-
name: "layout",
12
12
-
value: "layouts/home.vto",
13
13
-
},
14
14
-
{
15
15
-
type: "object",
16
16
-
name: "header",
17
17
-
description: "The header of the page",
18
18
-
fields: [
19
19
-
"title: text",
20
20
-
"description: markdown",
21
21
-
"avatar: file",
22
22
-
],
23
23
-
},
24
24
-
{
25
25
-
type: "object",
26
26
-
name: "metas",
27
27
-
description: "Data for the meta tags",
28
28
-
fields: [
29
29
-
"title: text",
30
30
-
"description: text",
31
31
-
"image: text",
32
32
-
"twitter: text",
33
33
-
"generator: checkbox",
34
34
-
],
35
35
-
},
36
36
-
{
37
37
-
name: "links",
38
38
-
type: "object-list",
39
39
-
description: "The list of links.",
40
40
-
fields: [
41
41
-
{
42
42
-
type: "text",
43
43
-
name: "type",
44
44
-
description:
45
45
-
"The type of link. It uses the icons and colors from https://simpleicons.org/. For example, 'github', 'instagram', etc.",
46
46
-
options: [
47
47
-
"github",
48
48
-
"instagram",
49
49
-
"linkedin",
50
50
-
"x",
51
51
-
"youtube",
52
52
-
"facebook",
53
53
-
"tiktok",
54
54
-
"patreon",
55
55
-
"paypal",
56
56
-
"mastodon",
57
57
-
"discord",
58
58
-
"spotify",
59
59
-
"opencollective",
60
60
-
"twitch",
61
61
-
],
62
62
-
},
63
63
-
"text: text",
64
64
-
"href: text",
65
65
-
"only_icon: checkbox",
66
66
-
],
67
67
-
},
68
68
-
{
69
69
-
name: "extra_head",
70
70
-
type: "code",
71
71
-
description: "Extra content to include in the <head> tag",
72
72
-
},
73
73
-
{
74
74
-
name: "footer",
75
75
-
type: "markdown",
76
76
-
description: "The footer of the page",
77
77
-
},
78
78
-
],
79
79
-
);
80
80
-
81
81
-
cms.upload("uploads: Uploaded files", "src:*{.jpg,.svg}");
82
82
-
83
83
-
export default cms;
+10
-3
_config.ts
···
1
1
import lume from "lume/mod.ts";
2
2
-
import plugins from "./plugins.ts";
2
2
+
import jsx from "lume/plugins/jsx.ts";
3
3
+
import postcss from "lume/plugins/postcss.ts";
4
4
+
import simpleIcons from "https://deno.land/x/lume_icon_plugins@v0.2.4/simpleicons.ts";
3
5
4
6
const site = lume({
5
7
src: "./src",
8
8
+
dest: "./public"
6
9
});
7
10
8
8
-
site.use(plugins());
11
11
+
site.use(jsx());
12
12
+
site.use(postcss());
13
13
+
site.add("styles.css");
14
14
+
site.copy([".jpg", ".svg"]);
15
15
+
site.use(simpleIcons());
9
16
10
10
-
export default site;
17
17
+
export default site;
+33
-23
deno.json
···
1
1
{
2
2
-
"imports": {
3
3
-
"lume/": "https://deno.land/x/lume@v2.4.2/",
4
4
-
"lume/cms/": "https://cdn.jsdelivr.net/gh/lumeland/cms@0.7.3/"
5
5
-
},
6
6
-
"tasks": {
7
7
-
"lume": "echo \"import 'lume/cli.ts'\" | deno run -A -",
8
8
-
"build": "deno task lume",
9
9
-
"serve": "deno task lume -s"
10
10
-
},
11
11
-
"compilerOptions": {
12
12
-
"types": [
13
13
-
"lume/types.ts"
14
14
-
],
15
15
-
"jsx": "react-jsx",
16
16
-
"jsxImportSource": "npm:preact"
17
17
-
},
18
18
-
"exclude": [
19
19
-
"./_site"
20
20
-
],
21
21
-
"fmt": {
22
22
-
"useTabs": true,
23
23
-
"indentWidth": 4
24
24
-
}
2
2
+
"imports": {
3
3
+
"lume/": "https://deno.land/x/lume@v3.0.8/",
4
4
+
"lume/cms/": "https://cdn.jsdelivr.net/gh/lumeland/cms@0.12.5/",
5
5
+
"lume/jsx-runtime": "https://deno.land/x/ssx@v0.1.12/jsx-runtime.ts"
6
6
+
},
7
7
+
"tasks": {
8
8
+
"lume": "echo \"import 'lume/cli.ts'\" | deno run -A -",
9
9
+
"build": "deno task lume",
10
10
+
"serve": "deno task lume -s"
11
11
+
},
12
12
+
"compilerOptions": {
13
13
+
"types": [
14
14
+
"lume/types.ts"
15
15
+
],
16
16
+
"jsx": "react-jsx",
17
17
+
"jsxImportSource": "lume"
18
18
+
},
19
19
+
"exclude": [
20
20
+
"./public"
21
21
+
],
22
22
+
"fmt": {
23
23
+
"useTabs": true,
24
24
+
"indentWidth": 4
25
25
+
},
26
26
+
"unstable": [
27
27
+
"temporal",
28
28
+
"fmt-component"
29
29
+
],
30
30
+
"lint": {
31
31
+
"plugins": [
32
32
+
"https://deno.land/x/lume@v3.0.8/lint.ts"
33
33
+
]
34
34
+
}
25
35
}
-25
mod.ts
···
1
1
-
import plugins from "./plugins.ts";
2
2
-
3
3
-
import "lume/types.ts";
4
4
-
5
5
-
export default function () {
6
6
-
return (site: Lume.Site) => {
7
7
-
// Configure the site
8
8
-
site.use(plugins());
9
9
-
10
10
-
// Add remote files
11
11
-
const files = [
12
12
-
"_includes/css/header.css",
13
13
-
"_includes/css/link.css",
14
14
-
"_includes/layouts/base.vto",
15
15
-
"index.yml",
16
16
-
"styles.css",
17
17
-
"favicon.svg",
18
18
-
"avatar.jpg",
19
19
-
];
20
20
-
21
21
-
for (const file of files) {
22
22
-
site.remoteFile(file, import.meta.resolve(`./src/${file}`));
23
23
-
}
24
24
-
};
25
25
-
}
-32
plugins.ts
···
1
1
-
import "lume/types.ts";
2
2
-
import Color from "npm:colorjs.io@0.5.2";
3
3
-
import simpleIcons from "https://deno.land/x/lume_icon_plugins@v0.1.1/simpleicons.ts";
4
4
-
import basePath from "lume/plugins/base_path.ts";
5
5
-
import favicon from "lume/plugins/favicon.ts";
6
6
-
import metas from "lume/plugins/metas.ts";
7
7
-
import postcss from "lume/plugins/postcss.ts";
8
8
-
import transformImages from "lume/plugins/transform_images.ts";
9
9
-
import jsx from "lume/plugins/jsx_preact.ts";
10
10
-
11
11
-
/** Configure the site */
12
12
-
export default function () {
13
13
-
return (site: Lume.Site) => {
14
14
-
site.use(postcss())
15
15
-
.use(metas())
16
16
-
.use(favicon())
17
17
-
.use(basePath())
18
18
-
.mergeKey("extra_head", "stringArray")
19
19
-
.use(transformImages())
20
20
-
.use(simpleIcons())
21
21
-
.use(jsx());
22
22
-
23
23
-
site.data("textColor", (hex: string) => {
24
24
-
const color = new Color(`#${hex}`);
25
25
-
const onWhite = Math.abs(color.contrastWCAG21("white"));
26
26
-
const onBlack = Math.abs(color.contrastWCAG21("black"));
27
27
-
return (onWhite + 0.5) > onBlack ? "white" : "black";
28
28
-
});
29
29
-
30
30
-
site.copy([".jpg", ".webp", ".png"]);
31
31
-
};
32
32
-
}
+11
-6
src/_components/Button.tsx
···
23
23
// Function to determine text color based on background color brightness
24
24
const getTextColor = (backgroundColor: string) => {
25
25
// Remove the # if present and pad to 6 characters if needed
26
26
-
const color = (backgroundColor.startsWith("#")
27
27
-
? backgroundColor.slice(1)
28
28
-
: backgroundColor
29
29
-
).padEnd(6, backgroundColor.length <= 4 ? backgroundColor.slice(-1) : "");
26
26
+
const color =
27
27
+
(backgroundColor.startsWith("#")
28
28
+
? backgroundColor.slice(1)
29
29
+
: backgroundColor).padEnd(
30
30
+
6,
31
31
+
backgroundColor.length <= 4
32
32
+
? backgroundColor.slice(-1)
33
33
+
: "",
34
34
+
);
30
35
31
36
// Convert hex to RGB
32
37
const r = parseInt(color.substring(0, 2), 16);
···
34
39
const b = parseInt(color.substring(4, 6), 16);
35
40
36
41
// Calculate luminance to determine perceived brightness
37
37
-
const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b);
42
42
+
const luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
38
43
39
44
// Return black for light backgrounds, white for dark ones
40
45
return luminance > 128 ? "#000000" : "#ffffff";
···
55
60
}}
56
61
/>
57
62
);
58
58
-
}
63
63
+
}
-2
src/_components/Linktree.tsx
···
35
35
</>
36
36
);
37
37
}
38
38
-
39
39
-
export const css = "@import './_components/Button.css';";
+1
-3
src/_includes/layout.tsx
···
3
3
const description = data.header?.description || data.description || "";
4
4
const avatar = data.header?.avatar || "/avatar.jpg";
5
5
const footer = data.footer || "";
6
6
-
const links = data.links || [];
7
6
8
7
return (
9
8
<html lang={data.lang || "en"}>
···
26
25
media="(prefers-color-scheme: dark)"
27
26
/>
28
27
<link rel="stylesheet" href="/styles.css" />
29
29
-
<link rel="stylesheet" href="/components.css" />
30
28
<link
31
29
rel="icon"
32
30
type="image/png"
33
31
sizes="32x32"
34
34
-
href="/favicon.png"
32
32
+
href="/favicon.svg"
35
33
/>
36
34
<link rel="canonical" href={data.url} />
37
35
{data.extra_head?.map((item: string) => (
src/index.tsx
src/index.page.tsx
+1
src/styles.css
···
1
1
/* Lume's design system */
2
2
@import "https://unpkg.com/@lumeland/ds@0.5.2/ds.css";
3
3
+
@import "./_components/Button.css";
3
4
4
5
body {
5
6
display: grid;