check eslint and typescript

Resolves #99.
This commit is contained in:
alex
2021-08-28 00:10:16 +01:00
parent 706996d71a
commit 7d5d872a07
24 changed files with 4776 additions and 3497 deletions
+3
View File
@@ -7,3 +7,6 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = true
[*.{yml,yaml}]
indent_size = 2
+19
View File
@@ -0,0 +1,19 @@
name: reviewdog
on: pull_request
jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: cd frontend && yarn
- uses: reviewdog/action-eslint@v1
with:
reporter: github-pr-check
workdir: frontend
eslint_flags: src --ext .js,.jsx,.ts,.tsx
typescript:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reviewdog/action-setup@v1
- run: cd frontend && yarn && yarn run tsc | reviewdog -f tsc -reporter github-pr-check
+5
View File
@@ -0,0 +1,5 @@
{
"eslint.workingDirectories": [
"frontend"
]
}
+25
View File
@@ -0,0 +1,25 @@
module.exports = {
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"extends": [
"eslint:recommended",
"preact",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"semi": ["error", "never", { "beforeStatementContinuationChars": "always" }],
"indent": ["error", 4],
"quotes": ["error", "double"],
"quote-props": ["error", "consistent"],
"brace-style": "error",
"object-curly-spacing": ["error", "always"],
"array-bracket-spacing": ["error", "never"],
"no-else-return": "off",
"no-trailing-spaces": "error",
"@typescript-eslint/explicit-module-boundary-types": "off",
"react/no-danger": "off"
}
}
+8 -2
View File
@@ -2,7 +2,8 @@
"license": "MIT",
"scripts": {
"start": "snowpack dev --polyfill-node",
"build": "snowpack build --polyfill-node"
"build": "snowpack build --polyfill-node",
"lint": "eslint src --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"@monaco-editor/react": "^4.2.2",
@@ -23,11 +24,16 @@
"@prefresh/snowpack": "^3.0.0",
"@snowpack/plugin-postcss": "^1.4.3",
"@types/react-router-dom": "^5.1.8",
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"autoprefixer": "^10.3.1",
"cssnano": "^5.0.7",
"dotenv": "^10.0.0",
"eslint": "^7.32.0",
"eslint-config-preact": "^1.1.4",
"postcss": "^8.3.6",
"postcss-scrollbar": "^0.3.0",
"snowpack": "^3.7.1"
"snowpack": "^3.7.1",
"typescript": "3.4.5"
}
}
+3 -3
View File
@@ -44,9 +44,9 @@ export default function App() {
reverseOrder={true}
toastOptions={{
style: {
borderRadius: '100px',
background: '#333',
color: '#fff',
borderRadius: "100px",
background: "#333",
color: "#fff",
},
}}
/>
+3 -3
View File
@@ -3,17 +3,17 @@ import { MarkGithubIcon, ChevronRightIcon } from "@primer/octicons-react"
export default function Unimplemented({ issue }: { issue: string }) {
return <div style={{ color: "#ffffff88" }}>
<p style={{ paddingTop: '0.5em', paddingBottom: '0.25em' }}>
<p style={{ paddingTop: "0.5em", paddingBottom: "0.25em" }}>
There's meant to be more here, but it's not implemented yet.
</p>
<span style={{ padding: '0.5em', paddingLeft: '0' }}>
<span style={{ padding: "0.5em", paddingLeft: "0" }}>
Think you could help?
</span>
{issue ? <a class="button" href={`https://github.com/ethteck/decomp.me/issues/${issue}`}>
<MarkGithubIcon /> See the GitHub issue <ChevronRightIcon />
</a> : <a class="button" href="https://github.com/ethteck/decomp.me">
<MarkGithubIcon /> Contribute to decomp.me on GitHub
<MarkGithubIcon /> Contribute to decomp.me on GitHub
</a>}
</div>
}
+12 -10
View File
@@ -1,5 +1,7 @@
const { API_BASE } = import.meta.env
type Json = Record<string, unknown>
const commonOpts: RequestInit = {
credentials: "include",
cache: "reload",
@@ -8,12 +10,12 @@ const commonOpts: RequestInit = {
// Read the Django CSRF token, from https://docs.djangoproject.com/en/3.2/ref/csrf/#ajax
export const csrftoken = (function (name) {
let cookieValue = null
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';')
if (document.cookie && document.cookie !== "") {
const cookies = document.cookie.split(";")
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim()
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
if (cookie.substring(0, name.length + 1) === (`${name }=`)) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1))
break
}
@@ -49,7 +51,7 @@ export async function get(url: string, cache = false) {
return await response.json()
}
export async function post(url: string, json: object) {
export async function post(url: string, json: Json) {
const body: string = JSON.stringify(json)
console.info("POST", url, JSON.parse(body))
@@ -59,8 +61,8 @@ export async function post(url: string, json: object) {
method: "POST",
body,
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
"Content-Type": "application/json",
"X-CSRFToken": csrftoken,
},
})
@@ -71,7 +73,7 @@ export async function post(url: string, json: object) {
return await response.json()
}
export async function patch(url: string, json: object) {
export async function patch(url: string, json: Json) {
const body = JSON.stringify(json)
console.info("PATCH", url, JSON.parse(body))
@@ -81,8 +83,8 @@ export async function patch(url: string, json: object) {
method: "PATCH",
body,
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
"Content-Type": "application/json",
"X-CSRFToken": csrftoken,
},
})
@@ -90,7 +92,7 @@ export async function patch(url: string, json: object) {
throw new ResponseError(response, await response.json())
}
let text = await response.text()
const text = await response.text()
if (!text) {
return
}
+1 -1
View File
@@ -17,7 +17,7 @@ export default function CompilerButton({ value, onChange, disabled }) {
onOutsideClick: close,
overflowContainer: false,
auto: true,
placement: "bottom-end",
placement: "bottom-end",
triggerOffset: 14,
})
+7 -5
View File
@@ -1,5 +1,6 @@
import { h, createContext } from "preact"
import { useState, useContext, useEffect } from "preact/hooks"
import Skeleton from "react-loading-skeleton"
import Select from "../Select"
@@ -11,7 +12,7 @@ const OptsContext = createContext()
export function Checkbox({ flag, description }) {
const { checkFlag, setFlag } = useContext(OptsContext)
const isChecked = checkFlag(flag)
return <div class={styles.flag} onClick={() => setFlag(flag, !isChecked)}>
@@ -57,7 +58,7 @@ export default function CompilerOpts({ value, onChange, title, isPopup }) {
useEffect(() => {
onChange({
compiler: compiler,
compiler,
cc_opts: opts,
})
}, [compiler, opts])
@@ -66,16 +67,16 @@ export default function CompilerOpts({ value, onChange, title, isPopup }) {
checkFlag(flag) {
return opts.split(" ").includes(flag)
},
setFlag(flag, enable) {
let split = opts.split(" ")
if (enable) {
split.push(flag)
} else {
split = split.filter(f => f !== flag)
}
opts = split.join(" ").trim()
setOpts(opts)
},
@@ -97,6 +98,7 @@ function OptsEditor({ compiler, setCompiler, opts, setOpts }) {
<div class={styles.row}>
<Select class={styles.compilerSelect} onChange={e => setCompiler(e.target.value)}>
{Object.values(compilers).map(c => <option
key={c.id}
value={c.id}
selected={c.name === compilerComp.name}
>
+2 -2
View File
@@ -28,14 +28,14 @@ export default function PresetSelect({ compiler, opts, setCompiler, setOpts }) {
return
}
const preset = presets[parseInt(e.target.value)]
const preset = presets[parseInt(e.target.value, 10)]
setOpts(preset.opts)
setCompiler(preset.compiler)
}}>
{!selectedPreset && <option value="custom" selected>Custom</option>}
{presets.map((preset, idx) =>
<option value={idx} selected={preset === selectedPreset}>
<option key={idx} value={idx} selected={preset === selectedPreset}>
{preset.name}
</option>
)}
+2 -2
View File
@@ -1,7 +1,7 @@
import { useState, useRef, useLayoutEffect, StateUpdater } from "preact/hooks"
import useResizeObserver from "@react-hook/resize-observer"
export function useLocalStorage<S>(key: string, initialValue: object): [S, StateUpdater<S>] {
export function useLocalStorage<S>(key: string, initialValue: S): [S, StateUpdater<S>] {
const [storedValue, setStoredValue] = useState(() => {
const item = localStorage.getItem(key)
return item ? JSON.parse(item) : initialValue
@@ -19,7 +19,7 @@ export function useLocalStorage<S>(key: string, initialValue: object): [S, State
export function useSize<T extends HTMLElement>() {
const ref = useRef<T>()
const [size, setSize] = useState({ width: 0, height: 0 })
useLayoutEffect(() => {
setSize(ref.current.getBoundingClientRect())
}, [ref])
+11 -11
View File
@@ -1,5 +1,5 @@
import { h, Fragment } from "preact"
import { useEffect, useState, useRef } from "preact/hooks"
import { useEffect, useState } from "preact/hooks"
import Skeleton from "react-loading-skeleton"
import MonacoEditor, { useMonaco } from "@monaco-editor/react"
import type { editor } from "monaco-editor"
@@ -29,10 +29,10 @@ export default function Editor({ forceLoading, value, valueVersion, onChange, pa
console.info("Updating editor value because valueVersion changed")
model.setValue(value)
}
}, [valueVersion, model])
}, [valueVersion, model]) // eslint-disable-line react-hooks/exhaustive-deps
return <>
<div style={{ display: (isLoading || forceLoading) ? 'none' : 'block' }} class={styles.monacoContainer}>
<div style={{ display: (isLoading || forceLoading) ? "none" : "block" }} class={styles.monacoContainer}>
<MonacoEditor
language="custom_c"
theme="custom"
@@ -48,7 +48,7 @@ export default function Editor({ forceLoading, value, valueVersion, onChange, pa
padding: padding ? { top: 30, bottom: 30 } : {},
fontSize: 13,
}}
onMount={(editor, monaco) => {
onMount={editor => {
setModel(editor.getModel())
}}
onChange={(newValue: string) => {
@@ -60,13 +60,13 @@ export default function Editor({ forceLoading, value, valueVersion, onChange, pa
</div>
<div style={{
display: (isLoading || forceLoading) ? 'block' : 'none',
paddingTop: padding ? '2em' : '0',
paddingBottom: padding ? '2em' : '0',
paddingLeft: '2em',
paddingRight: '2em',
background: '#14161a',
height: '100%',
display: (isLoading || forceLoading) ? "block" : "none",
paddingTop: padding ? "2em" : "0",
paddingBottom: padding ? "2em" : "0",
paddingLeft: "2em",
paddingRight: "2em",
background: "#14161a",
height: "100%",
}}>
<Skeleton count={6} height={22} />
</div>
+2 -2
View File
@@ -29,7 +29,7 @@ export default function NewScratch() {
console.warn("create scratch action already in progress")
return
}
try {
setAwaitingResponse(true)
const { slug } = await api.post("/scratch", {
@@ -63,7 +63,7 @@ export default function NewScratch() {
<div class={styles.targetasm}>
<Editor language="asm" value={asm} onChange={setAsm} />
</div>
<p class={styles.description}>
Include any C context (structs, definitions, etc) below:
</p>
+38 -33
View File
@@ -87,9 +87,9 @@ export default function Scratch() {
}).catch(error => Promise.reject(error.message))
await toast.promise(promise, {
loading: 'Saving...',
success: 'Scratch saved!',
error: 'Error saving scratch',
loading: "Saving...",
success: "Scratch saved!",
error: "Error saving scratch",
})
setSavedCompiler(compiler)
@@ -106,29 +106,31 @@ export default function Scratch() {
history.push(`/scratch/${newScratch.slug}`)
toast.success("Fork created!", {
icon: '🍴',
icon: "🍴",
})
}
useEffect(async () => {
const { scratch, is_yours } = await api.get(`/scratch/${slug}`)
useEffect(() => {
(async () => {
const { scratch, is_yours } = await api.get(`/scratch/${slug}`)
setIsYours(is_yours)
setCompiler({
compiler: scratch.compiler,
cc_opts: scratch.cc_opts,
})
setCContext(scratch.context)
setCCode(scratch.source_code)
setIsYours(is_yours)
setCompiler({
compiler: scratch.compiler,
cc_opts: scratch.cc_opts,
})
setCContext(scratch.context)
setCCode(scratch.source_code)
setSavedCompiler({
compiler: scratch.compiler,
cc_opts: scratch.cc_opts,
})
setSavedCCode(scratch.source_code)
setSavedCContext(scratch.context)
setSavedCompiler({
compiler: scratch.compiler,
cc_opts: scratch.cc_opts,
})
setSavedCCode(scratch.source_code)
setSavedCContext(scratch.context)
setLoadDate(Date.now())
setLoadDate(Date.now())
})()
}, [slug])
const debouncedCompile = useDebouncedCallback(compile, 500, { leading: false, trailing: true })
@@ -162,7 +164,10 @@ export default function Scratch() {
}
}
useEffect(debouncedCompile, compiler ? [compiler.compiler, compiler.cc_opts] : [])
useEffect(
debouncedCompile,
[debouncedCompile, compiler && compiler.compiler, compiler && compiler.cc_opts],
)
return <>
<Nav />
@@ -173,7 +178,7 @@ export default function Scratch() {
<resizer.Section minSize="4em" className={styles.sourceCode}>
<div class={styles.sectionHeader}>
Source
<span class={styles.grow}></span>
<span class={styles.grow} />
<button class={isCompiling ? styles.compiling : ""} onClick={compile} disabled={!isCompilerChosen}>
<SyncIcon size={16} /> Compile
</button>
@@ -185,7 +190,7 @@ export default function Scratch() {
<RepoForkedIcon size={16} /> Fork
</button>
<CompilerButton disabled={!isCompilerChosen} value={compiler} onChange={setCompiler} />
<CompilerButton disabled={!isCompilerChosen} value={compiler} onChange={c => setCompiler(c)} />
</div>
<Editor
@@ -201,7 +206,7 @@ export default function Scratch() {
</resizer.Section>
<resizer.Bar
style={{ cursor: 'row-resize' }}
style={{ cursor: "row-resize" }}
onClick={toggleContextSection}
>
<div class={styles.sectionHeader}>
@@ -227,8 +232,8 @@ export default function Scratch() {
<resizer.Bar
size={1}
style={{
cursor: 'col-resize',
background: '#2e3032',
cursor: "col-resize",
background: "#2e3032",
}}
expandInteractiveArea={{ left: 4, right: 4 }}
/>
@@ -242,18 +247,18 @@ export default function Scratch() {
</span>}
<span class={styles.grow} />
<input type="checkbox" checked={showWarnings} onChange={() => setShowWarnings(!showWarnings)} name="showWarnings" />
<label for="showWarnings" onClick={() => setShowWarnings(!showWarnings)}>Show warnings</label>
</>}
</div>
<div class={styles.output}>
{(!isCompilerChosen) ?
{(!isCompilerChosen) ? <>
<ChooseACompiler onCommit={setCompiler} />
: (diff === null && log === null)
?
</> : (diff === null && log === null)
? <>
<Skeleton height={20} count={20} />
: <>
</> : <>
{(showWarnings || !diff) && <code class={styles.log}>{log}</code>}
<code class={styles.diff} dangerouslySetInnerHTML={{ __html: diff }} />
</>
@@ -269,9 +274,9 @@ function ChooseACompiler({ onCommit }) {
const [compiler, setCompiler] = useLocalStorage("ChooseACompiler.recent")
return <div>
<CompilerOpts title="Choose a compiler" value={compiler} onChange={setCompiler} />
<CompilerOpts title="Choose a compiler" value={compiler} onChange={c => setCompiler(c)} />
<div style={{ padding: '1em', float: 'right' }}>
<div style={{ padding: "1em", float: "right" }}>
<button onClick={() => onCommit(compiler)}>
Use this compiler
<ArrowRightIcon size={16} />
+447
View File
@@ -0,0 +1,447 @@
export const conf = {
comments: {
lineComment: "//",
blockComment: ["/*", "*/"]
},
brackets: [
["{", "}"],
["[", "]"],
["(", ")"],
],
autoClosingPairs: [
{ open: "[", close: "]" },
{ open: "{", close: "}" },
{ open: "(", close: ")" },
{ open: "'", close: "'", notIn: ["string", "comment"] },
{ open: "\"", close: "\"", notIn: ["string"] }
],
surroundingPairs: [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: "\"", close: "\"" },
{ open: "'", close: "'" }
],
folding: {
markers: {
start: new RegExp("^\\s*#pragma\\s+region\\b"),
end: new RegExp("^\\s*#pragma\\s+endregion\\b")
}
}
}
export const language = {
defaultToken: "",
tokenPostfix: ".c",
brackets: [
{ token: "delimiter.curly", open: "{", close: "}" },
{ token: "delimiter.parenthesis", open: "(", close: ")" },
{ token: "delimiter.square", open: "[", close: "]" },
{ token: "delimiter.angle", open: "<", close: ">" }
],
keywords: [
"abstract",
"amp",
"array",
"auto",
"break",
"case",
"catch",
"class",
"const",
"constexpr",
"const_cast",
"continue",
"cpu",
"decltype",
"default",
"delegate",
"delete",
"do",
"double",
"dynamic_cast",
"each",
"else",
"enum",
"event",
"explicit",
"export",
"extern",
"false",
"final",
"finally",
"for",
"friend",
"gcnew",
"generic",
"goto",
"if",
"in",
"initonly",
"inline",
"interface",
"interior_ptr",
"internal",
"literal",
"long",
"mutable",
"namespace",
"new",
"noexcept",
"nullptr",
"__nullptr",
"operator",
"override",
"partial",
"pascal",
"pin_ptr",
"private",
"property",
"protected",
"public",
"ref",
"register",
"reinterpret_cast",
"restrict",
"return",
"safe_cast",
"sealed",
"short",
"signed",
"sizeof",
"static",
"static_assert",
"static_cast",
"struct",
"switch",
"template",
"this",
"thread_local",
"throw",
"tile_static",
"true",
"try",
"typedef",
"typeid",
"typename",
"union",
"using",
"virtual",
"volatile",
"wchar_t",
"where",
"while",
"_asm", // reserved word with one underscores
"_based",
"_cdecl",
"_declspec",
"_fastcall",
"_if_exists",
"_if_not_exists",
"_inline",
"_multiple_inheritance",
"_pascal",
"_single_inheritance",
"_stdcall",
"_virtual_inheritance",
"_w64",
"__abstract", // reserved word with two underscores
"__alignof",
"__asm",
"__assume",
"__based",
"__box",
"__builtin_alignof",
"__cdecl",
"__clrcall",
"__declspec",
"__delegate",
"__event",
"__except",
"__fastcall",
"__finally",
"__forceinline",
"__gc",
"__hook",
"__identifier",
"__if_exists",
"__if_not_exists",
"__inline",
"__int128",
"__int16",
"__int32",
"__int64",
"__int8",
"__interface",
"__leave",
"__m128",
"__m128d",
"__m128i",
"__m256",
"__m256d",
"__m256i",
"__m64",
"__multiple_inheritance",
"__newslot",
"__nogc",
"__noop",
"__nounwind",
"__novtordisp",
"__pascal",
"__pin",
"__pragma",
"__property",
"__ptr32",
"__ptr64",
"__raise",
"__restrict",
"__resume",
"__sealed",
"__single_inheritance",
"__stdcall",
"__super",
"__thiscall",
"__try",
"__try_cast",
"__typeof",
"__unaligned",
"__unhook",
"__uuidof",
"__value",
"__virtual_inheritance",
"__w64",
"__wchar_t",
],
types: [
"void",
"s64",
"s32",
"s16",
"s8",
"u64",
"u32",
"u16",
"u8",
"f64",
"f32",
"bool",
"char",
"int",
"float",
"long",
"unsigned",
],
operators: [
"=",
"!",
"~",
"?",
":",
"&&",
"||",
"++",
"--",
"+",
"-",
"*",
"/",
"&",
"|",
"^",
"%",
"<<",
">>",
">>>",
"+=",
"-=",
"*=",
"/=",
"&=",
"|=",
"^=",
"%=",
"<<=",
">>=",
">>>=",
"...",
],
comparisonOperators: [
">",
"<",
"==",
"<=",
">=",
"!=",
],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*/^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
integersuffix: /(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,
floatsuffix: /[fFlL]?/,
encoding: /u|u8|U|L/,
// The main tokenizer for our languages
tokenizer: {
root: [
// Macro
[/[A-Z][A-Z0-9_]*(?=\b)/, { token: "macro" }],
// PascalCase for types
[/[A-Z]\w*/, { token: "storage.type" }],
// function call
[/[a-zA-Z_]\w*(?=\()/, { token: "function" }],
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
"@keywords": { token: "keyword.$0" },
"@types": { token: "storage.type.$0" },
"@default": "identifier"
}
}
],
// The preprocessor checks must be before whitespace as they check /^\s*#/ which
// otherwise fails to match later after other whitespace has been removed.
// Inclusion
[/^\s*#\s*include/, { token: "keyword.directive.include", next: "@include" }],
// Preprocessor directive
[/^\s*#\s*\w+/, "keyword.directive"],
// whitespace
{ include: "@whitespace" },
// [[ attributes ]].
[/\[\s*\[/, { token: "annotation", next: "@annotation" }],
// delimiters and operators
[/[{}()[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[
/@symbols/,
{
cases: {
"@comparisonOperators": { token: "operator.comparison" },
"@operators": { token: "operator" },
"@default": { token: "delimiter" }
}
}
],
// numbers
[/\d*\d+[eE]([-+]?\d+)?(@floatsuffix)/, "number.float"],
[/\d*\.\d+([eE][-+]?\d+)?(@floatsuffix)/, "number.float"],
[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, "number.hex"],
[/0[0-7']*[0-7](@integersuffix)/, "number.octal"],
[/0[bB][0-1']*[0-1](@integersuffix)/, "number.binary"],
[/\d[\d']*\d(@integersuffix)/, "number"],
[/\d(@integersuffix)/, "number"],
// delimiter: after number because of .\d floats
[/[;,.]/, "delimiter"],
// strings
[/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string
[/"/, "string", "@string"],
// characters
[/'[^\\']'/, "string"],
[/(')(@escapes)(')/, ["string", "string.escape", "string"]],
[/'/, "string.invalid"]
],
whitespace: [
[/[ \t\r\n]+/, ""],
[/\/\*\*(?!\/)/, "comment.doc", "@doccomment"],
[/\/\*/, "comment", "@comment"],
[/\/\/.*\\$/, "comment", "@linecomment"],
[/\/\/.*$/, "comment"]
],
comment: [
[/[^/*]+/, "comment"],
[/\*\//, "comment", "@pop"],
[/[/*]/, "comment"]
],
//For use with continuous line comments
linecomment: [
[/.*[^\\]$/, "comment", "@pop"],
[/[^]+/, "comment"]
],
//Identical copy of comment above, except for the addition of .doc
doccomment: [
[/[^/*]+/, "comment.doc"],
[/\*\//, "comment.doc", "@pop"],
[/[/*]/, "comment.doc"]
],
string: [
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, "string", "@pop"]
],
raw: [
[
/(.*)(\))(?:([^ ()\\\t"]*))(")/,
{
cases: {
"$3==$S2": [
"string.raw",
"string.raw.end",
"string.raw.end",
{ token: "string.raw.end", next: "@pop" }
],
"@default": ["string.raw", "string.raw", "string.raw", "string.raw"]
}
}
],
[/.*/, "string.raw"]
],
annotation: [
{ include: "@whitespace" },
[/using|alignas/, "keyword"],
[/[a-zA-Z0-9_]+/, "annotation"],
[/[,:]/, "delimiter"],
[/[()]/, "@brackets"],
[/\]\s*\]/, { token: "annotation", next: "@pop" }]
],
include: [
[
/(\s*)(<)([^<>]*)(>)/,
[
"",
"keyword.directive.include.begin",
"string.include.identifier",
{ token: "keyword.directive.include.end", next: "@pop" }
]
],
[
/(\s*)(")([^"]*)(")/,
[
"",
"keyword.directive.include.begin",
"string.include.identifier",
{ token: "keyword.directive.include.end", next: "@pop" }
]
]
]
}
}
-449
View File
@@ -1,449 +0,0 @@
import type { languages } from "monaco-editor"
export const conf = {
comments: {
lineComment: '//',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')'],
],
autoClosingPairs: [
{ open: '[', close: ']' },
{ open: '{', close: '}' },
{ open: '(', close: ')' },
{ open: "'", close: "'", notIn: ['string', 'comment'] },
{ open: '"', close: '"', notIn: ['string'] }
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"' },
{ open: "'", close: "'" }
],
folding: {
markers: {
start: new RegExp('^\\s*#pragma\\s+region\\b'),
end: new RegExp('^\\s*#pragma\\s+endregion\\b')
}
}
};
export const language: languages.IMonarchLanguage = {
defaultToken: '',
tokenPostfix: '.c',
brackets: [
{ token: 'delimiter.curly', open: '{', close: '}' },
{ token: 'delimiter.parenthesis', open: '(', close: ')' },
{ token: 'delimiter.square', open: '[', close: ']' },
{ token: 'delimiter.angle', open: '<', close: '>' }
],
keywords: [
'abstract',
'amp',
'array',
'auto',
'break',
'case',
'catch',
'class',
'const',
'constexpr',
'const_cast',
'continue',
'cpu',
'decltype',
'default',
'delegate',
'delete',
'do',
'double',
'dynamic_cast',
'each',
'else',
'enum',
'event',
'explicit',
'export',
'extern',
'false',
'final',
'finally',
'for',
'friend',
'gcnew',
'generic',
'goto',
'if',
'in',
'initonly',
'inline',
'interface',
'interior_ptr',
'internal',
'literal',
'long',
'mutable',
'namespace',
'new',
'noexcept',
'nullptr',
'__nullptr',
'operator',
'override',
'partial',
'pascal',
'pin_ptr',
'private',
'property',
'protected',
'public',
'ref',
'register',
'reinterpret_cast',
'restrict',
'return',
'safe_cast',
'sealed',
'short',
'signed',
'sizeof',
'static',
'static_assert',
'static_cast',
'struct',
'switch',
'template',
'this',
'thread_local',
'throw',
'tile_static',
'true',
'try',
'typedef',
'typeid',
'typename',
'union',
'using',
'virtual',
'volatile',
'wchar_t',
'where',
'while',
'_asm', // reserved word with one underscores
'_based',
'_cdecl',
'_declspec',
'_fastcall',
'_if_exists',
'_if_not_exists',
'_inline',
'_multiple_inheritance',
'_pascal',
'_single_inheritance',
'_stdcall',
'_virtual_inheritance',
'_w64',
'__abstract', // reserved word with two underscores
'__alignof',
'__asm',
'__assume',
'__based',
'__box',
'__builtin_alignof',
'__cdecl',
'__clrcall',
'__declspec',
'__delegate',
'__event',
'__except',
'__fastcall',
'__finally',
'__forceinline',
'__gc',
'__hook',
'__identifier',
'__if_exists',
'__if_not_exists',
'__inline',
'__int128',
'__int16',
'__int32',
'__int64',
'__int8',
'__interface',
'__leave',
'__m128',
'__m128d',
'__m128i',
'__m256',
'__m256d',
'__m256i',
'__m64',
'__multiple_inheritance',
'__newslot',
'__nogc',
'__noop',
'__nounwind',
'__novtordisp',
'__pascal',
'__pin',
'__pragma',
'__property',
'__ptr32',
'__ptr64',
'__raise',
'__restrict',
'__resume',
'__sealed',
'__single_inheritance',
'__stdcall',
'__super',
'__thiscall',
'__try',
'__try_cast',
'__typeof',
'__unaligned',
'__unhook',
'__uuidof',
'__value',
'__virtual_inheritance',
'__w64',
'__wchar_t',
],
types: [
'void',
's64',
's32',
's16',
's8',
'u64',
'u32',
'u16',
'u8',
'f64',
'f32',
'bool',
'char',
'int',
'float',
'long',
'unsigned',
],
operators: [
'=',
'!',
'~',
'?',
':',
'&&',
'||',
'++',
'--',
'+',
'-',
'*',
'/',
'&',
'|',
'^',
'%',
'<<',
'>>',
'>>>',
'+=',
'-=',
'*=',
'/=',
'&=',
'|=',
'^=',
'%=',
'<<=',
'>>=',
'>>>=',
'...',
],
comparisonOperators: [
'>',
'<',
'==',
'<=',
'>=',
'!=',
],
// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
integersuffix: /(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,
floatsuffix: /[fFlL]?/,
encoding: /u|u8|U|L/,
// The main tokenizer for our languages
tokenizer: {
root: [
// Macro
[/[A-Z][A-Z0-9_]*(?=\b)/, { token: 'macro' }],
// PascalCase for types
[/[A-Z]\w*/, { token: 'storage.type' }],
// function call
[/[a-zA-Z_]\w*(?=\()/, { token: 'function' }],
// identifiers and keywords
[
/[a-zA-Z_]\w*/,
{
cases: {
'@keywords': { token: 'keyword.$0' },
'@types': { token: 'storage.type.$0' },
'@default': 'identifier'
}
}
],
// The preprocessor checks must be before whitespace as they check /^\s*#/ which
// otherwise fails to match later after other whitespace has been removed.
// Inclusion
[/^\s*#\s*include/, { token: 'keyword.directive.include', next: '@include' }],
// Preprocessor directive
[/^\s*#\s*\w+/, 'keyword.directive'],
// whitespace
{ include: '@whitespace' },
// [[ attributes ]].
[/\[\s*\[/, { token: 'annotation', next: '@annotation' }],
// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@comparisonOperators': { token: 'operator.comparison' },
'@operators': { token: 'operator' },
'@default': { token: 'delimiter' }
}
}
],
// numbers
[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/\d*\.\d+([eE][\-+]?\d+)?(@floatsuffix)/, 'number.float'],
[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/, 'number.hex'],
[/0[0-7']*[0-7](@integersuffix)/, 'number.octal'],
[/0[bB][0-1']*[0-1](@integersuffix)/, 'number.binary'],
[/\d[\d']*\d(@integersuffix)/, 'number'],
[/\d(@integersuffix)/, 'number'],
// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],
// strings
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
[/"/, 'string', '@string'],
// characters
[/'[^\\']'/, 'string'],
[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
[/'/, 'string.invalid']
],
whitespace: [
[/[ \t\r\n]+/, ''],
[/\/\*\*(?!\/)/, 'comment.doc', '@doccomment'],
[/\/\*/, 'comment', '@comment'],
[/\/\/.*\\$/, 'comment', '@linecomment'],
[/\/\/.*$/, 'comment']
],
comment: [
[/[^\/*]+/, 'comment'],
[/\*\//, 'comment', '@pop'],
[/[\/*]/, 'comment']
],
//For use with continuous line comments
linecomment: [
[/.*[^\\]$/, 'comment', '@pop'],
[/[^]+/, 'comment']
],
//Identical copy of comment above, except for the addition of .doc
doccomment: [
[/[^\/*]+/, 'comment.doc'],
[/\*\//, 'comment.doc', '@pop'],
[/[\/*]/, 'comment.doc']
],
string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, 'string', '@pop']
],
raw: [
[
/(.*)(\))(?:([^ ()\\\t"]*))(\")/,
{
cases: {
'$3==$S2': [
'string.raw',
'string.raw.end',
'string.raw.end',
{ token: 'string.raw.end', next: '@pop' }
],
'@default': ['string.raw', 'string.raw', 'string.raw', 'string.raw']
}
}
],
[/.*/, 'string.raw']
],
annotation: [
{ include: '@whitespace' },
[/using|alignas/, 'keyword'],
[/[a-zA-Z0-9_]+/, 'annotation'],
[/[,:]/, 'delimiter'],
[/[()]/, '@brackets'],
[/\]\s*\]/, { token: 'annotation', next: '@pop' }]
],
include: [
[
/(\s*)(<)([^<>]*)(>)/,
[
'',
'keyword.directive.include.begin',
'string.include.identifier',
{ token: 'keyword.directive.include.end', next: '@pop' }
]
],
[
/(\s*)(")([^"]*)(")/,
[
'',
'keyword.directive.include.begin',
'string.include.identifier',
{ token: 'keyword.directive.include.end', next: '@pop' }
]
]
]
}
};
+2 -2
View File
@@ -1,11 +1,11 @@
import { h, Fragment } from "preact"
import { h } from "preact"
import { MarkGithubIcon } from "@primer/octicons-react"
const { GITHUB_CLIENT_ID } = import.meta.env
// https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps
const SCOPES = ["public_repo"]
const LOGIN_URL = `https://github.com/login/oauth/authorize?client_id=${GITHUB_CLIENT_ID}&scope=${SCOPES.join('%20')}`
const LOGIN_URL = `https://github.com/login/oauth/authorize?client_id=${GITHUB_CLIENT_ID}&scope=${SCOPES.join("%20")}`
export default function GitHubLoginButton() {
if (GITHUB_CLIENT_ID) {
+2 -2
View File
@@ -29,13 +29,13 @@ export default function LoginPage() {
setError(error)
})
}
}, [code])
}, [code, history, mutate, next])
return <>
<main class={styles.container}>
{error ? <div class={styles.card}>
<p class={styles.error}>
Sign-in error.<br/>
Sign-in error.<br />
{error.message}
</p>
<p>
+1 -1
View File
@@ -23,7 +23,7 @@ export default function LoginState({ onChange }: Props) {
return <div>{error}</div>
} else if (!data?.user) {
// Loading...
return <div></div>
return <div />
} else if (data?.user?.username) {
return <UserLink username={data.user.username} />
} else {
+1 -2
View File
@@ -3,7 +3,6 @@ import useSWR from "swr"
import { Link } from "react-router-dom"
import * as api from "../api"
import { FullUser } from "./userTypes"
import styles from "./UserLink.module.css"
@@ -12,7 +11,7 @@ export type Props = {
}
export default function UserCard({ username }: Props) {
const { data: user, error } = useSWR<FullUser>(`/user/${username}`, api.get)
const { data: user, error } = useSWR<api.FullUser>(`/user/${username}`, api.get)
if (user) {
return <Link
+1
View File
@@ -65,6 +65,7 @@ export default function UserPage() {
export function ScratchList({ user }: { user: api.FullUser }) {
// TODO: needs backend
void user
/*
const { data: scratches, error } = useSWR<api.Scratch[]>(`/user/${user.username}/scratches`, api.get)
+2 -2
View File
@@ -5,7 +5,7 @@
"jsxFragmentFactory": "Fragment",
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"lib": ["ESNext"]
},
"lib": ["ESNext"],
}
+4179 -2965
View File
File diff suppressed because it is too large Load Diff