htmv 0.0.53 → 0.0.55

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.
package/README.md CHANGED
@@ -162,4 +162,9 @@ Having to restart the server every time you make a change can be quite tedious.
162
162
 
163
163
  # Still have questions?
164
164
  How about asking the DeepWiki instead?
165
- [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Fabrisdev/htmv)
165
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Fabrisdev/htmv)
166
+
167
+ # Interested in HTMV's development or would like to contribute?
168
+ There's still a ton of work left! Check out features to come at [**HTMV's Trello page**](https://trello.com/b/rhprnM4y/htmv)!
169
+
170
+ If you would like to contribute, check out the Trello for ideas on what to work on!
@@ -79,8 +79,16 @@ export function parse(tokens) {
79
79
  text: `<${tag} `,
80
80
  });
81
81
  let nextToken = tokens[i];
82
+ let isFirstAttribute = true;
82
83
  while (nextToken?.type === "arguments" ||
83
84
  nextToken?.type === "attr-binding") {
85
+ if (!isFirstAttribute) {
86
+ nodes.push({
87
+ type: "text",
88
+ text: " ",
89
+ });
90
+ }
91
+ isFirstAttribute = false;
84
92
  if (nextToken.type === "arguments") {
85
93
  parseArgs(nextToken.value);
86
94
  i++;
@@ -35,7 +35,8 @@ export function tokenize(input) {
35
35
  i = finishingPosition;
36
36
  continue;
37
37
  }
38
- const args = values.slice(1);
38
+ const rawArgs = values.slice(1);
39
+ const args = splitRawArguments(rawArgs);
39
40
  tokens.push({
40
41
  type: "open",
41
42
  tag,
@@ -93,3 +94,37 @@ function readTill(charToSearchFor, startingPosition, text) {
93
94
  finishingPosition,
94
95
  };
95
96
  }
97
+ function splitRawArguments(args) {
98
+ const result = [];
99
+ let current = null;
100
+ let quote = null;
101
+ for (const part of args) {
102
+ if (current === null) {
103
+ const match = part.match(/(['"])/);
104
+ if (match) {
105
+ const q = match[1];
106
+ const count = (part.match(new RegExp(q, "g")) || []).length;
107
+ if (count === 1) {
108
+ current = part;
109
+ quote = q;
110
+ }
111
+ else {
112
+ result.push(part);
113
+ }
114
+ }
115
+ else {
116
+ result.push(part);
117
+ }
118
+ }
119
+ else {
120
+ current += " " + part;
121
+ const count = (current.match(new RegExp(quote, "g")) || []).length;
122
+ if (count % 2 === 0) {
123
+ result.push(current);
124
+ current = null;
125
+ quote = null;
126
+ }
127
+ }
128
+ }
129
+ return result;
130
+ }
@@ -4,7 +4,6 @@ export type HttpResponse = {
4
4
  headers?: Headers;
5
5
  body?: string;
6
6
  };
7
- type ResponseLike = string | object | HttpResponse;
7
+ export type ResponseLike = string | object | HttpResponse;
8
8
  export declare function resolveResponse(result: ResponseLike): Response;
9
9
  export declare function requestHelper(status: number, body?: string | object, headers?: Headers): HttpResponse;
10
- export {};
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createApp } from "./app";
2
- import { registerRoutes } from "./routing";
2
+ import { registerRoutes } from "./routing/routing";
3
3
  import { setViewsPath } from "./views";
4
4
  export { view } from "./views";
5
5
  export async function setup(paths) {
@@ -0,0 +1,2 @@
1
+ import type { Method } from "./types";
2
+ export declare function isMethod(value: string): value is Method;
@@ -0,0 +1,3 @@
1
+ export function isMethod(value) {
2
+ return ["get", "post", "put", "patch", "delete", "all"].includes(value);
3
+ }
@@ -0,0 +1,2 @@
1
+ import type Elysia from "elysia";
2
+ export declare function registerModuleRoutes(app: Elysia, prefix: string, path: string): Promise<void>;
@@ -0,0 +1,25 @@
1
+ import { isMethod } from "./helpers";
2
+ import { registerRoute } from "./routes-handler";
3
+ export async function registerModuleRoutes(app, prefix, path) {
4
+ const module = (await import(path));
5
+ for (const propName in module) {
6
+ const prop = module[propName];
7
+ if (typeof prop !== "function")
8
+ continue;
9
+ const fn = prop;
10
+ const name = fn.name.toLowerCase();
11
+ const method = isMethod(name)
12
+ ? name
13
+ : propName === "default"
14
+ ? "all"
15
+ : undefined;
16
+ if (method) {
17
+ registerRoute({
18
+ app,
19
+ method,
20
+ path: prefix,
21
+ fn,
22
+ });
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,10 @@
1
+ import type Elysia from "elysia";
2
+ import type { Method, RouteFn } from "./types";
3
+ type RegisterRouteParams = {
4
+ app: Elysia;
5
+ method: Method;
6
+ path: string;
7
+ fn: RouteFn;
8
+ };
9
+ export declare function registerRoute({ app, method, path, fn }: RegisterRouteParams): void;
10
+ export {};
@@ -0,0 +1,7 @@
1
+ import { resolveResponse } from "../http/response";
2
+ export function registerRoute({ app, method, path, fn }) {
3
+ app[method](path, async ({ request, query, params }) => {
4
+ const result = await fn({ request, query, params });
5
+ return resolveResponse(result);
6
+ });
7
+ }
@@ -0,0 +1,16 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { registerModuleRoutes } from "./modules-handler";
4
+ export async function registerRoutes(app, baseDir, prefix = "/") {
5
+ const entries = await fs.readdir(baseDir, { withFileTypes: true });
6
+ for (const entry of entries) {
7
+ const fullPath = path.join(baseDir, entry.name);
8
+ if (entry.isDirectory()) {
9
+ await registerRoutes(app, fullPath, path.join(prefix, entry.name));
10
+ continue;
11
+ }
12
+ if (entry.name !== "index.ts")
13
+ continue;
14
+ await registerModuleRoutes(app, prefix, fullPath);
15
+ }
16
+ }
package/dist/types.d.ts CHANGED
@@ -9,4 +9,3 @@ export type Paths = {
9
9
  public: string;
10
10
  port: number;
11
11
  };
12
- export type RouteFn = (_: RouteParams) => Promise<Response> | Response | Promise<string> | string;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "htmv",
3
3
  "main": "dist/index.js",
4
4
  "type": "module",
5
- "version": "0.0.53",
5
+ "version": "0.0.55",
6
6
  "exports": {
7
7
  ".": {
8
8
  "types": "./dist/index.d.ts",
package/dist/routing.js DELETED
@@ -1,38 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { resolveResponse } from "./http/response";
4
- export async function registerRoutes(app, baseDir, prefix = "/") {
5
- const entries = await fs.readdir(baseDir, { withFileTypes: true });
6
- for (const entry of entries) {
7
- const fullPath = path.join(baseDir, entry.name);
8
- if (entry.isDirectory()) {
9
- await registerRoutes(app, fullPath, path.join(prefix, entry.name));
10
- continue;
11
- }
12
- if (entry.name !== "index.ts")
13
- continue;
14
- const module = (await import(fullPath));
15
- const defaultFn = module.default;
16
- if (defaultFn && typeof defaultFn === "function") {
17
- app.all(prefix, async ({ request, query, params }) => {
18
- const result = await defaultFn({ request, query, params });
19
- return resolveResponse(result);
20
- });
21
- console.log(`Registered ${fullPath} on ${prefix} route with method all`);
22
- }
23
- for (const propName in module) {
24
- const prop = module[propName];
25
- if (typeof prop !== "function")
26
- continue;
27
- const fn = prop;
28
- const name = fn.name.toLowerCase();
29
- if (!["get", "post", "put", "patch", "delete"].includes(name))
30
- continue;
31
- app[name](prefix, async ({ request, query, params }) => {
32
- const result = await fn({ request, query, params });
33
- return resolveResponse(result);
34
- });
35
- console.log(`Registered ${fullPath} on ${prefix} route with method ${name}`);
36
- }
37
- }
38
- }
File without changes