create-evikit 2.3.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ when:
2
+ - event: push
3
+ branch: main
4
+ - event: pull_request
5
+
6
+ steps:
7
+ - name: build
8
+ image: node:24-alpine
9
+ commands:
10
+ - apk add git
11
+ # Are types correct?
12
+ - npm i
13
+ - npm run lint
14
+ - npm run build
15
+ # Does todo app example build?
16
+ - npm link
17
+ - npx create-evikit my-app
18
+ - (cd my-app; npm run build)
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # create-evikit
2
+
3
+ Create a monolith server-rendered Preact app with an API powered by a node:sqlite database, using [EviKit](https://evikit.js.org/):
4
+
5
+ ```sh
6
+ npm init evikit my-app
7
+ cd my-app
8
+ npm run dev
9
+ ```
10
+
11
+ Open http://localhost:5173/, try editing the example routes and see changes live.
12
+
13
+ You can continue with the [EviKit tutorial](https://codeberg.org/nykula/evikit#documentation). With this initializer, you don't have to manually install dependencies, add scripts to `package.json`, or create typical files such as `index.html` and `vite.config.js`.
14
+
15
+ > 😉 If you are new to Preact and the concept of Virtual DOM, it is a good idea to complete the [Preact tutorial](https://preactjs.com/tutorial/) first.
16
+
17
+ ## Read more
18
+
19
+ Think of EviKit as an [LXDE](https://en.wikipedia.org/wiki/LXDE#Software_components_of_LXDE) of web frameworks, it stands on the shoulders of awesome libraries and tools from the Preact and Node.js ecosystems:
20
+
21
+ - **[valibot](https://valibot.dev/guides/introduction/)** - Lets you declare detabase schema and validate API input/output.
22
+ - **[hoofd/preact](https://github.com/0no-co/hoofd)** - Populates `<title>` and `<meta>` tags.
23
+ - **[gettext.js](https://github.com/smhg/gettext-parser)** - Lets you pluralize translated strings.
24
+ - **[vite](https://vite.dev/guide/)** - Builds your app for development and production.
25
+ - **[express](https://expressjs.com/)** - Lets you apply compression, serve static files and use other familiar middleware.
26
+ - [@fastify/busboy](https://github.com/fastify/busboy) - Parses forms, including uploaded files.
27
+ - [@preact/preset-vite](https://github.com/preactjs/preset-vite) - In development, shows your code changes without reloading the page.
28
+ - [env-paths](https://github.com/fastify/busboy) - Saves your database in standard system-specific directory.
29
+ - [gettext-parser](https://github.com/smhg/gettext-parser) - Parses translation files.
30
+ - [preact-iso](https://github.com/preactjs/preact-iso) - Handles routing and hydrates the server-rendered code on the client.
31
+
32
+ ## License
33
+
34
+ SPDX-License-Identifier: 0BSD
35
+
36
+ Note: this license applies to this example application template. EviKit itself uses the MIT license.
@@ -25,7 +25,7 @@ for (const file of [...template, "eslint.config.js", "tsconfig.json"]) {
25
25
  path,
26
26
  readFileSync(join(ownRoot, file), "utf8")
27
27
  .replace(
28
- /<link\s+href="[^"]+"(\s+media="[^"]+")?\s+rel="[a-z]+"\s+\/>\s+/g,
28
+ /<link\s+href="[^"]+"\s+media="[^"]+"\s+rel="[a-z]+"\s+\/>\s+/g,
29
29
  "",
30
30
  )
31
31
  .replace(', "uk"', ""),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-evikit",
3
- "version": "2.3.1",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "bin": "bin/create-evikit.js",
6
6
  "scripts": {
@@ -37,7 +37,7 @@
37
37
  "@speed-highlight/core": "^1.2.17",
38
38
  "accept-language": "^3.0.20",
39
39
  "classnames": "^2.5.1",
40
- "evikit": "^2.3.2",
40
+ "evikit": "^2.5.0",
41
41
  "express": "^5.2.1",
42
42
  "file-type": "^22.0.1",
43
43
  "hoofd": "^1.7.3",
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: create-evikit\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2026-07-08 12:51+0300\n"
11
+ "POT-Creation-Date: 2026-07-08 14:48+0300\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -53,6 +53,11 @@ msgstr ""
53
53
  msgid "Quick start"
54
54
  msgstr ""
55
55
 
56
+ msgid ""
57
+ "<a href=\"{translate}\">Translate</a> this page to your language using <a "
58
+ "href=\"{poedit}\">Poedit</a> and send a merge request!"
59
+ msgstr ""
60
+
56
61
  msgid ""
57
62
  "There’s intentionally <b>not much API</b>. Documentation entirely fits in a "
58
63
  "long but straightforward <b>README</b>. Like the Django tutorial, it guides "
package/po/uk.po CHANGED
@@ -7,8 +7,8 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: create-evikit\n"
9
9
  "Report-Msgid-Bugs-To: \n"
10
- "POT-Creation-Date: 2026-07-08 12:51+0300\n"
11
- "PO-Revision-Date: 2026-07-08 03:11+0300\n"
10
+ "POT-Creation-Date: 2026-07-08 14:48+0300\n"
11
+ "PO-Revision-Date: 2026-07-08 14:49+0300\n"
12
12
  "Last-Translator: EMAIL@ADDRESS\n"
13
13
  "Language-Team: Ukrainian\n"
14
14
  "Language: uk\n"
@@ -64,6 +64,13 @@ msgstr ""
64
64
  msgid "Quick start"
65
65
  msgstr "Швидкий початок"
66
66
 
67
+ msgid ""
68
+ "<a href=\"{translate}\">Translate</a> this page to your language using <a "
69
+ "href=\"{poedit}\">Poedit</a> and send a merge request!"
70
+ msgstr ""
71
+ "<a href=\"{translate}\">Перекладіть</a> цю сторінку своєю мовою за допомогою "
72
+ "<a href=\"{poedit}\">Poedit</a> і надішліть запит на злиття!"
73
+
67
74
  msgid ""
68
75
  "There’s intentionally <b>not much API</b>. Documentation entirely fits in a "
69
76
  "long but straightforward <b>README</b>. Like the Django tutorial, it guides "
@@ -1,3 +1,4 @@
1
+ import { daemon } from "evikit/server";
1
2
  import { sqlite } from "evikit/sqlite";
2
3
 
3
4
  import pkg from "../../../package.json" with { type: "json" };
@@ -5,15 +6,13 @@ import * as schema from "./schema.js";
5
6
 
6
7
  export const db = sqlite({ pkg, schema });
7
8
 
8
- if (
9
- process.env["npm_command"] == "start" ||
10
- process.env["npm_lifecycle_event"] == "dev"
11
- ) {
12
- setInterval(() => {
9
+ daemon(() => {
10
+ const interval = setInterval(() => {
13
11
  db.Todo.delete({
14
12
  text: db.Todo.select()
15
13
  .filter(({ createdAt }) => createdAt < Date.now() - 10 * 60e3)
16
14
  .map(({ text }) => text),
17
15
  });
18
16
  }, 1000);
19
- }
17
+ return () => clearInterval(interval);
18
+ });
@@ -182,7 +182,21 @@ npm run dev
182
182
 
183
183
  h(
184
184
  Code,
185
- { file: data?.File["src/lib/index.js"], lang: "js" },
185
+ {
186
+ file: data?.File["src/lib/index.js"],
187
+ lang: "js",
188
+ note:
189
+ "🤝 " +
190
+ i18n
191
+ .gettext(
192
+ `<a href="{translate}">Translate</a> this page to your language using <a href="{poedit}">Poedit</a> and send a merge request!`,
193
+ )
194
+ .replace(
195
+ "{translate}",
196
+ "https://codeberg.org/nykula/create-evikit/src/branch/main/po/create-evikit.pot",
197
+ )
198
+ .replace("{poedit}", "https://poedit.com/"),
199
+ },
186
200
  span(null, "src/lib/"),
187
201
  b(null, "index.js"),
188
202
  ),
@@ -285,8 +299,8 @@ npm run dev
285
299
  );
286
300
  }
287
301
 
288
- /** @param {{ children?: any, lang: string, file: string | undefined, tag?: string }} props */
289
- function Code({ children, file, lang, tag }) {
302
+ /** @param {{ children?: any, lang: string, file: string | undefined, note?: string, tag?: string }} props */
303
+ function Code({ children, file, lang, note, tag }) {
290
304
  const inner = pre(
291
305
  { class: "mt-4 overflow-auto text-sm" },
292
306
  code(
@@ -304,10 +318,11 @@ function Code({ children, file, lang, tag }) {
304
318
  ),
305
319
  ),
306
320
  );
321
+ const more = note ? p({ class: "mt-5", ...sanitize(note) }) : undefined;
307
322
  const style = `${darkBg} mb-4 mx-0 overflow-hidden p-4 rounded-xl`;
308
323
  return tag == "details"
309
- ? details({ class: style }, summary(null, children), inner)
310
- : figure({ class: style }, figcaption(null, children), inner);
324
+ ? details({ class: style }, summary(null, children), inner, more)
325
+ : figure({ class: style }, figcaption(null, children), inner, more);
311
326
  }
312
327
 
313
328
  /** @param {string} html */
@@ -316,7 +331,7 @@ function sanitize(html) {
316
331
  dangerouslySetInnerHTML: {
317
332
  __html: html.replace(/<([^>]*)>/g, (match) =>
318
333
  /^<\/?[a-z]+>$/.test(match) ||
319
- /^<a href="[0-9A-Za-z:/.#%]*"( target="_top")?>$/.test(match)
334
+ /^<a href="[0-9A-Za-z:/.#%-]*"( target="_top")?>$/.test(match)
320
335
  ? match
321
336
  : "",
322
337
  ),
Binary file
Binary file