summaryrefslogtreecommitdiff
path: root/packages/client/src/nirax.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2022-12-27 14:36:33 +0900
commit9384f5399da39e53855beb8e7f8ded1aa56bf72e (patch)
treece5959571a981b9c4047da3c7b3fd080aa44222c /packages/client/src/nirax.ts
parentwip: retention for dashboard (diff)
downloadmisskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.gz
misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.tar.bz2
misskey-9384f5399da39e53855beb8e7f8ded1aa56bf72e.zip
rename: client -> frontend
Diffstat (limited to 'packages/client/src/nirax.ts')
-rw-r--r--packages/client/src/nirax.ts275
1 files changed, 0 insertions, 275 deletions
diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts
deleted file mode 100644
index 53e73a8d48..0000000000
--- a/packages/client/src/nirax.ts
+++ /dev/null
@@ -1,275 +0,0 @@
-// NIRAX --- A lightweight router
-
-import { EventEmitter } from 'eventemitter3';
-import { Ref, Component, ref, shallowRef, ShallowRef } from 'vue';
-import { pleaseLogin } from '@/scripts/please-login';
-import { safeURIDecode } from '@/scripts/safe-uri-decode';
-
-type RouteDef = {
- path: string;
- component: Component;
- query?: Record<string, string>;
- loginRequired?: boolean;
- name?: string;
- hash?: string;
- globalCacheKey?: string;
- children?: RouteDef[];
-};
-
-type ParsedPath = (string | {
- name: string;
- startsWith?: string;
- wildcard?: boolean;
- optional?: boolean;
-})[];
-
-export type Resolved = { route: RouteDef; props: Map<string, string>; child?: Resolved; };
-
-function parsePath(path: string): ParsedPath {
- const res = [] as ParsedPath;
-
- path = path.substring(1);
-
- for (const part of path.split('/')) {
- if (part.includes(':')) {
- const prefix = part.substring(0, part.indexOf(':'));
- const placeholder = part.substring(part.indexOf(':') + 1);
- const wildcard = placeholder.includes('(*)');
- const optional = placeholder.endsWith('?');
- res.push({
- name: placeholder.replace('(*)', '').replace('?', ''),
- startsWith: prefix !== '' ? prefix : undefined,
- wildcard,
- optional,
- });
- } else if (part.length !== 0) {
- res.push(part);
- }
- }
-
- return res;
-}
-
-export class Router extends EventEmitter<{
- change: (ctx: {
- beforePath: string;
- path: string;
- resolved: Resolved;
- key: string;
- }) => void;
- replace: (ctx: {
- path: string;
- key: string;
- }) => void;
- push: (ctx: {
- beforePath: string;
- path: string;
- route: RouteDef | null;
- props: Map<string, string> | null;
- key: string;
- }) => void;
- same: () => void;
-}> {
- private routes: RouteDef[];
- public current: Resolved;
- public currentRef: ShallowRef<Resolved> = shallowRef();
- public currentRoute: ShallowRef<RouteDef> = shallowRef();
- private currentPath: string;
- private currentKey = Date.now().toString();
-
- public navHook: ((path: string, flag?: any) => boolean) | null = null;
-
- constructor(routes: Router['routes'], currentPath: Router['currentPath']) {
- super();
-
- this.routes = routes;
- this.currentPath = currentPath;
- this.navigate(currentPath, null, false);
- }
-
- public resolve(path: string): Resolved | null {
- let queryString: string | null = null;
- let hash: string | null = null;
- if (path[0] === '/') path = path.substring(1);
- if (path.includes('#')) {
- hash = path.substring(path.indexOf('#') + 1);
- path = path.substring(0, path.indexOf('#'));
- }
- if (path.includes('?')) {
- queryString = path.substring(path.indexOf('?') + 1);
- path = path.substring(0, path.indexOf('?'));
- }
-
- if (_DEV_) console.log('Routing: ', path, queryString);
-
- function check(routes: RouteDef[], _parts: string[]): Resolved | null {
- forEachRouteLoop:
- for (const route of routes) {
- let parts = [..._parts];
- const props = new Map<string, string>();
-
- pathMatchLoop:
- for (const p of parsePath(route.path)) {
- if (typeof p === 'string') {
- if (p === parts[0]) {
- parts.shift();
- } else {
- continue forEachRouteLoop;
- }
- } else {
- if (parts[0] == null && !p.optional) {
- continue forEachRouteLoop;
- }
- if (p.wildcard) {
- if (parts.length !== 0) {
- props.set(p.name, safeURIDecode(parts.join('/')));
- parts = [];
- }
- break pathMatchLoop;
- } else {
- if (p.startsWith) {
- if (parts[0] == null || !parts[0].startsWith(p.startsWith)) continue forEachRouteLoop;
-
- props.set(p.name, safeURIDecode(parts[0].substring(p.startsWith.length)));
- parts.shift();
- } else {
- if (parts[0]) {
- props.set(p.name, safeURIDecode(parts[0]));
- }
- parts.shift();
- }
- }
- }
- }
-
- if (parts.length === 0) {
- if (route.children) {
- const child = check(route.children, []);
- if (child) {
- return {
- route,
- props,
- child,
- };
- } else {
- continue forEachRouteLoop;
- }
- }
-
- if (route.hash != null && hash != null) {
- props.set(route.hash, safeURIDecode(hash));
- }
-
- if (route.query != null && queryString != null) {
- const queryObject = [...new URLSearchParams(queryString).entries()]
- .reduce((obj, entry) => ({ ...obj, [entry[0]]: entry[1] }), {});
-
- for (const q in route.query) {
- const as = route.query[q];
- if (queryObject[q]) {
- props.set(as, safeURIDecode(queryObject[q]));
- }
- }
- }
-
- return {
- route,
- props,
- };
- } else {
- if (route.children) {
- const child = check(route.children, parts);
- if (child) {
- return {
- route,
- props,
- child,
- };
- } else {
- continue forEachRouteLoop;
- }
- } else {
- continue forEachRouteLoop;
- }
- }
- }
-
- return null;
- }
-
- const _parts = path.split('/').filter(part => part.length !== 0);
-
- return check(this.routes, _parts);
- }
-
- private navigate(path: string, key: string | null | undefined, emitChange = true) {
- const beforePath = this.currentPath;
- this.currentPath = path;
-
- const res = this.resolve(this.currentPath);
-
- if (res == null) {
- throw new Error('no route found for: ' + path);
- }
-
- if (res.route.loginRequired) {
- pleaseLogin('/');
- }
-
- const isSamePath = beforePath === path;
- if (isSamePath && key == null) key = this.currentKey;
- this.current = res;
- this.currentRef.value = res;
- this.currentRoute.value = res.route;
- this.currentKey = res.route.globalCacheKey ?? key ?? path;
-
- if (emitChange) {
- this.emit('change', {
- beforePath,
- path,
- resolved: res,
- key: this.currentKey,
- });
- }
-
- return res;
- }
-
- public getCurrentPath() {
- return this.currentPath;
- }
-
- public getCurrentKey() {
- return this.currentKey;
- }
-
- public push(path: string, flag?: any) {
- const beforePath = this.currentPath;
- if (path === beforePath) {
- this.emit('same');
- return;
- }
- if (this.navHook) {
- const cancel = this.navHook(path, flag);
- if (cancel) return;
- }
- const res = this.navigate(path, null);
- this.emit('push', {
- beforePath,
- path,
- route: res.route,
- props: res.props,
- key: this.currentKey,
- });
- }
-
- public replace(path: string, key?: string | null, emitEvent = true) {
- this.navigate(path, key);
- if (emitEvent) {
- this.emit('replace', {
- path,
- key: this.currentKey,
- });
- }
- }
-}