diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b153b54b..8b9954a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,7 +35,9 @@ jobs: yarn build yarn build:ui:production - name: Lint - run: yarn lint:ci + run: | + yarn lint:ci + yarn lint:ui:ci - name: Publish if: ${{ github.event_name == 'push' }} run: node build/publish.js diff --git a/.gitignore b/.gitignore index e0f1fff8..490a99eb 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ packages/**/*.js packages/ui-default/public packages/ui-default/misc/.iconfont packages/ui-default/static/locale +plugins/** # Data files *.mmdb diff --git a/package.json b/package.json index c783d765..51420a00 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "hydro-workspace", "private": true, "workspaces": [ - "packages/*" + "packages/*", + "plugins/*" ], "main": "package.json", "scripts": { @@ -13,22 +14,20 @@ "build:ui:production": "node packages/ui-default/build --production", "lint": "eslint packages --ext ts --fix", "lint:ci": "eslint packages --ext ts", - "lint:ui": "yarn run --cwd=packages/ui-default eslint . --fix", - "lint:ui:ci": "yarn run --cwd=packages/ui-default eslint .", - "pub": "node build/publish", + "lint:ui": "yarn workspace @hydrooj/ui-default eslint --ext .js,.ts,.jsx,.tsx . --fix", + "lint:ui:ci": "yarn workspace @hydrooj/ui-default eslint --ext .js,.ts,.jsx,.tsx .", "typedoc": "cross-env NODE_OPTIONS=--max_old_space_size=8192 typedoc", "debug:all": "node --trace-warnings --async-stack-traces --trace-deprecation build/start --debug --template", "debug": "node --trace-warnings --async-stack-traces --trace-deprecation node_modules/hydrooj/bin/hydrooj --debug --template", "start:all": "node build/start", "start": "node_modules/.bin/hydrooj", - "postinstall": "node build/hack", - "clean": "zsh -c \"rm -rf tsconfig.build.tsbuildinfo ./packages/*/tsconfig.tsbuildinfo ./.coverage\"" + "postinstall": "node build/hack && node build/prepare.js" }, "version": "1.0.0", "license": "AGPL-3.0-only", "devDependencies": { "@types/cross-spawn": "^6.0.2", - "@types/node": "^16.11.25", + "@types/node": "^16.11.26", "@types/semver": "^7.3.9", "@typescript-eslint/eslint-plugin": "5.12.0", "@typescript-eslint/parser": "5.12.0", @@ -36,19 +35,18 @@ "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "esbuild": "0.14.3", - "eslint": "^8.9.0", + "eslint": "^8.10.0", "eslint-config-airbnb-typescript": "12.3.1", "eslint-import-resolver-typescript": "2.5.0", "eslint-plugin-import": "2.25.4", "eslint-plugin-simple-import-sort": "7.0.0", - "fs-extra": "^10.0.0", + "fs-extra": "^10.0.1", "globby": "11.1.0", "latest-version": "^6.0.0", "mongodb": "^3.7.3", - "nmls": "^3.0.1", "ora": "5.4.1", "semver": "^7.3.5", - "typedoc": "^0.22.11", + "typedoc": "^0.22.12", "typescript": "4.4.3" } } diff --git a/packages/ui-default/backendlib/markdown-it-media.js b/packages/ui-default/backendlib/markdown-it-media.js index a73001cc..57193b8e 100644 --- a/packages/ui-default/backendlib/markdown-it-media.js +++ b/packages/ui-default/backendlib/markdown-it-media.js @@ -44,51 +44,45 @@ function extractVideoParameters(url) { return parameterMap; } function videoUrl(service, videoID, url, options) { - switch (service) { - case 'youtube': { - const parameters = extractVideoParameters(url); - if (options.youtube.parameters) { - Object.keys(options.youtube.parameters).forEach((key) => { - parameters.set(key, options.youtube.parameters[key]); - }); - } - const timeParameter = parameters.get('t'); - if (timeParameter !== undefined) { - let startTime = 0; - const timeParts = timeParameter.match(/[0-9]+/g); - let j = 0; - while (timeParts.length > 0) { - startTime += Number(timeParts.pop()) * Math.pow(60, j); - j += 1; - } - parameters.set('start', startTime); - parameters.delete('t'); + if (service === 'youtube') { + const parameters = extractVideoParameters(url); + if (options.youtube.parameters) { + Object.keys(options.youtube.parameters).forEach((key) => { + parameters.set(key, options.youtube.parameters[key]); + }); + } + const timeParameter = parameters.get('t'); + if (timeParameter !== undefined) { + let startTime = 0; + const timeParts = timeParameter.match(/[0-9]+/g); + let j = 0; + while (timeParts.length > 0) { + startTime += Number(timeParts.pop()) * Math.pow(60, j); + j += 1; } - parameters.delete('v'); - parameters.delete('feature'); - parameters.delete('origin'); - const parameterArray = Array.from(parameters, (p) => p.join('=')); - const parameterPos = videoID.indexOf('?'); - let finalUrl = 'https://www.youtube'; - if (options.youtube.nocookie || url.indexOf('youtube-nocookie.com') > -1) finalUrl += '-nocookie'; - finalUrl += `.com/embed/${parameterPos > -1 ? videoID.substr(0, parameterPos) : videoID}`; - if (parameterArray.length > 0) finalUrl += `?${parameterArray.join('&')}`; - return finalUrl; + parameters.set('start', startTime); + parameters.delete('t'); } - case 'vimeo': - return `https://player.vimeo.com/video/${videoID}`; - case 'vine': - return `https://vine.co/v/${videoID}/embed/${options.vine.embed}`; - case 'prezi': - return `https://prezi.com/embed/${videoID - }/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&` - + 'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&' - + 'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI'; - case 'osf': - return `https://mfr.osf.io/render?url=https://osf.io/${videoID}/?action=download`; - default: - return videoID; + parameters.delete('v'); + parameters.delete('feature'); + parameters.delete('origin'); + const parameterArray = Array.from(parameters, (p) => p.join('=')); + const parameterPos = videoID.indexOf('?'); + let finalUrl = 'https://www.youtube'; + if (options.youtube.nocookie || url.indexOf('youtube-nocookie.com') > -1) finalUrl += '-nocookie'; + finalUrl += `.com/embed/${parameterPos > -1 ? videoID.substr(0, parameterPos) : videoID}`; + if (parameterArray.length > 0) finalUrl += `?${parameterArray.join('&')}`; + return finalUrl; + } + if (service === 'vimeo') return `https://player.vimeo.com/video/${videoID}`; + if (service === 'vine') return `https://vine.co/v/${videoID}/embed/${options.vine.embed}`; + if (service === 'prezi') { + return `https://prezi.com/embed/${videoID}/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&` + + 'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&' + + 'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI'; } + if (service === 'osf') return `https://mfr.osf.io/render?url=https://osf.io/${videoID}/?action=download`; + return videoID; } module.exports = function videoPlugin(md) { @@ -138,10 +132,10 @@ module.exports = function videoPlugin(md) { } if (options[service]?.width) { return `
-
`; + `; } return `
${escapeHtml(videoID)}
`; }; diff --git a/packages/ui-default/components/messagepad/reducers/dialogues.js b/packages/ui-default/components/messagepad/reducers/dialogues.js index f8386bfb..e56009a5 100644 --- a/packages/ui-default/components/messagepad/reducers/dialogues.js +++ b/packages/ui-default/components/messagepad/reducers/dialogues.js @@ -4,11 +4,11 @@ export default function reducer(state = {}, action) { switch (action.type) { case 'DIALOGUES_LOAD_DIALOGUES_FULFILLED': { const { messages } = action.payload; - return {...state, ..._.keyBy(messages, 'udoc._id')}; + return { ...state, ..._.keyBy(messages, 'udoc._id') }; } case 'DIALOGUES_CREATE': { const { user } = action.payload; - if (state[user._id]) return state + if (state[user._id]) return state; return { ...state, [user._id]: { diff --git a/packages/ui-default/components/monaco/nls.js b/packages/ui-default/components/monaco/nls.js index 61eac917..00648b1d 100644 --- a/packages/ui-default/components/monaco/nls.js +++ b/packages/ui-default/components/monaco/nls.js @@ -40,10 +40,10 @@ export function setLocaleData(data) { CURRENT_LOCALE_DATA = data; } -export function loadMessageBundle(file) { +export function loadMessageBundle() { return localize; } -export function config(opt) { +export function config() { return loadMessageBundle; } diff --git a/packages/ui-default/components/react/DomComponent.jsx b/packages/ui-default/components/react/DomComponent.jsx deleted file mode 100644 index 07bd08d6..00000000 --- a/packages/ui-default/components/react/DomComponent.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -export default class DomComponent extends React.PureComponent { - componentDidMount() { - this.refs.dom.appendChild(this.props.childDom); - } - - componentWillUnmount() { - $(this.refs.dom).empty(); - } - - render() { - const { - childDom, - ...rest - } = this.props; - return ( -
- ); - } -} - -DomComponent.propTypes = { - childDom: PropTypes.instanceOf(HTMLElement).isRequired, -}; diff --git a/packages/ui-default/components/react/DomComponent.tsx b/packages/ui-default/components/react/DomComponent.tsx new file mode 100644 index 00000000..01ae0ee9 --- /dev/null +++ b/packages/ui-default/components/react/DomComponent.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { omit } from 'lodash'; + +export default function DomComponent(props: React.HTMLAttributes & { childDom: HTMLElement }) { + const ref = React.useRef(); + React.useEffect(() => { + ref.current.appendChild(props.childDom); + return () => { + $(ref.current).empty(); + }; + }); + return
; +} diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 3851f1de..af634eb0 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.33.2", + "version": "4.33.3", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", diff --git a/packages/ui-default/pages/problem_detail.page.jsx b/packages/ui-default/pages/problem_detail.page.jsx index f89bc602..edf0e6ba 100644 --- a/packages/ui-default/pages/problem_detail.page.jsx +++ b/packages/ui-default/pages/problem_detail.page.jsx @@ -254,7 +254,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor window.onresize = function () { statusChart.resize(); scoreChart.resize(); - } + }; } $(document).on('click', '[name="problem-sidebar__open-scratchpad"]', (ev) => { diff --git a/plugins/.gitkeep b/plugins/.gitkeep new file mode 100644 index 00000000..e69de29b