mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
ui: use vite
This commit is contained in:
15 files changed
+588
-31
No files matched your search
@@ -1,10 +1,278 @@
|
||||
// This file is imported in all stylus source code
|
||||
|
||||
base-font-size ?= 16px
|
||||
rasterise-media-queries ?= false
|
||||
|
||||
rupture = {
|
||||
rasterise-media-queries: rasterise-media-queries
|
||||
mobile-cutoff: 400px
|
||||
desktop-cutoff: 1050px
|
||||
hd-cutoff: 1800px
|
||||
enable-em-breakpoints: false
|
||||
base-font-size: base-font-size
|
||||
anti-overlap: false
|
||||
density-queries: 'dppx' 'webkit' 'moz' 'dpi'
|
||||
retina-density: 1.5
|
||||
use-device-width: false
|
||||
}
|
||||
rupture.scale = 0 (rupture.mobile-cutoff) 600px 800px (rupture.desktop-cutoff) (rupture.hd-cutoff)
|
||||
rupture.scale-names = 'xs' 's' 'm' 'l' 'xl' 'hd'
|
||||
|
||||
-is-string(val)
|
||||
if typeof(val) is not 'unit'
|
||||
if val is a 'string' or val is a 'ident'
|
||||
true
|
||||
else
|
||||
false
|
||||
else
|
||||
false
|
||||
|
||||
-get-scale-number(scale-name)
|
||||
for list-item, i in rupture.scale-names
|
||||
if list-item is scale-name
|
||||
return i + 1
|
||||
return false
|
||||
|
||||
-convert-to(to-unit, value, context = rupture.base-font-size)
|
||||
from-unit = unit(value)
|
||||
return value if to-unit is from-unit
|
||||
if to-unit in ('em' 'rem')
|
||||
return value if from-unit in ('em' 'rem')
|
||||
return unit((value / context), to-unit)
|
||||
if to-unit is 'px'
|
||||
return unit((value * context), 'px')
|
||||
|
||||
-on-scale(n)
|
||||
return unit(n) is ''
|
||||
|
||||
-larger-than-scale(n)
|
||||
return (n > (length(rupture.scale) - 1)) and -on-scale(n)
|
||||
|
||||
-is-zero(n)
|
||||
return n is 0
|
||||
|
||||
-overlap-shift(anti-overlap, n)
|
||||
shift-unit = unit(n)
|
||||
anti-overlap = 0px unless anti-overlap
|
||||
anti-overlap = 1px if anti-overlap is true
|
||||
if length(anti-overlap) is 1
|
||||
return -convert-to(shift-unit, anti-overlap)
|
||||
for val in anti-overlap
|
||||
return val if unit(val) is shift-unit
|
||||
|
||||
-adjust-overlap(anti-overlap, n, side = 'min')
|
||||
-shift = -overlap-shift(anti-overlap, n)
|
||||
if (side is 'min' and -shift > 0) or (side is 'max' and -shift < 0)
|
||||
n = n + -shift
|
||||
return n
|
||||
|
||||
-is-positive(n)
|
||||
return n >= 0
|
||||
|
||||
-density-queries(density)
|
||||
if typeof(density) is not 'unit'
|
||||
if not -is-string(density)
|
||||
density = '%s' % density
|
||||
density = rupture.retina-density if density is 'retina'
|
||||
queries = ()
|
||||
for query in rupture.density-queries
|
||||
if query is 'webkit'
|
||||
push(queries, '(-webkit-min-device-pixel-ratio: %s)' % (density))
|
||||
else if query is 'moz'
|
||||
push(queries, '(min--moz-device-pixel-ratio: %s)' % (density))
|
||||
else if query is 'o'
|
||||
push(queries, '(-o-min-device-pixel-ratio: %s/1)' % (density))
|
||||
else if query is 'ratio'
|
||||
push(queries, '(min-device-pixel-ratio: %s)' % (density))
|
||||
else if query is 'dpi'
|
||||
if -is-string(density)
|
||||
density=convert(density)
|
||||
push(queries, '(min-resolution: %sdpi)' % (round(density * 96, 1)))
|
||||
else if query is 'dppx'
|
||||
push(queries, '(min-resolution: %sdppx)' % (density))
|
||||
return queries
|
||||
|
||||
create-fallback-class(selected, class)
|
||||
/{'' + class + ' ' + selected}
|
||||
{block}
|
||||
|
||||
// +between(min, max)
|
||||
// usage (scale can be mixed with custom values):
|
||||
// - +between(1, 3) scale:scale
|
||||
// - +between(0, 3) 0 width:scale
|
||||
// - +between(200px, 500px) custom:custom
|
||||
// - +between(0, 300px) 0 width:custom
|
||||
// - +between(1, 300px) scale:custom
|
||||
// - +between(200px, 4) custom:scale
|
||||
|
||||
between(min, max, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
selected = selector()
|
||||
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
if -is-string(min)
|
||||
min = -get-scale-number(min)
|
||||
if -is-string(max)
|
||||
max = -get-scale-number(max)
|
||||
|
||||
-min = rupture.scale[min - 1] unless -is-zero(min) or (not -on-scale(min))
|
||||
-max = rupture.scale[max] unless not -on-scale(max)
|
||||
-min ?= min
|
||||
-max ?= max
|
||||
|
||||
if (rupture.rasterise-media-queries)
|
||||
if not (density or -max or orientation)
|
||||
{block}
|
||||
else
|
||||
condition = 'only screen'
|
||||
use-device-width = use-device-width ? 'device-' : ''
|
||||
unless -min is 0
|
||||
-min = -convert-to('em', -min) if rupture.enable-em-breakpoints
|
||||
-min = -adjust-overlap(anti-overlap, -min, side: 'min')
|
||||
condition = condition + ' and (min-' + use-device-width + 'width: %s)' % (-min)
|
||||
unless -larger-than-scale(max)
|
||||
-max = -convert-to('em', -max) if rupture.enable-em-breakpoints
|
||||
-max = -adjust-overlap(anti-overlap, -max, side: 'max')
|
||||
condition = condition + ' and (max-' + use-device-width + 'width: %s)' % (-max)
|
||||
if orientation
|
||||
condition = condition + ' and (orientation: %s)' % (orientation)
|
||||
if density
|
||||
conditions = ()
|
||||
for query in -density-queries(density)
|
||||
push(conditions, condition + ' and %s' % (query))
|
||||
condition = join(', ', conditions)
|
||||
@media condition
|
||||
{block}
|
||||
if fallback-class
|
||||
+create-fallback-class(selected, fallback-class)
|
||||
{block}
|
||||
|
||||
at(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+between(scale-point, scale-point, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
from-width(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+between(scale-point, length(rupture.scale), anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
above = from-width
|
||||
|
||||
to-width(scale-point, anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+between(1, scale-point, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
below = to-width
|
||||
|
||||
mobile(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+below(rupture.mobile-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
tablet(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+between(rupture.mobile-cutoff, rupture.desktop-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
desktop(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+above(rupture.desktop-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
hd(anti-overlap = rupture.anti-overlap, density = null, orientation = null, use-device-width = rupture.use-device-width, fallback-class = null)
|
||||
if -is-string(orientation)
|
||||
orientation = convert(orientation)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
+above(rupture.hd-cutoff, anti-overlap, density, orientation, use-device-width, fallback-class)
|
||||
{block}
|
||||
|
||||
density(density, orientation = null, fallback-class = null)
|
||||
selected = selector()
|
||||
if not (rupture.rasterise-media-queries)
|
||||
conditions = ()
|
||||
for query in -density-queries(density)
|
||||
condition = 'only screen and %s' % (query)
|
||||
if orientation
|
||||
condition = condition + ' and (orientation: %s)' % (orientation)
|
||||
push(conditions, condition)
|
||||
condition = join(', ', conditions)
|
||||
@media condition
|
||||
{block}
|
||||
if fallback-class
|
||||
+create-fallback-class(selected, fallback-class)
|
||||
{block}
|
||||
|
||||
pixel-ratio = density
|
||||
|
||||
retina(orientation = null, fallback-class = null)
|
||||
+density('retina', orientation, fallback-class)
|
||||
{block}
|
||||
|
||||
landscape(density = null, fallback-class = null)
|
||||
selected = selector()
|
||||
if not (rupture.rasterise-media-queries)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
if density
|
||||
+pixel-ratio(density, orientation: landscape, fallback-class)
|
||||
{block}
|
||||
else
|
||||
@media only screen and (orientation: landscape)
|
||||
{block}
|
||||
if fallback-class
|
||||
+create-fallback-class(selected, fallback-class)
|
||||
{block}
|
||||
|
||||
portrait(density = null, fallback-class = null)
|
||||
selected = selector()
|
||||
if not (rupture.rasterise-media-queries)
|
||||
if -is-string(density)
|
||||
density = convert(density)
|
||||
if density
|
||||
+pixel-ratio(density, orientation: portrait, fallback-class)
|
||||
{block}
|
||||
else
|
||||
@media only screen and (orientation: portrait)
|
||||
{block}
|
||||
if fallback-class
|
||||
+create-fallback-class(selected, fallback-class)
|
||||
{block}
|
||||
|
||||
rupture-hover(density = null, orientation = null, fallback-class = null)
|
||||
condition = "only screen and (hover: hover)";
|
||||
@media ({condition})
|
||||
{block}
|
||||
|
||||
hover = rupture-hover
|
||||
|
||||
breakpoints = json('../breakpoints.json', { hash: true })
|
||||
rupture.mobile-cutoff = unit(breakpoints.mobile, 'px')
|
||||
rupture.desktop-cutoff = unit(breakpoints.desktop, 'px')
|
||||
rupture.hd-cutoff = unit(breakpoints.hd, 'px')
|
||||
|
||||
@import '~vj/misc/.iconfont/webicon.inc.styl'
|
||||
@import '../misc/.iconfont/webicon.inc.styl'
|
||||
@import 'color.inc.styl'
|
||||
@import 'variables.inc.styl'
|
||||
@import 'easing.inc.styl'
|
||||
|
||||
@@ -13,14 +13,14 @@ import getLoader from 'prismjs/dependencies';
|
||||
import Notification from 'vj/components/notification/index';
|
||||
import { i18n } from 'vj/utils';
|
||||
import languageMeta from './meta';
|
||||
import langs from 'prismjs/components/index';
|
||||
|
||||
const files = require.context('prismjs/components/', true, /prism-[a-z0-9-]+\.js/);
|
||||
const loadedLanguages = new Set();
|
||||
function loadLanguages() {
|
||||
const languages = Object.keys(components.languages).filter((l) => l !== 'meta');
|
||||
const loaded = [...loadedLanguages, ...Object.keys(Prism.languages)];
|
||||
getLoader(components, languages, loaded).load((lang) => {
|
||||
files(`./prism-${lang}.js`);
|
||||
langs[lang]?.();
|
||||
loadedLanguages.add(lang);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ const onmessage = (msg) => {
|
||||
|
||||
const initWorkerMode = (endpoint) => {
|
||||
console.log('Messages: using SharedWorker');
|
||||
const worker = new SharedWorker('/messages-shared-worker.js', { name: 'HydroMessagesWorker' });
|
||||
const worker = new SharedWorker(new URL('./worker.ts?worker', import.meta.url), { name: 'HydroMessagesWorker' });
|
||||
worker.port.start();
|
||||
window.addEventListener('beforeunload', () => {
|
||||
worker.port.postMessage({ type: 'unload' });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
export default function DataInputComponent(props) {
|
||||
const {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
export default function ToolbarComponent(props) {
|
||||
const {
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import $ from 'jquery';
|
||||
import * as timeago from 'timeago.js';
|
||||
import en_US from 'timeago.js/lib/lang/en_US';
|
||||
import ko from 'timeago.js/lib/lang/ko';
|
||||
import zh_CN from 'timeago.js/lib/lang/zh_CN';
|
||||
import zh_TW from 'timeago.js/lib/lang/zh_TW';
|
||||
import { AutoloadPage } from 'vj/misc/Page';
|
||||
import { i18n } from 'vj/utils';
|
||||
|
||||
try {
|
||||
const locales = require.context('timeago.js/lib/lang', false, /\.js$/);
|
||||
let locale;
|
||||
try {
|
||||
locale = locales(`./${i18n('timeago_locale')}.js`).default;
|
||||
} catch (e) {
|
||||
locale = locales('./en_US.js').default;
|
||||
}
|
||||
const locales = {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
zh_CN, zh_TW, ko, en_US,
|
||||
};
|
||||
const locale = locales[i18n('timeago_locale')] || locales.en_US;
|
||||
timeago.register(i18n('timeago_locale'), locale);
|
||||
} catch (e) {
|
||||
console.error(`Cannot register timeago locale: ${i18n('timeago_locale')}`);
|
||||
console.error(`Cannot register timeago locale: ${i18n('timeago_locale')}`, e);
|
||||
}
|
||||
function runRelativeTime($container) {
|
||||
$container.find('span.time.relative[data-timestamp]').get().forEach((element) => {
|
||||
|
||||
@@ -7,6 +7,7 @@ window.Hydro = {
|
||||
node_modules: {},
|
||||
version: process.env.VERSION,
|
||||
};
|
||||
window.jQuery = $; // sticky-kit require this
|
||||
window.externalModules = {};
|
||||
window.lazyModuleResolver = {};
|
||||
|
||||
@@ -30,7 +31,11 @@ window.UserContext = JSON.parse(window.UserContext);
|
||||
try { __webpack_public_path__ = UiContext.cdn_prefix; } catch (e) { }
|
||||
if ('serviceWorker' in navigator) {
|
||||
const encodedConfig = encodeURIComponent(JSON.stringify(UiContext.SWConfig));
|
||||
navigator.serviceWorker.register(`/service-worker.js?config=${encodedConfig}`).then((registration) => {
|
||||
const dev = process.env.NODE_ENV === 'development';
|
||||
navigator.serviceWorker.register(
|
||||
dev ? '/dev-sw.js?dev-sw' : `/sw.js?config=${encodedConfig}`,
|
||||
{ scope: '/', type: dev ? 'module' : 'classic' },
|
||||
).then((registration) => {
|
||||
console.log('SW registered: ', registration);
|
||||
}).catch((registrationError) => {
|
||||
console.log('SW registration failed: ', registrationError);
|
||||
@@ -82,6 +82,7 @@ export async function initPageLoader() {
|
||||
Notification.warn(`Failed to call '${type}Loading' of ${page.name}`);
|
||||
console.error(`Failed to call '${type}Loading' of ${page.name}\n${e.stack}`);
|
||||
console.error(e);
|
||||
console.info(func.toString());
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.time(`${page.name}: ${type}Loading`);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import pages from '../__glob_page';
|
||||
import { Page } from './Page';
|
||||
|
||||
export default class PageLoader {
|
||||
constructor() {
|
||||
const pages = require.context('../pages/', true, /\.page\.[jt]sx?$/i);
|
||||
const components = require.context('../components/', true, /\.page\.[jt]sx?$/i);
|
||||
this.pageInstances = [
|
||||
...pages.keys().map((key) => pages(key)),
|
||||
...components.keys().map((key) => components(key)),
|
||||
...pages,
|
||||
...window.Hydro.extraPages,
|
||||
].map((page) => {
|
||||
page = page?.default || page;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blueprintjs/core": "^5.10.3",
|
||||
"@codingame/esbuild-import-meta-url-plugin": "^1.0.2",
|
||||
"@fontsource/dm-mono": "^5.0.20",
|
||||
"@fontsource/fira-code": "^5.0.18",
|
||||
"@fontsource/inconsolata": "^5.0.18",
|
||||
@@ -24,6 +25,7 @@
|
||||
"@fontsource/source-code-pro": "^5.0.18",
|
||||
"@fontsource/ubuntu-mono": "^5.0.20",
|
||||
"@hydrooj/utils": "workspace:^",
|
||||
"@rollup/plugin-inject": "^5.0.5",
|
||||
"@simplewebauthn/browser": "7.4.0",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@types/gulp-if": "^0.0.34",
|
||||
@@ -117,6 +119,10 @@
|
||||
"ts-loader": "^9.5.1",
|
||||
"vditor": "^3.10.4",
|
||||
"vinyl-buffer": "^1.0.1",
|
||||
"vite": "^5.2.12",
|
||||
"vite-plugin-pwa": "^0.20.0",
|
||||
"vite-plugin-static-copy": "^1.0.5",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"web-streams-polyfill": "^4.0.0",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-bundle-analyzer": "^4.10.2",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '~vj/components/tab/var.inc.styl'
|
||||
@import '../components/tab/var.inc.styl'
|
||||
|
||||
.page--user_detail
|
||||
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
export { }; // make it a module so that declare self works
|
||||
declare const self: ServiceWorkerGlobalScope;
|
||||
|
||||
let dev = false;
|
||||
let version = 'dev';
|
||||
try {
|
||||
dev = process.env.NODE_ENV !== 'production';
|
||||
version = process.env.VERSION;
|
||||
} catch (e) {
|
||||
// process doesnt exist
|
||||
dev = location.search.includes('dev-sw');
|
||||
}
|
||||
|
||||
const map = new Map();
|
||||
|
||||
function createStream(port) {
|
||||
@@ -88,13 +98,13 @@ self.addEventListener('notificationclick', (event) => {
|
||||
}));
|
||||
});
|
||||
|
||||
const PRECACHE = `precache-${process.env.VERSION}`;
|
||||
const PRECACHE = `precache-${version}`;
|
||||
const DO_NOT_PRECACHE = ['vditor', '.worker.js', 'fonts', 'i.monaco'];
|
||||
|
||||
function shouldCachePath(path: string) {
|
||||
if (!path.split('?')[0].split('/').pop()) return false;
|
||||
if (!path.split('?')[0].split('/').pop().includes('.')) return false;
|
||||
if (process.env.NODE_ENV !== 'production' && (path.includes('.hot-update.') || path.includes('?version='))) return false;
|
||||
if (dev && (path.includes('.hot-update.') || path.includes('?version='))) return false;
|
||||
return true;
|
||||
}
|
||||
function shouldCache(request: Request) {
|
||||
@@ -119,7 +129,7 @@ interface ServiceWorkerConfig {
|
||||
let config: ServiceWorkerConfig = null;
|
||||
|
||||
function initConfig() {
|
||||
config = JSON.parse(new URLSearchParams(location.search).get('config'));
|
||||
config = JSON.parse(new URLSearchParams(location.search).get('config')) || {};
|
||||
config.hosts ||= [];
|
||||
if (!config.domains?.length) config.domains = [location.host];
|
||||
console.log('Config:', config);
|
||||
@@ -127,7 +137,7 @@ function initConfig() {
|
||||
|
||||
self.addEventListener('install', (event) => event.waitUntil((async () => {
|
||||
initConfig();
|
||||
if (process.env.NODE_ENV === 'production' && config?.preload) {
|
||||
if (!dev && config?.preload) {
|
||||
const [cache, manifest] = await Promise.all([
|
||||
caches.open(PRECACHE),
|
||||
fetch('/manifest.json').then((res) => res.json()),
|
||||
@@ -193,6 +203,7 @@ async function cachedRespond(request: Request) {
|
||||
caches.open(PRECACHE),
|
||||
get(request),
|
||||
]);
|
||||
if (response.headers.get('Cache-Control') === 'no-cache') return response;
|
||||
if (response.ok) {
|
||||
cache.put(url, response.clone());
|
||||
return response;
|
||||
|
||||
@@ -37,8 +37,7 @@
|
||||
{% endif %}
|
||||
</style>
|
||||
{% if process.env.DEV %}
|
||||
<script src="/default.theme.js?version={{ global.Hydro.version['ui-default'] }}"></script>
|
||||
<link rel="stylesheet" media="all" href="/theme.css?version={{ global.Hydro.version['ui-default'] }}">
|
||||
<script src="/theme/default.js?version={{ global.Hydro.version['ui-default'] }}" type="module"></script>
|
||||
{% else %}
|
||||
<link rel="stylesheet" media="all" href="{{ UiContext.cdn_prefix }}theme-{{ global.Hydro.version['ui-default'] }}.css">
|
||||
{% endif %}
|
||||
@@ -67,7 +66,7 @@
|
||||
{% set UserContext = Object.create(UserContext) %}
|
||||
{% if process.env.DEV %}
|
||||
<script type="text/javascript" src="/resource/hash/lang-{{ _('__id') }}.js?version={{ global.Hydro.version['ui-default'] }}"></script>
|
||||
<script type="text/javascript" src="/hydro.js?version={{ global.Hydro.version['ui-default'] }}"></script>
|
||||
<script type="module" src="/entry.jsx?version={{ global.Hydro.version['ui-default'] }}"></script>
|
||||
{% else %}
|
||||
<script type="text/javascript" src="{{ UiContext.cdn_prefix }}resource/{{ global.Hydro.version['ui-default'] }}/lang-{{ _('__id') }}.js"></script>
|
||||
<script type="text/javascript" src="{{ UiContext.cdn_prefix }}hydro-{{ global.Hydro.version['ui-default'] }}.js"></script>
|
||||
|
||||
@@ -27,9 +27,6 @@ import 'vj/misc/nothing.styl';
|
||||
import 'vj/components/editor/cmeditor.styl';
|
||||
import 'vj/components/datepicker/datepicker.styl';
|
||||
import './dark.styl';
|
||||
|
||||
// load all page stylesheets
|
||||
const pageStyleReq = require.context('../', true, /\.page\.styl$/i);
|
||||
pageStyleReq.keys().map((key) => pageStyleReq(key));
|
||||
const pageStyleReqDefault = require.context('../', true, /\.page\.default\.styl$/i);
|
||||
pageStyleReqDefault.keys().map((key) => pageStyleReqDefault(key));
|
||||
import '../__glob_page.styl';
|
||||
import '../__glob_default.styl';
|
||||
@@ -0,0 +1,268 @@
|
||||
import importMetaUrlPlugin from '@codingame/esbuild-import-meta-url-plugin';
|
||||
import inject from '@rollup/plugin-inject';
|
||||
import fs from 'fs';
|
||||
import { globbySync } from 'globby';
|
||||
import httpProxy from 'http-proxy';
|
||||
import path from 'path';
|
||||
import colors from 'picocolors';
|
||||
// import federation from '@originjs/vite-plugin-federation';
|
||||
import { defineConfig } from 'vite';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
import svgr from 'vite-plugin-svgr';
|
||||
import { version } from './package.json';
|
||||
|
||||
const proxy = httpProxy.createProxyServer({
|
||||
ws: true,
|
||||
target: 'http://localhost:2333',
|
||||
});
|
||||
|
||||
const setOriginHeader = (proxyReq, options) => {
|
||||
if (options.changeOrigin) {
|
||||
const { target } = options;
|
||||
|
||||
if (proxyReq.getHeader('origin') && target) {
|
||||
const changedOrigin = typeof target === 'object'
|
||||
? `${target.protocol}//${target.host}`
|
||||
: target;
|
||||
|
||||
proxyReq.setHeader('origin', changedOrigin);
|
||||
}
|
||||
}
|
||||
};
|
||||
proxy.on('error', (err, req, originalRes) => {
|
||||
const res = originalRes;
|
||||
if (!res) {
|
||||
console.error(
|
||||
`${colors.red(`http proxy error: ${err.message}`)}\n${err.stack}`,
|
||||
{
|
||||
timestamp: true,
|
||||
error: err,
|
||||
},
|
||||
);
|
||||
} else if ('req' in res) {
|
||||
console.error(
|
||||
`${colors.red(`http proxy error: ${originalRes.req.url}`)}\n${err.stack
|
||||
}`,
|
||||
{
|
||||
timestamp: true,
|
||||
error: err,
|
||||
},
|
||||
);
|
||||
if (!res.headersSent && !res.writableEnded) {
|
||||
res
|
||||
.writeHead(500, {
|
||||
'Content-Type': 'text/plain',
|
||||
})
|
||||
.end();
|
||||
}
|
||||
} else {
|
||||
console.error(`${colors.red('ws proxy error:')}\n${err.stack}`, {
|
||||
timestamp: true,
|
||||
error: err,
|
||||
});
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
proxy.on('proxyReq', (proxyReq, req, res, options) => {
|
||||
setOriginHeader(proxyReq, options);
|
||||
});
|
||||
proxy.on('proxyReqWs', (proxyReq, req, socket, options) => {
|
||||
setOriginHeader(proxyReq, options);
|
||||
socket.on('error', (err) => {
|
||||
console.error(
|
||||
`${colors.red('ws proxy socket error:')}\n${err.stack}`,
|
||||
{
|
||||
timestamp: true,
|
||||
error: err,
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
proxy.on('proxyRes', (proxyRes, req, res) => {
|
||||
res.on('close', () => {
|
||||
if (!res.writableEnded) {
|
||||
proxyRes.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getGlobStyle(glob = '**/*.page.styl') {
|
||||
const files = globbySync(glob, { cwd: __dirname, ignore: ['node_modules'] });
|
||||
const result = [];
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(path.join(__dirname, file), 'utf-8');
|
||||
if (content.includes('@import \'.')) {
|
||||
result.push(`@import ${JSON.stringify(file)}`);
|
||||
} else {
|
||||
result.push(content);
|
||||
}
|
||||
}
|
||||
return `${result.filter((i) => i.startsWith('@import')).join('\n')}
|
||||
${result.filter((i) => !i.startsWith('@import')).join('\n')}`;
|
||||
}
|
||||
function updateGlobStyle(glob, filename) {
|
||||
const file = path.join(__dirname, filename);
|
||||
const content = getGlobStyle(glob);
|
||||
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf-8') !== content) {
|
||||
fs.writeFileSync(file, content);
|
||||
}
|
||||
}
|
||||
updateGlobStyle('**/*.page.styl', '__glob_page.styl');
|
||||
updateGlobStyle('**/*.page.default.styl', '__glob_default.styl');
|
||||
function getGlobPage(glob = '**/*.page.[jt]sx?') {
|
||||
const files = globbySync(glob, { cwd: __dirname, ignore: ['node_modules'] });
|
||||
const result = [];
|
||||
const exps = [];
|
||||
for (const file of files) {
|
||||
result.push(`import ${file.replace(/[/\\.-]/g, '_')} from "${file.startsWith('/') ? file : `./${file}`}";`);
|
||||
exps.push(file.replace(/[/\\.-]/g, '_'));
|
||||
}
|
||||
result.push(`export default [${exps.join(',')}]`);
|
||||
return result.join('\n');
|
||||
}
|
||||
function updateGlobPage(glob, filename) {
|
||||
const file = path.join(__dirname, filename);
|
||||
const content = getGlobPage(glob);
|
||||
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf-8') !== content) {
|
||||
fs.writeFileSync(file, content);
|
||||
}
|
||||
}
|
||||
updateGlobPage(['**/*.page.js', '**/*.page.ts', '**/*.page.jsx', '**/*.page.tsx'], '__glob_page.js');
|
||||
|
||||
function patchPrism() {
|
||||
const langs = globbySync('prism-*.js', { cwd: import.meta.resolve('prismjs/components').split(':')[1], ignore: ['node_modules'] });
|
||||
const lines = langs.filter((i) => !i.endsWith('.min.js')).map((i) => {
|
||||
const name = i.split('prism-')[1].split('.')[0];
|
||||
return `'${name}': () => require('./${i}'),`;
|
||||
});
|
||||
const loader = `export default {
|
||||
${lines.join('\n')}
|
||||
}`;
|
||||
fs.writeFileSync(import.meta.resolve('prismjs/components/index.js').split(':')[1], loader);
|
||||
}
|
||||
patchPrism();
|
||||
|
||||
export default defineConfig({
|
||||
root: __dirname,
|
||||
esbuild: {
|
||||
jsx: 'transform',
|
||||
loader: 'tsx',
|
||||
},
|
||||
publicDir: 'static',
|
||||
build: {
|
||||
minify: process.env.NODE_NEV === 'production',
|
||||
outDir: 'public',
|
||||
rollupOptions: {
|
||||
input: './entry.jsx',
|
||||
output: {
|
||||
globals: {
|
||||
jQuery: 'jQuery',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
dedupe: ['monaco-editor', 'vscode'],
|
||||
alias: {
|
||||
vj: __dirname,
|
||||
},
|
||||
},
|
||||
define: {
|
||||
'process.env.VERSION': JSON.stringify(version),
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
|
||||
...(process.env.NODE_ENV === 'development' ? { 'process.cwd': '()=>null' } : {}),
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['jquery'],
|
||||
esbuildOptions: {
|
||||
plugins: [importMetaUrlPlugin],
|
||||
},
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
styl: {
|
||||
use: [],
|
||||
imports: [
|
||||
// import.meta.resolve('rupture/rupture/index.styl'),
|
||||
path.join(__dirname, 'common/common.inc.styl'),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
port: 8000,
|
||||
headers: {
|
||||
'Cross-Origin-Opener-Policy': 'same-origin',
|
||||
'Cross-Origin-Embedder-Policy': 'require-corp',
|
||||
},
|
||||
proxy: {
|
||||
},
|
||||
},
|
||||
worker: {
|
||||
format: 'es',
|
||||
},
|
||||
plugins: [
|
||||
inject({
|
||||
$: 'jquery',
|
||||
React: 'react',
|
||||
include: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
|
||||
}),
|
||||
svgr({}),
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{ src: 'components/navigation/nav-logo-small_dark.png', dest: 'components/navigation/nav-logo-small_dark.png' },
|
||||
{ src: import.meta.resolve('streamsaver/mitm.html'), dest: 'streamsaver/mitm.html' },
|
||||
{ src: import.meta.resolve('streamsaver/sw.js'), dest: 'streamsaver/sw.js' },
|
||||
{ src: import.meta.resolve('vditor/dist'), dest: 'vditor/dist' },
|
||||
// { from: root(`${dirname(require.resolve('graphiql/package.json'))}/graphiql.min.css`), to: 'graphiql.min.css' },
|
||||
// { from: `${dirname(require.resolve('monaco-themes/package.json'))}/themes`, to: 'monaco/themes/' },
|
||||
],
|
||||
}),
|
||||
VitePWA({
|
||||
injectRegister: null,
|
||||
registerType: 'autoUpdate',
|
||||
strategies: 'injectManifest',
|
||||
srcDir: '.',
|
||||
filename: 'service-worker.ts',
|
||||
injectManifest: {
|
||||
injectionPoint: undefined,
|
||||
},
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
|
||||
},
|
||||
devOptions: {
|
||||
enabled: true,
|
||||
type: 'module',
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: 'configure-server',
|
||||
watchChange(id) {
|
||||
if (id.endsWith('.styl') && !id.includes('/__')) {
|
||||
console.log('change', id);
|
||||
updateGlobStyle('**/*.page.styl', '__glob_page.styl');
|
||||
updateGlobStyle('**/*.page.default.styl', '__glob_default.styl');
|
||||
}
|
||||
},
|
||||
configureServer(server) {
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
// console.log(req.url);
|
||||
const resource = req.url.split('?')[0];
|
||||
if (['/@fs/', '/@vite/', '/sw.js', '/dev-sw.js', '/vditor'].some((t) => resource.startsWith(t))) next();
|
||||
else if (resource !== '/' && fs.existsSync(path.join(__dirname, resource.substring(1)))) next();
|
||||
else {
|
||||
const options = {};
|
||||
proxy.web(req, res, options);
|
||||
}
|
||||
});
|
||||
server.httpServer.on('upgrade', (req, socket, head) => {
|
||||
if (req.url !== '/') {
|
||||
proxy.ws(req, socket, head);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
Reference in new issue
Block a user