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)