diff options
| author | aura <nw@moneybot.cc> | 2026-02-19 19:57:10 +0100 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-02-19 19:57:10 +0100 |
| commit | bedf43af45d97a10a6f62b4f1bb21cd66fda1d71 (patch) | |
| tree | 6501bb95977a574c188bef6a228ff7500b243f3a /public | |
| parent | b5fca421c8f5f0f8f26d1392ef48635196887fa3 (diff) | |
empty moneyjsx site
Diffstat (limited to 'public')
35 files changed, 2360 insertions, 0 deletions
diff --git a/public/package.json b/public/package.json new file mode 100644 index 0000000..4418f02 --- /dev/null +++ b/public/package.json @@ -0,0 +1,32 @@ +{ + "type": "module", + "name": "jqueryjsx", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "build": "webpack --config webpack-prod.config.cjs", + "start": "webpack serve --open --config webpack-dev.config.cjs" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@types/jquery": "^3.5.32", + "@types/react": "^18.3.12", + "copy-webpack-plugin": "^12.0.2", + "css-loader": "^7.1.2", + "highlight.js": "^11.11.1", + "html-webpack-plugin": "^5.6.3", + "jquery": "^4.0.0-beta.2", + "jsx-runtime": "^1.2.0", + "nakedjsx": "^0.17.2", + "style-loader": "^4.0.0", + "typescript": "^5.6.3" + }, + "devDependencies": { + "ts-loader": "^9.5.1", + "webpack": "^5.95.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.1.0" + } +} diff --git a/public/src/api.tsx b/public/src/api.tsx new file mode 100644 index 0000000..fa941ec --- /dev/null +++ b/public/src/api.tsx @@ -0,0 +1,39 @@ +export const url = "https://forum.networkheaven.net/api/"; + +export interface ReqParams { + method: string, + body?: string, +} + +export async function post( endpoint: string, body: Object ) { + return await req( endpoint, { + method: "POST", + body: JSON.stringify( body ), + } ); +} + +export async function req( endpoint: string, params: ReqParams ) { + const res = await fetch( `${url}/${endpoint}`, { + method: params.method, + headers: { + "Content-Type": "application/json", + }, + body: params.body, + } ); + + if( !res.ok ) { + let json = null; + try { + json = await res.json(); + } catch( e: any ) { + throw new Error( "error contacting server" ); + } + + throw new Error( json.msg ); + } + + const json = await res.json(); + if( json.status != 'ok' ) + throw new Error( json.msg ); + return json; +} diff --git a/public/src/components.tsx b/public/src/components.tsx new file mode 100644 index 0000000..689179a --- /dev/null +++ b/public/src/components.tsx @@ -0,0 +1,257 @@ +import $ from "jquery"; +import * as JSX from "./jsx"; +import { Header } from "./header"; + +const popup_stack = []; +window.onclick = ( e: Event ) => { + if( !e.target ) return; + + if( popup_stack.length > 0 ) { + const last = popup_stack[popup_stack.length - 1]; + if( last.el[0] == e.target || last.el.find( e.target ).length != 0 ) return; + e.preventDefault(); + e.stopPropagation(); + if( last.fn ) + last.fn(); + + popup_stack.pop(); + last.el.remove(); + } +} + +/** + * appends an element to the DOM and saves it in the popup stack to be removed. +**/ +export function addPopup( element: any ) { + document.body.appendChild( element[0] ); + setTimeout( () => popup_stack.push( { el: element, fn: null } ) ); +} + +/** + * closes the topmost popup +**/ +export function closePopup() { + if( popup_stack.length > 0 ) { + const last = popup_stack[popup_stack.length - 1]; + if( last.fn ) + last.fn(); + + popup_stack.pop(); + setTimeout( () => last.el.remove() ); + } +} + +/** + * sets a callback that will get executed once the current popup is closed + **/ +export function onPopupClosed( fn: Function ) { + setTimeout( () => { + if( popup_stack.length > 0 ) { + popup_stack[popup_stack.length - 1].fn = fn; + } + } ); +} + +/* + * accepts "folded" prop +**/ +export function RolldownListItem( props: any ) { + const ret = <div class="rolldown"> + <div class="rolldown-collapsed-container"> + <div class="rolldown-icon-container">></div> + <div class="rolldown-collapsed">{props.folded}</div> + </div> + <div class="rolldown-expanded-container"> + <div class="rolldown-expanded">{props.children}</div> + </div> + </div>; + + ret.onclick = () => { + $( ret ).toggleClass( "active" ); + $( ret ).find( ".rolldown-expanded-container" ).toggleClass( 'active' ); + }; + + return ret; +} + +export function Spinner( props: any ) { + let spinner_steps = [ + '/', + '-', + '\\', + '|', + '/', + '-', + '\\', + '|' + ]; + + const id = props.id || ''; + + let el = $( <div class="spinner" id={ id } style={ props.style || '' } /> ); + let i = 0; + let loop = () => { + el.text( spinner_steps[i++] ); + if( i > spinner_steps.length ) + i = 0; + + if( el[0].isConnected ) + setTimeout( loop, 100 ); + }; + + setTimeout( loop, 100 ); + return el[0]; +} + +/* + * accepts title prop +**/ +export function RolldownList( props: any ) { + return <GroupBox title={props.title} style={props.style} innerStyle="margin: 0px; width: 100%"> + <div class="rolldownlist"> + { props.children } + </div> + </GroupBox> +} + +/* + * accepts title prop and optional innerStyle +**/ +export function GroupBox( props: any ) { + return <div class="groupbox" id={props.id || ''} style={props.style || ''}> + <span class="grouptitle"> + {props.title} + </span> + <span class="groupbody" style={props.innerStyle || ''}> + {props.children} + </span> + </div> +} + +export function Page( props: any ) { + return <> + <Header /> + <div id="page-main"> + <div id="page-main-content"> + {props.children} + </div> + </div> + + <BackgroundToggle /> + </> +} + +export function DropdownItem( props: any ) { + return <div class="dropdown-inner" style={ props.style || "" } onclick={ props.onclick || null }> + {props.children} + </div> +} + +/** + * supports innerStyle for styling the actual dropdown picker + **/ +export function Dropdown( props: any ) { + const children = props.children; + let title = props.title; + let inline = props.inline; + let onchange = props.onchange; + let classes = props.class || ''; + let style = props.style || ""; + let id = props.id || ''; + let innerStyle = props.innerStyle || ""; + + const showItems = ( e: Event ) => { + e.preventDefault(); + const target = $( e.target as HTMLElement ); + + const newDropdown = $( <div class="dropdown-wrapper" style={ innerStyle }> + { children.map( ( child: HTMLElement ) => { + if( !child.onclick ) child.onclick = onchange; return child; + } ) } + </div> ); + target.parent().append( newDropdown[0] ); + setTimeout( () => popup_stack.push( { el: newDropdown, fn: null } ) ); + } + + if( inline ) { + return <button class={ 'dropdown' + ' ' + classes } style={ style } onclick={ showItems } id={ id }> + { title } + </button> + } + else { + return <> + <label>{ title }</label> + <button class={ 'dropdown' + ' ' + classes } style={ style } onclick={ showItems } id={ id }> + </button> + </> + } +} + +export function OkPopup( props: any ) { + const children = props.children; + const classes = props.class || ''; + const style = props.style || ''; + const id = props.id || ''; + + const onclick = ( e: Event ) => { + e.preventDefault(); + e.stopPropagation(); + if( props.onclick ) + props.onclick(); + + closePopup(); + } + + return <div class={ "popup-msg " + classes } id={ id } style={ style }> + { children } + <div style="display: flex; justify-content: center"> + <button onclick={ onclick }>Ok</button> + </div> + </div> +} + +export function OkCancelPopup( props: any ) { + const children = props.children; + const classes = props.class || ''; + const style = props.style || ''; + const id = props.id || ''; + + const onclick = ( e: Event ) => { + e.preventDefault(); + e.stopPropagation(); + if( props.onclick ) + props.onclick(); + + closePopup(); + } + + const oncancel = ( e: Event ) => { + e.preventDefault(); + e.stopPropagation(); + + closePopup(); + } + + return <div class={ "popup-msg " + classes } id={ id } style={ style }> + { children } + <div style="display: flex; justify-content: center"> + <button onclick={ onclick } style="margin-right: 10px">Ok</button> + <button onclick={ oncancel }>Cancel</button> + </div> + </div> +} + +export function BackgroundToggle() { + const toggleBackground = () => { + const main = $( "#page-main" ); + if( main.css( "display" ) == "none" ) { + main.css( "display", "" ); + } else { + main.css( "display", "none" ); + } + } + + return <div id="background-toggle" onclick={ toggleBackground }> + show background + </div> +} diff --git a/public/src/header.tsx b/public/src/header.tsx new file mode 100644 index 0000000..731241d --- /dev/null +++ b/public/src/header.tsx @@ -0,0 +1,10 @@ +import $ from 'jquery'; +import * as JSX from './jsx'; + +export function Header( props: any ) { + return <div class="border-wrapper" style="z-index: 1"> + <div class="header"> + forum.networkheaven.net + </div> + </div> +} diff --git a/public/src/home.tsx b/public/src/home.tsx new file mode 100644 index 0000000..eb7a674 --- /dev/null +++ b/public/src/home.tsx @@ -0,0 +1,11 @@ +import $ from "jquery"; +import * as JSX from "./jsx"; +import { Page } from "./components"; + +export default function Home() { + return <Page> + <div class="page-title"> + <h3 style="font-family: JPN24; width: max-content" class="gradient">NETWORKHEAVEN</h3> + </div> + </Page>; +} diff --git a/public/src/index-page.tsx b/public/src/index-page.tsx new file mode 100644 index 0000000..dabaf05 --- /dev/null +++ b/public/src/index-page.tsx @@ -0,0 +1,10 @@ +import * as JSX from "./jsx"; +import Home from "./home"; + +JSX.setDefaultTitle( "forum.networkheaven.net" ); +JSX.addRoute( "/", () => <Home /> ); + +document.head.appendChild( <link rel="shortcut icon" href="/static/icon.ico" /> ); + +const url = new URL( window.location.href ); +JSX.navigateParams( url.pathname, url.searchParams.entries() ); diff --git a/public/src/index.html b/public/src/index.html new file mode 100644 index 0000000..215dd8f --- /dev/null +++ b/public/src/index.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="description" content="networkheaven forum"> + <meta name="viewport" content="user-scalable=yes"> + <title>forum.networkheaven.net</title> + <link rel="stylesheet" href="/static/main.css"> + <link href="/static/highlight.css" rel="preload" as="style" onload="this.rel='stylesheet'"> + <link rel="icon" href="data:image/png;base64,iVBORw0KGgo="> + <noscript> + <link rel="shortcut icon" href="/static/icon.ico" type="image"> + </noscript> + </head> + <body> + <div id="moneyjsx-root"> + <div id="homepage" style="padding-top: 0px"> + <noscript> + + <!--- for browsers with noscript !---> + <div id="ascii-art"> + + </div> + <h3 style="margin-top: 5px;">forum.networkheaven.net</h3> + <div> + you need javascript to use this website + </div> + </noscript> + </div> + </div> + </body> +</html> + diff --git a/public/src/jsx.tsx b/public/src/jsx.tsx new file mode 100644 index 0000000..db46f15 --- /dev/null +++ b/public/src/jsx.tsx @@ -0,0 +1,338 @@ +import $ from 'jquery'; +const assetAttributeNames = new Set( ['data', 'srcset', 'src', 'href'] ); + +let curRoute = null; +export interface Route { + path: string, + component: Function, + wildcard: boolean +}; + +const routes: Route[] = []; +let err404page = "/"; +let rootId = "moneyjsx-root"; +let defaultTitle = ""; +let onprenavigate: Function = () => {}; +let onpostnavigate: Function = () => {}; + +function routeForPath( route: string ) : Function | null { + if( !routes[route] ) { + for( let key of Object.keys( routes ) ) { + const r = routes[key]; + + if( r.wildcard ) { + if( route.slice( 0, r.path.length ) == r.path ) { + return r.component; + } + } + } + + return null; + } else return routes[route].component; +} + +/** + * sets the id of the element to be replaced by the navigator + **/ +export function setRootId( rootId: string ) { + rootId = rootId; +} + +export function setDefaultTitle( title: string ) { + defaultTitle = title; +} + +/** + * adds a route component to the routes list + * the component function must return either a jquery or a DOM element + **/ +export function addRoute( name: string, component: Function ) { + let path = name; + let wildcard = false; + if( path[path.length - 1] === "*" ) { + path = path.substring( 0, path.length - 1 ); + wildcard = true; + } + + routes[path] = { path, component, wildcard }; +} + +/** + * sets the route for a 404 page + **/ +export function set404Route( name: string ) { + err404page = name; +} + +/** + * sets the callback that will get called when a route changes + **/ +export function onPreNavigate( callback: Function ) { + onprenavigate = callback; +} + +/** + * sets the callback that will get called when a route changes + **/ +export function onPostNavigate( callback: Function ) { + onpostnavigate = callback; +} + + +/** + * replaces the root element with the route component + **/ +export function navigate( route: string ) { + let url = new URL( window.location.href ); + let cb = routeForPath( route ); + url.pathname = route; + if( !cb ) + return navigate( err404page ); + + if( curRoute != cb ) + window.history.pushState( {}, null, url.href ); + + onprenavigate(); + setTitle(); + const el = $( cb() ); + curRoute = cb; + + $( `#${rootId}` ).children().remove(); + $( `#${rootId}` ).append( el ); + onpostnavigate(); +} + +/** + * navigate with params. see: navigate + **/ +export function navigateParams( route: string, params: any ) { + let url = new URL( window.location.href ); + let uparams = new URLSearchParams( params ); + url.pathname = route; + url.search = uparams.toString(); + let cb = routeForPath( route ); + if( !cb ) + return navigate( err404page ); + + if( curRoute != cb ) + window.history.pushState( {}, null, url.href ); + + onprenavigate(); + setTitle(); + const el = $( cb() ); + curRoute = cb; + + $( `#${rootId}` ).children().remove(); + $( `#${rootId}` ).append( el ); + onpostnavigate(); +} + +/** + * convenience function to pass to href elements + **/ +export function href( e: Event ) { + const el = $( e.target ); + if( el.is( 'a' ) ) { + e.preventDefault(); + navigate( el.attr( 'href' ) ); + } +} + +/** + * wrapper for history.pushState + **/ +export function pushParams( params: any ) { + const url = new URL( window.location.href ); + url.search = new URLSearchParams( params ).toString(); + + window.history.pushState( {}, null, url.href ); +} + +/** + * navigates without adding a history entry + * useful for e.g. re-rendering a page after waiting for a data callback +**/ +export function navigateParamsSilent( route: string, params: any ) { + let url = new URL( window.location.href ); + let uparams = new URLSearchParams( params ); + url.pathname = route; + url.search = uparams.toString(); + let cb = routeForPath( route ); + if( !cb ) + return navigateSilent( err404page ); + + onprenavigate(); + setTitle(); + const el = $( cb() ); + curRoute = cb; + + $( `#${rootId}` ).children().remove(); + $( `#${rootId}` ).append( el ); + onpostnavigate(); +} + +/** + * see: navigateParamsSilent + **/ +export function navigateSilent( route: string ) { + let url = new URL( window.location.href ); + url.pathname = route; + let cb = routeForPath( route ); + if( !cb ) + return navigateSilent( err404page ); + + onprenavigate(); + setTitle(); + const el = $( cb() ); + curRoute = cb; + + $( `#${rootId}` ).children().remove(); + $( `#${rootId}` ).append( el ); + onpostnavigate(); +} + +/** + * action when the back button is pressed +**/ +export function onPopState() { + let url = new URL( window.location.href ); + let uparams = new URLSearchParams( url.searchParams ); + url.search = uparams.toString(); + let cb = routeForPath( url.pathname ); + if( !cb ) + return navigateSilent( err404page ); + + if( cb == curRoute ) + return; + + onprenavigate(); + setTitle(); + const el = $( cb() ); + curRoute = cb; + + $( `#${rootId}` ).children().remove(); + $( `#${rootId}` ).append( el ); + onpostnavigate(); +} + +/** + * navigates to the parent directory from the current page +**/ +export function goUpDirectory() { + const url = new URL( window.location.href ); + if( url.pathname.endsWith( "/" ) ) + url.pathname = url.pathname.slice( 0, -1 ); + let idx = url.pathname.lastIndexOf( "/" ); + if( idx === -1 ) + return; + url.pathname = url.pathname.slice( 0, url.pathname.lastIndexOf( "/" ) ); + navigate( url.pathname ); +} + +export function getRoutes() : Route[] { + return routes; +} + + +// internal stuff below + +const originalAppendChild = Element.prototype.appendChild; +Element.prototype.appendChild = function( child: any ) { + if( Array.isArray( child ) ) { + for( const childArrayMember of child ) + this.appendChild( childArrayMember ); + + return child; + } + else if( typeof child === 'string' ) { + return originalAppendChild.call( this, document.createTextNode( child ) ); + } + else if( child ) { + return originalAppendChild.call( this, child ); + } +}; + +export function createElement( tag: any, props: any, ...children: any ) { + props = props || {}; + + if( typeof tag === "function" ) { + props.children = children; + return tag( props ); + } + + if( tag === 'raw-content' ) { + const dummy = document.createElement( 'div' ); + dummy.innerHTML = props.content; + return [...dummy.children]; + } + + const element = document.createElement( tag ); + + for( const [name, value] of Object.entries( props ) ) { + if( name.startsWith( 'on' ) ) { + const lowercaseName = name.toLowerCase(); + + if( lowercaseName in window ) { + element.addEventListener( lowercaseName.substring( 2 ), value ); + continue; + } + } + + if( name == 'ref' ) { + ( value as any ).current = element; + continue; + } + + if( value === false ) + continue; + + if( value === true ) { + element.setAttribute( name, '' ); + continue; + } + + if( assetAttributeNames.has( name ) ) { + if( typeof value === 'string' ) { + element.setAttribute( name, value ); + } + continue; + } + + element.setAttribute( name, value ); + }; + + for( const child of children ) + element.appendChild( child ); + + return element; +} + +export function createFragment( props: any ) { + return props.children; +} + +function setTitle() { + document.title = defaultTitle; +} + +document.addEventListener( "click", e => { + let a = ( e.target ) as HTMLAnchorElement; + if( !a ) + return; + if( a.origin !== location.origin ) + return; + + e.preventDefault(); + if( !a.onclick ) { + if( routeForPath( a.pathname ) ) + return navigate( a.pathname ); + + const hasExt = /\.[a-zA-Z0-9]{1,8}$/.test( a.href ); + if( hasExt ) + location.href = a.href; + else + navigate( err404page ); + } +} ); + +window.onpopstate = onPopState; diff --git a/public/src/tsconfig.json b/public/src/tsconfig.json new file mode 100644 index 0000000..b964594 --- /dev/null +++ b/public/src/tsconfig.json @@ -0,0 +1,121 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + "moduleResolution": "node", + /* Language and Environment */ + "target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": [ + "ES2017", + "DOM", + "DOM.Iterable", + "ScriptHost" + ], + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "react", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + "jsxFactory": "JSX.createElement", + "jsxFragmentFactory": "JSX.createFragment", + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "es2020", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "baseUrl": ".", + "paths": { + "*": ["types/*"] + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": [ + "./node_modules/@types", + "./types" + ], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */ + "strictFunctionTypes": false, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + "strictBindCallApply": false, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + "strictPropertyInitialization": false, /* Check for class properties that are declared but not set in the constructor. */ + "strictBuiltinIteratorReturn": false, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + "noImplicitThis": false, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/public/src/user.tsx b/public/src/user.tsx new file mode 100644 index 0000000..d909d9e --- /dev/null +++ b/public/src/user.tsx @@ -0,0 +1,6 @@ +import $ from 'jquery'; + +import * as JSX from './jsx'; +import * as api from './api'; + + diff --git a/public/src/util.tsx b/public/src/util.tsx new file mode 100644 index 0000000..f083d9f --- /dev/null +++ b/public/src/util.tsx @@ -0,0 +1,60 @@ +export function escapeHtml( html: string ) { + const entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + + return String( html ).replace( /[&<>"'`=\/]/g, ( s ) => { + return entityMap[s]; + } ); +} + +export function parseJWT( token: string ) : any { + const parts = token.split( '.' ); + let encoded = parts[1]; + encoded = encoded.replace(/-/g, '+').replace(/_/g, '/'); + const pad = encoded.length % 4; + if( pad === 1 ) + throw new Error( 'what the fuck' ); + if( pad > 1 ) + encoded += new Array( 5 - pad ).join( '=' ); + + const payload = JSON.parse( atob( encoded ) ); + return payload; +} + +export function sizeHumanReadable( size: number, short: boolean = false ) { + if( size < 1024 ) + return size + (short? 'B' : ' B'); + else if( size < 1024 * 1024 ) + return ( size / 1024 ).toFixed( short? 1: 2 ) + (short? 'K' : ' KB'); + else if( size < 1024 * 1024 * 1024 ) + return ( size / 1024 / 1024 ).toFixed( short? 1 : 2 ) + (short? 'M' : ' MB'); + else + return ( size / 1024 / 1024 / 1024 ).toFixed( short? 1 : 2 ) + (short? 'G':' GB'); +} + +export function monthToNumber( month: string ) { + const months = [ + '', + 'jan', + 'feb', + 'mar', + 'apr', + 'may', + 'jun', + 'jul', + 'aug', + 'sep', + 'oct', + 'nov', + 'dec' + ]; + return months.indexOf( month.toLowerCase() ); +}; diff --git a/public/static/fonts/LICENSE.TXT b/public/static/fonts/LICENSE.TXT new file mode 100644 index 0000000..fd662a7 --- /dev/null +++ b/public/static/fonts/LICENSE.TXT @@ -0,0 +1,428 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/public/static/fonts/Web437_DOS-V_re_ANK16.woff b/public/static/fonts/Web437_DOS-V_re_ANK16.woff Binary files differnew file mode 100644 index 0000000..a61193e --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_ANK16.woff diff --git a/public/static/fonts/Web437_DOS-V_re_ANK19.woff b/public/static/fonts/Web437_DOS-V_re_ANK19.woff Binary files differnew file mode 100644 index 0000000..6842296 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_ANK19.woff diff --git a/public/static/fonts/Web437_DOS-V_re_ANK24.woff b/public/static/fonts/Web437_DOS-V_re_ANK24.woff Binary files differnew file mode 100644 index 0000000..a54c6ad --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_ANK24.woff diff --git a/public/static/fonts/Web437_DOS-V_re_ANK30.woff b/public/static/fonts/Web437_DOS-V_re_ANK30.woff Binary files differnew file mode 100644 index 0000000..623d973 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_ANK30.woff diff --git a/public/static/fonts/Web437_DOS-V_re_JPN12.woff b/public/static/fonts/Web437_DOS-V_re_JPN12.woff Binary files differnew file mode 100644 index 0000000..04ea332 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_JPN12.woff diff --git a/public/static/fonts/Web437_DOS-V_re_JPN16.woff b/public/static/fonts/Web437_DOS-V_re_JPN16.woff Binary files differnew file mode 100644 index 0000000..6c91b6e --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_JPN16.woff diff --git a/public/static/fonts/Web437_DOS-V_re_JPN19.woff b/public/static/fonts/Web437_DOS-V_re_JPN19.woff Binary files differnew file mode 100644 index 0000000..48f154d --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_JPN19.woff diff --git a/public/static/fonts/Web437_DOS-V_re_JPN24.woff b/public/static/fonts/Web437_DOS-V_re_JPN24.woff Binary files differnew file mode 100644 index 0000000..a77aca7 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_JPN24.woff diff --git a/public/static/fonts/Web437_DOS-V_re_JPN30.woff b/public/static/fonts/Web437_DOS-V_re_JPN30.woff Binary files differnew file mode 100644 index 0000000..3073f72 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_JPN30.woff diff --git a/public/static/fonts/Web437_DOS-V_re_PRC16.woff b/public/static/fonts/Web437_DOS-V_re_PRC16.woff Binary files differnew file mode 100644 index 0000000..4ddf047 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_PRC16.woff diff --git a/public/static/fonts/Web437_DOS-V_re_PRC19.woff b/public/static/fonts/Web437_DOS-V_re_PRC19.woff Binary files differnew file mode 100644 index 0000000..322c960 --- /dev/null +++ b/public/static/fonts/Web437_DOS-V_re_PRC19.woff diff --git a/public/static/fonts/Web437_IBM_PGC.woff b/public/static/fonts/Web437_IBM_PGC.woff Binary files differnew file mode 100644 index 0000000..23a07a1 --- /dev/null +++ b/public/static/fonts/Web437_IBM_PGC.woff diff --git a/public/static/highlight.css b/public/static/highlight.css new file mode 100644 index 0000000..faa5d4d --- /dev/null +++ b/public/static/highlight.css @@ -0,0 +1,7 @@ +/*! + Theme: Synth Midnight Terminal Dark + Author: Michaël Ball (http://github.com/michael-ball/) + License: ~ MIT (or more permissive) [via base16-schemes-source] + Maintainer: @highlightjs/core-team + Version: 2021.09.0 +*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#c1c3c4;background:#050608}.hljs ::selection,.hljs::selection{background-color:#28292a;color:#c1c3c4}.hljs-comment{color:#474849}.hljs-tag{color:#a3a5a6}.hljs-operator,.hljs-punctuation,.hljs-subst{color:#c1c3c4}.hljs-operator{opacity:.7}.hljs-bullet,.hljs-deletion,.hljs-name,.hljs-selector-tag,.hljs-template-variable,.hljs-variable{color:#b53b50}.hljs-attr,.hljs-link,.hljs-literal,.hljs-number,.hljs-symbol,.hljs-variable.constant_{color:#ea770d}.hljs-class .hljs-title,.hljs-title,.hljs-title.class_{color:#c9d364}.hljs-strong{font-weight:700;color:#c9d364}.hljs-addition,.hljs-code,.hljs-string,.hljs-title.class_.inherited__{color:#06ea61}.hljs-built_in,.hljs-doctag,.hljs-keyword.hljs-atrule,.hljs-quote,.hljs-regexp{color:#42fff9}.hljs-attribute,.hljs-function .hljs-title,.hljs-section,.hljs-title.function_,.ruby .hljs-property{color:#03aeff}.diff .hljs-meta,.hljs-keyword,.hljs-template-tag,.hljs-type{color:#ea5ce2}.hljs-emphasis{color:#ea5ce2;font-style:italic}.hljs-meta,.hljs-meta .hljs-keyword,.hljs-meta .hljs-string{color:#cd6320}.hljs-meta .hljs-keyword,.hljs-meta-keyword{font-weight:700}
\ No newline at end of file diff --git a/public/static/icon.ico b/public/static/icon.ico Binary files differnew file mode 100644 index 0000000..759724a --- /dev/null +++ b/public/static/icon.ico diff --git a/public/static/main.css b/public/static/main.css new file mode 100644 index 0000000..1ebd88f --- /dev/null +++ b/public/static/main.css @@ -0,0 +1,788 @@ +:root { + --back: #888; + --front: #E76969; + --green: #69E769; + --site-font: JPN16; + --gradient: linear-gradient(90deg,rgba(255, 100, 255, 1) 0%, rgba(0, 255, 255, 1) 100%); +} + +@font-face { + font-family: Terminal; + src: url( /static/fonts/Web437_IBM_PGC.woff ) +} + +@font-face { + font-family: JPN12; + src: url( /static/fonts/Web437_DOS-V_re_JPN12.woff ) +} + +@font-face { + font-family: JPN16; + src: url( /static/fonts/Web437_DOS-V_re_JPN16.woff ) +} + + +@font-face { + font-family: JPN19; + src: url( /static/fonts/Web437_DOS-V_re_JPN19.woff ) +} + +@font-face { + font-family: JPN24; + src: url( /static/fonts/Web437_DOS-V_re_JPN24.woff ) +} + +@font-face { + font-family: JPN30; + src: url( /static/fonts/Web437_DOS-V_re_JPN30.woff ) +} + +#moneyjsx-root { + display: flex; + flex-direction: column; + padding: 0; + margin: 0; + font-weight: normal; +} + +input[type="radio"] { + appearance: none; + background-color: var( --back ); + margin: 0; + font: inherit; + color: #888; + width: 1em; + height: 1em; + border: 0.15em solid currentColor; + border-radius: 50%; + display: grid; + place-content: center; +} + +input[type="radio"]::before { + content: ""; + width: 0.75em; + height: 0.75em; + border-radius: 50%; + transform: scale(0); + transition: 120ms transform ease-in-out; + box-shadow: inset 1em 1em var(--front); +} + +input[type="radio"]:checked::before { + transform: scale(1); +} + +.border-wrapper { + justify-content: center; + flex-direction: row; + align-self: center; + position: relative; + display: flex; + width: calc( 100% - 2px ); + background: var(--gradient); + padding: 1px 1px 1px 1px; + margin: 0px; +} + +.header { + width: calc(100% - 2px); + background: var(--back); + font-family: JPN24; + font-size: 26px; + height: 38px; + display: flex; + flex-direction: row; +} + +code { + font-family: Terminal; + font-size: 18px; + white-space: pre-wrap; + background: #212325; + padding: 5px 7px !important; + border-top: 1px solid #aaa; + border-left: 1px solid #888; + border-right: 1px solid #666; + border-bottom: 1px solid #000; + display: inline-block; + margin-top: 3px; + margin-bottom: 3px; +} + +html, body { + height: 100%; + overflow: auto; +} + +input { + background-color: #222; + border: 1px solid var(--front); + color: #888; + font-family: Code; +} + +button { + cursor: pointer; + border: 1px solid var(--front); + background-color: #222; + color: #fff; + font-size: 16px; + font-family: var( --site-font ); +} + +textarea { + border: 1px solid var( --front ); + background-color: #222; + color: white; +} + +hr { + border-top: 1px solid #aaa; + background: #ccc; + height: 1px; + width: calc( 100% - 2px ); +} + +a { + text-decoration: none; + background: var( --gradient ); + background-clip: border-box; + text-decoration: underline; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + color: #c6a6ff; +} + + +a:hover { + cursor: pointer; + color: #fff; + background: var( --gradient ); + background-clip: border-box; + text-decoration: underline; + -webkit-text-fill-color: unset; + -webkit-background-clip: text; + text-decoration: underline; +} + +.gradient { + background: var( --gradient ); + background-clip: border-box; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; +} + +.nogradient { + -webkit-text-fill-color: white; + -webkit-background-clip: text; + background: none; +} + +a.nogradient { + margin-bottom: 0px; + text-decoration: none; +} + +a.nogradient:hover { + background: var( --gradient ); + background-clip: border-box; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + text-decoration: underline; +} + +a.nogradient::after { + content:'.'; + -webkit-text-fill-color: transparent; + color: transparent; + width:calc( 100% - 7px ); + display:inline-block; + z-index: 2; + height: 1px; + margin-top: -2px; + background: #30e8bf; + padding: 0; + background: var( --gradient ); +} + +a.nogradient:hover::after { + background: none; + content: ''; +} + + +body { + background-color: var( --back ); + background-image: url( "/static/networkheaven.jpg" ); + font-family: var( --site-font ); + font-smooth: never !important; + background-position: center; + background-size: cover; + flex-direction: column; + display: flex; + color: #fff; + margin: 0; +} + + +#page-main { + flex-direction: row; + justify-content: center; + align-items: initial; + text-align: center; + padding: 30px 0 0; + overflow-x: clip; + display: flex; + width: 100%; + z-index: 0; + margin: 0; + margin-bottom: 30px; +} + +#page-main-content { + width: 90%; + background: var( --back ); + border-left: 1px solid #ccc; + border-top: 1px solid #fff; + border-right: 1px solid #888; + border-bottom: 1px solid #222; + position: relative; +} + + +.red { color: #e96969; } +.black { color: #212325; } +.green { color: #10bb10; } +.btn_close { background: #ccc; } + + +#ascii-art { + white-space: pre-wrap; + font-family: Code; + font-size: 12px; + overflow:clip; + padding-top: 5px; +} + +#ascii-art span { + padding: 0; + margin: 0; +} + +#sidebar { + width: 230px; + height: 100%; + margin-right: 20px; + text-align: left; + background: var( --back ); + border-left: 1px solid #ccc; + border-top: 1px solid #fff; + border-right: 1px solid #888; + border-bottom: 1px solid #222; +} + +#sidebar h3 { + margin-top: 8px; + margin-bottom: 8px; + background: var( --gradient ); + background-clip: border-box; + text-decoration: none; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + width: fit-content; + font-family: JPN24; + font-size: 24px; + margin-left: 4px; +} + +#sidebar h4 { + margin-top: 0px; + margin-bottom: 0px; + width: fit-content; + font-family: JPN16; + font-size: 17px; + margin-left: 4px; +} + +.sidebar-row { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding-right: 4px; + margin-bottom: 0px; +} + +.page-title { + display: flex; + justify-content: center +} + +.page-title h3 { + margin-top: 15px; + margin-bottom: 6px; + font-size: 25px; +} + +h5 { + font-family: JPN16; + font-size: 17px; + font-weight: normal; + margin-top: 12px; +} + + +.package-entry-date, +.package-entry-time { + padding: 0 10px; +} + +#blog-entry { + display: flex; + justify-content: center; + padding-top: 8px; + width: 95%; + font-size: 17px; +} + +#blog-entry h4 { + margin-top: 4px; + margin-bottom: 4px; + font-family: JPN19; + font-size: 20px; +} + +#blog-entry ul { + padding-left: 30px; +} + +@media( max-width: 1100px ) { + #page-main-content { + width: calc( 100% - 20px ) !important; + min-width: unset !important; + margin-right: 20px; + margin-left: 0 !important; + }; + + #sidebar { + margin-left: 20px; + } + + .page-title h3 { + margin-top: 8px; + margin-bottom: 0px; + } + + .page-title { + } + + + h5 { + margin-top: 9px; + } + + #sidebar h3 { + margin-top: 8px; + margin-bottom: 8px; + background: var( --gradient ); + background-clip: border-box; + text-decoration: none; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + width: fit-content; + font-family: JPN24; + font-size: 24px; + margin-left: 4px; + } + + .sidebar-row { + margin-bottom: 8px; + } + + #sidebar h4 { + font-family: JPN12; + font-size: 13px; + } + + #package-entries table { + font-family: JPN12 !important; + font-size: 13px !important; + text-align: right; + } + + #ascii-art { + font-size: 9px; + } + + #blog-entry { + width: 98%; + font-family: JPN12; + font-size: 13px; + } +} + +@media( max-width: 740px ) { + #sidebar { + width: 200px; + } + + #sidebar h4 { + font-size: 10px; + margin-bottom: 0px; + margin-top: 0px; + } + + .page-title h3 { + font-size: 20px; + margin-top: 6px; + margin-bottom: 0px; + } + + h5 { + font-family: JPN16; + font-size: 10px; + font-weight: normal; + margin-top: 7px; + } + + #sidebar h3 { + font-size: 20px; + } + + .sidebar-row { + margin-bottom: 10px; + } + + + #package-entries table { + font-family: JPN12 !important; + font-size: 8px !important; + text-align: right; + width: 99% !important; + } + + #ascii-art { + font-size: 6px; + } + + .package-entry-date, + .package-entry-time { + padding: 0; + } +} + + +@media( max-width: 500px ) { + #sidebar { + width: 150px; + margin-left: 5px; + margin-right: 5px; + } + + #page-main-content { + margin-right: 5px; + } + + #page-main { + padding-top: 10px; + } + + #blog-entry ul { + padding-left: 20px; + } + + #blog-entry h4 { + font-size: 13px; + } + + .page-title h3 { + font-size: 17px; + margin-top: 8px; + margin-bottom: 0px; + } + + #ascii-art { + font-size: 4px; + } + + #sidebar h4 { + font-size: 8px; + margin-bottom: 0px; + margin-top: 0px; + } + + #sidebar h3 { + font-size: 17px; + } + + h5 { + font-family: JPN12; + font-size: 9px; + font-weight: normal; + margin-top: 4px; + } + + #blog-entry { + font-size: 10px; + } + + #blog-entry code { + font-size: 10px; + } +} + +@media( max-width: 350px ) { + #ascii-art { + font-size: 3px; + } + + #sidebar h4 { + font-size: 6px; + margin-bottom: 0px; + margin-top: 0px; + } + + #sidebar h3 { + font-size: 14px; + } + + #blog-entry { + font-size: 7px; + } + + #blog-entry code { + font-size: 7px; + } + + .sidebar-row { + margin-bottom: 13px; + } + + #sidebar { + width: 90px; + } +} + + +.groupbox { + border: 1px solid var( --front ); + background-color: var( --back ); + justify-content: flex-start; + align-items: flex-start; + flex-direction: column; + height: fit-content; + min-height: 25px; + min-width: 333px; /* may need to change this for mobile */ + max-width: 600px; + display: flex; + margin: 5px; + z-index: 1; + flex: 1; +} +.groupbox > .grouptitle { + background-color: var( --back ); + font-family: inherit; + position: relative; + margin: 0 0 -15px; /* stupid hardcode, but its: ( title font height - 4 ) * -1 */ + padding: 0px 5px; + font-size: 18px; + z-index: 2; + top: -9px; + left: 5px; +} +.groupbody { + width: calc( 100% - 5px ); + height: calc( 100% - 5px ); + text-align: left; + margin: 5px; +} + +#popup-msgbox { + display: none; + justify-content: center; + align-items: center; + position: absolute; + left: 50%; + min-width: 250px; + border: 1px solid var( --front ); + background: var( --back ); + min-height: 120px; + top: 45vh; + transform: translate( -50%, -50% ); +} + + +.dropdown { + background-color: var( --back ); + border-color: var( --front ); + text-align: center; + color: #888; + height: 24px; + color: #fff; +} + +.dropdown-wrapper { + border: 2px inset var( --front ); + background-color: var( --back ); + justify-content: space-evenly; + flex-direction: column; + align-items: center; + position: absolute; + width: 256px; + z-index: 10; + margin-left: 10px; +} + +.dropdown-inner { + height: 30px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + border-bottom: 1px solid #333; + cursor: pointer; +} + +.rolldownlist { + height: fit-content; + position: relative; + width: 100%; + padding: 0; + margin: 0; +} + +.rolldown { + transition: background-color 0.3s ease-in-out; + border-bottom: 1px solid #E76969; + justify-content: space-between; + flex-direction: column; + display: flex; + height: auto; + width: 100%; +} + +.rolldown:nth-of-type( 1 ) { margin-top: -5px; } +.rolldown:nth-last-of-type( 1 ) { border-bottom: none; } +.rolldown:hover { cursor: pointer; } + +.rolldown-collapsed-container { + overflow: hidden; + padding: 10px; + display: flex; + height: auto; + width: 100%; +} + +.rolldown-collapsed { + float: left; + padding: 0; +} + +.rolldown-expanded-container { + text-align: center; + overflow: hidden; + transition: max-height 0.3s linear; + max-height: 0px; + margin: 0; + padding: 0; +} + +.rolldown-expanded-container.active { + display: flex !important; + max-height: 200px; + height: auto; +} + +.rolldown-expanded { + margin: 20px; +} + +.rolldown-expanded a { color: white; } + +.rolldown-icon-container { + margin-right: 15px; + position: relative; + float: left; + height: fit-content; +} + +.rolldown.active .rolldown-icon-container { + transform: rotate( 90deg ); +} + +.popup { + border: 1px solid var( --front ); + background-color: var( --back ); + box-shadow: 1px 1px 2px black; + justify-content: center; + align-items: center; + align-self: center; + flex-direction: column; + position: absolute; + max-height: 888px; + max-width: 600px; + min-width: 300px; + display: flex; + padding: 20px; + z-index: 5; + width: 85%; + top: 50%; + left: 50%; + transform: translate( -50%, -50% ); +} + +.popup-msg { + border: 1px solid var( --front ); + background-color: var( --back ); + box-shadow: 1px 1px 2px black; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1000; + padding: 10px; + display: flex; + flex-direction: column; +} + +.column { + display: flex; + flex-direction: column; +} + +#background-toggle { + position: absolute; + + bottom: 0px; + right: 0px; + background: #888; + border-left: 1px solid #ccc; + border-top: 1px solid #fff; + border-right: 1px solid #888; + border-bottom: 1px solid #222; +} + +#package-entries { + display: flex; + flex-direction: column; + width: 100%; + justify-content: center; + align-items: center; +} + +#package-entries table { + text-align: right; + font-size: 17px; +} + +#package-entries table tr td:first-child { + text-align: left !important; +} + +.package-entry { + display: flex; + width: 80%; + + justify-content: space-between; +} diff --git a/public/static/networkheaven.jpg b/public/static/networkheaven.jpg Binary files differnew file mode 100644 index 0000000..e6f93db --- /dev/null +++ b/public/static/networkheaven.jpg diff --git a/public/static/networkheaven.png b/public/static/networkheaven.png Binary files differnew file mode 100644 index 0000000..97c2cf5 --- /dev/null +++ b/public/static/networkheaven.png diff --git a/public/static/nh.jpg b/public/static/nh.jpg Binary files differnew file mode 100644 index 0000000..f8d65bb --- /dev/null +++ b/public/static/nh.jpg diff --git a/public/static/nh.png b/public/static/nh.png Binary files differnew file mode 100644 index 0000000..fa8d531 --- /dev/null +++ b/public/static/nh.png diff --git a/public/tsconfig.json b/public/tsconfig.json new file mode 100644 index 0000000..8f78ddc --- /dev/null +++ b/public/tsconfig.json @@ -0,0 +1,117 @@ +{ + "compilerOptions": { + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + "moduleResolution": "bundler", + "target": "es2020", + "lib": [ + "ES2017", + "DOM", + "DOM.Iterable", + "ScriptHost" + ], + // "lib": [], + "jsx": "react", + // "experimentalDecorators": true, + // "emitDecoratorMetadata": true, + "jsxFactory": "JSX.createElement", + "jsxFragmentFactory": "JSX.createFragment", + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "es2020", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "baseUrl": ".", + "paths": { + "*": ["types/*"] + }, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + "typeRoots": [ + "./node_modules/@types", + "./types" + ], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + //"checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": false, /* When type checking, take into account 'null' and 'undefined'. */ + "strictFunctionTypes": false, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + "strictBindCallApply": false, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + "strictPropertyInitialization": false, /* Check for class properties that are declared but not set in the constructor. */ + "strictBuiltinIteratorReturn": false, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + "noImplicitThis": false, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/public/types/custom.d.ts b/public/types/custom.d.ts new file mode 100644 index 0000000..b7f740e --- /dev/null +++ b/public/types/custom.d.ts @@ -0,0 +1,8 @@ +declare namespace JSX { + type Element = any; + type ElementClass = any; + interface IntrinsicElements { + [elemName: string]: any; + } +} + diff --git a/public/webpack-dev.config.cjs b/public/webpack-dev.config.cjs new file mode 100644 index 0000000..6cffec7 --- /dev/null +++ b/public/webpack-dev.config.cjs @@ -0,0 +1,46 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = { + mode: 'development', + entry: './src/index-page.tsx', + module: { + rules: [ + { + test: /\.tsx?$/, + use: { + loader: 'ts-loader', + options: { + compilerOptions: { + module: 'es2020' + } + } + }, + exclude: /node_modules/, + } + ], + }, + resolve: { + extensions: ['.tsx', '.jsx', ".js"], + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist'), + publicPath: '/' + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './src/index.html', + }), + new CopyWebpackPlugin({ + patterns: [ + { from: './static/**' } + ] + }) + ], + devServer: { + historyApiFallback: true, + port: 9000, + }, +}; diff --git a/public/webpack-prod.config.cjs b/public/webpack-prod.config.cjs new file mode 100644 index 0000000..1a67053 --- /dev/null +++ b/public/webpack-prod.config.cjs @@ -0,0 +1,49 @@ +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +module.exports = { + mode: 'production', + entry: './src/index-page.tsx', + module: { + rules: [ + { + test: /\.tsx?$/, + use: { + loader: 'ts-loader', + options: { + compilerOptions: { + module: 'es2020' + } + } + }, + exclude: /node_modules/, + } + ], + }, + resolve: { + alias: { + jquery: "jquery/slim" + }, + extensions: ['.tsx', '.jsx', ".js"], + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist'), + publicPath: '/' + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './src/index.html', + }), + new CopyWebpackPlugin({ + patterns: [ + { from: './static/**' } + ] + }) + ], + devServer: { + historyApiFallback: true, + port: 9000, + }, +}; |
