plugin.frontend_js
Massimo Melina committed
Jan 9, 2022 at 20:01 UTC
a99453b9d7ebcc9b4789969cb90b9d3dbf292192
10 files changed
+54
-16
README.md
+6
-2
@@ -4,6 +4,8 @@ HFS is a file server offering a virtual file system (vfs).
4
You can easily share a single file instead of the whole folder,
5
or you can rename it, but without touching the real file, just virtually.
6
7
+Listing files, searching files, zipping folders, it's all very fast, streamed while data is produced, so you don't have to wait.
8
+
9
This project is in an early stage and distribution will be made easier.
10
11
This is a full rewrite of [the Delphi version](https://github.com/rejetto/hfs2).
@@ -40,7 +42,7 @@ Supported entries are:
42
You can specify multiple entries, or separate multiple file masks with a p|pe.
43
You can use the special value `auto` to attempt automatic detection.
44
- `max-kbps` throttle output speed. Default is Infinity.
43
-- `max-kbps-per-ip` throttle out speed on a per-ip basis. Default is Infinity.
45
+- `max-kbps-per-ip` throttle output speed on a per-ip basis. Default is Infinity.
46
47
## Virtual File System (VFS)
48
@@ -112,7 +114,9 @@ Supported keys are:
114
115
If the function returns `true`, other executions on this http request will be interrupted.
116
Return another function if you want to execute it in the "upstream" of middlewares.
115
-
117
+
118
- `frontend_css` path to one or more css files that you want the frontend to load.
119
120
+- `frontend_js` path to one or more js files that you want the frontend to load.
121
+
122
Each plug-in can have a `public` folder, and its files will be accessible at `/~/plugins/PLPUGIN_NAME/FILENAME`.
frontend/src/App.tsx
+11
-1
@@ -1,5 +1,5 @@
1
import { BrowserRouter, Route, Routes } from "react-router-dom"
2
-import { createElement as h, Fragment } from 'react'
2
+import { createElement as h, Fragment, useEffect } from 'react'
3
import { BrowseFiles } from "./BrowseFiles";
4
import { Dialogs } from './dialog'
5
import { useApi } from "./api";
@@ -8,6 +8,16 @@ import useTheme from "./useTheme";
8
function App() {
9
const extras = useApi('extras_to_load')
10
useTheme()
11
+
12
+ const imp = extras?.js
13
+ useEffect(() => {
14
+ for (const url of imp||[]) {
15
+ const el = document.createElement('script')
16
+ el.src = url
17
+ el.async = true
18
+ document.body.appendChild(el)
19
+ }
20
+ }, [imp])
21
return h(Fragment, {},
22
h(BrowserRouter, {},
23
h(Routes, {},
plugins/theme-example-disabled/plugin.yaml
+1
@@ -1,2 +1,3 @@
1
ver: 1
2
frontend_css: style.css
3
+frontend_js: test.js
\ No newline at end of file
plugins/theme-example-disabled/public/star.png
Binary files a/plugins/theme-example-disabled/public/star.png and /dev/null differ
plugins/theme-example-disabled/public/star.svg
new
+12
@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ version="1.0"
5
+ width="432.39999"
6
+ height="413.48999"
7
+>
8
+ <path
9
+ d="M 332.25647,385.51933 L 217.94322,325.58331 L 103.76342,385.77314 L 125.44132,258.53357 L 32.91382,168.54182 L 160.62472,149.83945 L 217.61942,34.031678 L 274.87122,149.71255 L 402.62329,168.13113 L 310.29602,258.32822 L 332.25647,385.51933 z "
10
+ style="fill:#55a;fill-opacity:1;stroke:#000000;stroke-width:10.86700058;stroke-miterlimit:4;stroke-opacity:1"
11
+ id="path6092" />
12
+</svg>
plugins/theme-example-disabled/public/style.css
+4
-1
@@ -1 +1,4 @@
1
-header { background:#fff url(star.png) top right no-repeat; }
1
+header {
2
+ background: var(--bg) url(star.svg) top right no-repeat;
3
+ background-size: 3em;
4
+}
plugins/theme-example-disabled/public/test.js
new
+1
@@ -0,0 +1 @@
1
+alert('ciao')
\ No newline at end of file
src/frontEndApis.ts
+6
-5
@@ -3,6 +3,7 @@ import { plugins } from './plugins'
3
import { PLUGINS_PUB_URI } from './const'
4
import * as api_file_list from './api.file_list'
5
import * as api_auth from './api.auth'
6
+import _ from 'lodash'
7
8
export const frontEndApis: ApiHandlers = {
9
@@ -11,11 +12,11 @@ export const frontEndApis: ApiHandlers = {
12
...api_auth,
13
14
async extras_to_load() {
14
- const css = []
15
- for (const [k,plug] of Object.entries(plugins))
16
- if (plug.frontend_css)
17
- css.push( ...plug.frontend_css.map(f => PLUGINS_PUB_URI + k + '/' + f) )
18
- return { css }
15
+ const css = _.map(plugins, (plug,k) =>
16
+ plug.frontend_css?.map(f => PLUGINS_PUB_URI + k + '/' + f)).flat().filter(Boolean)
17
+ const js = _.map(plugins, (plug,k) =>
18
+ plug.frontend_js?.map(f => PLUGINS_PUB_URI + k + '/' + f)).flat().filter(Boolean)
19
+ return { css, js }
20
},
21
22
}
src/index.ts
+1
@@ -23,6 +23,7 @@ const BUILD_TIMESTAMP = ""
23
export const SESSION_DURATION = 30*60_000
24
25
console.log('started', new Date().toLocaleString())
26
+console.log('build', BUILD_TIMESTAMP)
27
const app = new Koa()
28
app.keys = ['hfs-keys-test']
29
app.use(session({
src/plugins.ts
+12
-7
@@ -53,14 +53,16 @@ class Plugin {
53
plugins[k] = this // track this
54
55
// some validation
56
- let v = data.frontend_css
57
- if (typeof v === 'string')
58
- data.frontend_css = [v]
59
- else if (v && !Array.isArray(v)) {
60
- delete data.frontend_css
61
- console.warn('invalid frontend_css')
56
+ for (const k of ['frontend_css', 'frontend_js']) {
57
+ const v = data[k]
58
+ if (typeof v === 'string')
59
+ data[k] = [v]
60
+ else if (v && !Array.isArray(v)) {
61
+ delete data[k]
62
+ console.warn('invalid', k)
63
+ }
64
}
63
- v = data.middleware
65
+ let v = data.middleware
66
if (v && !(v instanceof Function)) {
67
delete data.middleware
68
console.warn('invalid middleware')
@@ -72,6 +74,9 @@ class Plugin {
74
get frontend_css(): undefined | string[] {
75
return this.data.frontend_css
76
}
77
+ get frontend_js(): undefined | string[] {
78
+ return this.data.frontend_js
79
+ }
80
81
unload() {
82
console.log('unloading plugin', this.k)