mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-23 20:54:48 -04:00
Merge branch '313-typescript-rebased' into 'main'
TypeScript Closes #313 See merge request PronounsPage/PronounsPage!414
This commit is contained in:
commit
88b0dee74d
174
.eslintrc.json
174
.eslintrc.json
@ -6,19 +6,28 @@
|
||||
"root": true,
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:jsonc/recommended-with-json",
|
||||
"plugin:yml/standard",
|
||||
"plugin:vue/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"@stylistic/js"
|
||||
"@stylistic",
|
||||
"@stylistic/ts"
|
||||
],
|
||||
"ignorePatterns": ["data", "dist", "new", "static", "census", "keys"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"node": true,
|
||||
"typescript": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"camelcase": ["warn", { "properties": "never" }],
|
||||
"curly": "warn",
|
||||
@ -29,72 +38,78 @@
|
||||
"no-irregular-whitespace": "warn",
|
||||
"no-prototype-builtins": "warn",
|
||||
"no-template-curly-in-string": "warn",
|
||||
"no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||
"no-useless-escape": "warn",
|
||||
"no-useless-rename": "warn",
|
||||
"object-shorthand": "warn",
|
||||
"prefer-const": "warn",
|
||||
"prefer-template": "warn",
|
||||
"import/extensions": ["error", "always"],
|
||||
"import/consistent-type-specifier-style": ["warn", "prefer-top-level"],
|
||||
"import/no-cycle": "warn",
|
||||
"import/no-self-import": "error",
|
||||
"import/no-useless-path-segments": "error",
|
||||
"@stylistic/js/array-bracket-newline": ["warn", "consistent"],
|
||||
"@stylistic/js/array-bracket-spacing": "warn",
|
||||
"@stylistic/js/array-element-newline": ["warn", "consistent"],
|
||||
"@stylistic/js/arrow-parens": "warn",
|
||||
"@stylistic/js/arrow-spacing": "warn",
|
||||
"@stylistic/js/block-spacing": "warn",
|
||||
"@stylistic/js/brace-style": "warn",
|
||||
"@stylistic/js/comma-dangle": ["warn", "always-multiline"],
|
||||
"@stylistic/js/comma-spacing": "warn",
|
||||
"@stylistic/js/comma-style": "warn",
|
||||
"@stylistic/js/computed-property-spacing": "warn",
|
||||
"@stylistic/js/dot-location": ["warn", "property"],
|
||||
"@stylistic/js/eol-last": "warn",
|
||||
"@stylistic/js/function-call-argument-newline": ["warn", "consistent"],
|
||||
"@stylistic/js/function-call-spacing": "warn",
|
||||
"@stylistic/js/function-paren-newline": "warn",
|
||||
"@stylistic/js/implicit-arrow-linebreak": "warn",
|
||||
"@stylistic/js/indent": ["warn", 4, { "SwitchCase": 1 }],
|
||||
"@stylistic/js/key-spacing": "warn",
|
||||
"@stylistic/js/keyword-spacing": "warn",
|
||||
"@stylistic/js/linebreak-style": "warn",
|
||||
"@stylistic/js/lines-between-class-members": "warn",
|
||||
"@stylistic/js/max-len": ["warn", { "code": 120 }],
|
||||
"@stylistic/js/max-statements-per-line": "warn",
|
||||
"@stylistic/js/multiline-ternary": ["warn", "always-multiline"],
|
||||
"@stylistic/js/new-parens": "warn",
|
||||
"@stylistic/js/newline-per-chained-call": "warn",
|
||||
"@stylistic/js/no-extra-parens": "warn",
|
||||
"@stylistic/js/no-extra-semi": "warn",
|
||||
"@stylistic/js/no-multi-spaces": "warn",
|
||||
"@stylistic/js/no-multiple-empty-lines": ["warn", { "max": 2, "maxEOF": 0, "maxBOF": 0 }],
|
||||
"@stylistic/js/no-tabs": "warn",
|
||||
"@stylistic/js/no-trailing-spaces": "warn",
|
||||
"@stylistic/js/no-whitespace-before-property": "warn",
|
||||
"@stylistic/js/object-curly-newline": "warn",
|
||||
"@stylistic/js/object-curly-spacing": ["warn", "always"],
|
||||
"@stylistic/js/object-property-newline": ["warn", { "allowAllPropertiesOnSameLine": true }],
|
||||
"@stylistic/js/one-var-declaration-per-line": "warn",
|
||||
"@stylistic/js/operator-linebreak": "warn",
|
||||
"@stylistic/js/padded-blocks": ["warn", "never"],
|
||||
"@stylistic/js/quote-props": ["warn", "as-needed"],
|
||||
"@stylistic/js/quotes": ["warn", "single"],
|
||||
"@stylistic/js/rest-spread-spacing": "warn",
|
||||
"@stylistic/js/semi": "warn",
|
||||
"@stylistic/js/semi-spacing": "warn",
|
||||
"@stylistic/js/space-before-blocks": "warn",
|
||||
"@stylistic/js/space-before-function-paren": ["warn", { "named": "never" }],
|
||||
"@stylistic/js/space-in-parens": "warn",
|
||||
"@stylistic/js/space-infix-ops": "warn",
|
||||
"@stylistic/js/space-unary-ops": "warn",
|
||||
"@stylistic/js/spaced-comment": "warn",
|
||||
"@stylistic/js/switch-colon-spacing": "warn",
|
||||
"@stylistic/js/template-curly-spacing": "warn",
|
||||
"@stylistic/js/template-tag-spacing": "warn",
|
||||
"@stylistic/js/wrap-iife": "warn",
|
||||
"@stylistic/js/yield-star-spacing": "warn",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/no-this-alias": "warn",
|
||||
"@stylistic/array-bracket-newline": ["warn", "consistent"],
|
||||
"@stylistic/array-bracket-spacing": "warn",
|
||||
"@stylistic/array-element-newline": ["warn", "consistent"],
|
||||
"@stylistic/arrow-parens": "warn",
|
||||
"@stylistic/arrow-spacing": "warn",
|
||||
"@stylistic/block-spacing": "warn",
|
||||
"@stylistic/brace-style": "warn",
|
||||
"@stylistic/comma-dangle": ["warn", "always-multiline"],
|
||||
"@stylistic/comma-spacing": "warn",
|
||||
"@stylistic/comma-style": "warn",
|
||||
"@stylistic/computed-property-spacing": "warn",
|
||||
"@stylistic/dot-location": ["warn", "property"],
|
||||
"@stylistic/eol-last": "warn",
|
||||
"@stylistic/function-call-argument-newline": ["warn", "consistent"],
|
||||
"@stylistic/function-call-spacing": "warn",
|
||||
"@stylistic/function-paren-newline": ["warn", "multiline-arguments"],
|
||||
"@stylistic/implicit-arrow-linebreak": "warn",
|
||||
"@stylistic/indent": ["warn", 4, { "SwitchCase": 1 }],
|
||||
"@stylistic/key-spacing": "warn",
|
||||
"@stylistic/keyword-spacing": "warn",
|
||||
"@stylistic/linebreak-style": "warn",
|
||||
"@stylistic/lines-between-class-members": ["warn", { "enforce": [
|
||||
{ "blankLine": "never", "prev": "field", "next": "field" },
|
||||
{ "blankLine": "always", "prev": "*", "next": "method" }
|
||||
] }],
|
||||
"@stylistic/max-len": ["warn", { "code": 120 }],
|
||||
"@stylistic/max-statements-per-line": "warn",
|
||||
"@stylistic/multiline-ternary": ["warn", "always-multiline"],
|
||||
"@stylistic/new-parens": "warn",
|
||||
"@stylistic/newline-per-chained-call": "warn",
|
||||
"@stylistic/no-extra-parens": "warn",
|
||||
"@stylistic/no-extra-semi": "warn",
|
||||
"@stylistic/no-multi-spaces": "warn",
|
||||
"@stylistic/no-multiple-empty-lines": ["warn", { "max": 2, "maxEOF": 0, "maxBOF": 0 }],
|
||||
"@stylistic/no-tabs": "warn",
|
||||
"@stylistic/no-trailing-spaces": "warn",
|
||||
"@stylistic/no-whitespace-before-property": "warn",
|
||||
"@stylistic/object-curly-newline": "warn",
|
||||
"@stylistic/object-curly-spacing": ["warn", "always"],
|
||||
"@stylistic/object-property-newline": ["warn", { "allowAllPropertiesOnSameLine": true }],
|
||||
"@stylistic/one-var-declaration-per-line": "warn",
|
||||
"@stylistic/operator-linebreak": "warn",
|
||||
"@stylistic/padded-blocks": ["warn", "never"],
|
||||
"@stylistic/quote-props": ["warn", "as-needed"],
|
||||
"@stylistic/quotes": ["warn", "single"],
|
||||
"@stylistic/rest-spread-spacing": "warn",
|
||||
"@stylistic/semi": "warn",
|
||||
"@stylistic/semi-spacing": "warn",
|
||||
"@stylistic/space-before-blocks": "warn",
|
||||
"@stylistic/space-before-function-paren": ["warn", { "named": "never" }],
|
||||
"@stylistic/space-in-parens": "warn",
|
||||
"@stylistic/space-infix-ops": "warn",
|
||||
"@stylistic/space-unary-ops": "warn",
|
||||
"@stylistic/spaced-comment": "warn",
|
||||
"@stylistic/switch-colon-spacing": "warn",
|
||||
"@stylistic/template-curly-spacing": "warn",
|
||||
"@stylistic/template-tag-spacing": "warn",
|
||||
"@stylistic/wrap-iife": "warn",
|
||||
"@stylistic/yield-star-spacing": "warn",
|
||||
"jsonc/array-bracket-newline": ["warn", "consistent"],
|
||||
"jsonc/array-bracket-spacing": "warn",
|
||||
"jsonc/array-element-newline": ["warn", "consistent"],
|
||||
@ -156,12 +171,42 @@
|
||||
"vue/template-curly-spacing": "warn"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.vue"],
|
||||
"rules": {
|
||||
// rules which require type information need to be listed separately
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/adjacent-overload-signatures": "warn",
|
||||
"@typescript-eslint/array-type": "warn",
|
||||
"@typescript-eslint/consistent-indexed-object-style": "warn",
|
||||
"@typescript-eslint/consistent-type-assertions": "warn",
|
||||
"@typescript-eslint/consistent-type-definitions": "warn",
|
||||
"@typescript-eslint/consistent-type-imports": "warn",
|
||||
"@typescript-eslint/consistent-type-exports": "warn",
|
||||
"@typescript-eslint/explicit-function-return-type": "warn",
|
||||
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "warn",
|
||||
"@typescript-eslint/no-unnecessary-type-arguments": "warn",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "warn",
|
||||
"@stylistic/ts/type-annotation-spacing": "warn"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.d.ts"],
|
||||
"rules": {
|
||||
// var is needed for globalThis declaration
|
||||
"no-var": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.json"],
|
||||
"parser": "jsonc-eslint-parser"
|
||||
},
|
||||
{
|
||||
"files": [".eslintrc.json"],
|
||||
"files": [".eslintrc.json", "tsconfig.json"],
|
||||
"rules": {
|
||||
"jsonc/no-comments": "off"
|
||||
}
|
||||
@ -170,7 +215,16 @@
|
||||
"files": ["*.suml", "*.yml"],
|
||||
"parser": "yaml-eslint-parser",
|
||||
"rules": {
|
||||
"@stylistic/js/spaced-comment": "off"
|
||||
"@stylistic/spaced-comment": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.vue"],
|
||||
"parser": "vue-eslint-parser",
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"extraFileExtensions": [".vue"],
|
||||
"project": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
check:
|
||||
stage: test
|
||||
image: node:latest
|
||||
image: node:18.17.1
|
||||
before_script:
|
||||
- set -o pipefail
|
||||
- export NODE_ENV=development
|
||||
@ -35,6 +35,10 @@ check:
|
||||
- make switch LANG=en
|
||||
- end_section
|
||||
|
||||
- start_section "Type checking"
|
||||
- yarn vue-tsc || record_failure
|
||||
- end_section
|
||||
|
||||
- start_section "Unit Tests"
|
||||
- >
|
||||
yarn test --ci --reporters=default --reporters=jest-junit
|
||||
@ -53,12 +57,12 @@ check:
|
||||
# calls scripts to check for simple issues while disabling actual work (e.g. no publishing to third party)
|
||||
# some scripts are left out because they need special configuration or are not safe to smoke test
|
||||
- start_section "Smoke test server scripts"
|
||||
- node server/migrate.js || record_failure "Smoke test migrate"
|
||||
- node server/calendarBot.js en,pl,es,pt,de,nl,fr,ja,ru,sv,lad,ua,vi "" || record_failure "Smoke test calendarBot"
|
||||
- node server/cleanupAccounts.js || record_failure "Smoke test cleanupAccounts"
|
||||
- node server/notify.js || record_failure "Smoke test notify"
|
||||
- node server/stats.js || record_failure "Smoke test stats"
|
||||
- node server/subscriptions.js || record_failure "Smoke test subscriptions"
|
||||
- yarn ts-node server/migrate.ts || record_failure "Smoke test migrate"
|
||||
- yarn ts-node server/calendarBot.js en,pl,es,pt,de,nl,fr,ja,ru,sv,lad,ua,vi "" || record_failure "Smoke test calendarBot"
|
||||
- yarn ts-node server/cleanupAccounts.js || record_failure "Smoke test cleanupAccounts"
|
||||
- yarn ts-node server/notify.js || record_failure "Smoke test notify"
|
||||
- yarn ts-node server/stats.ts || record_failure "Smoke test stats"
|
||||
- yarn ts-node server/subscriptions.js || record_failure "Smoke test subscriptions"
|
||||
- end_section
|
||||
|
||||
- >
|
||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -4,7 +4,7 @@
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.validate": ["javascript", "json", "jsonc", "yaml"],
|
||||
"eslint.validate": ["javascript", "json", "jsonc", "ts", "yaml"],
|
||||
"files.associations": {
|
||||
"*.suml": "yaml"
|
||||
},
|
||||
|
6
Makefile
6
Makefile
@ -12,7 +12,7 @@ install:
|
||||
mkdir -p moderation
|
||||
touch moderation/sus.txt moderation/rules-users.md moderation/rules-terminology.md moderation/rules-sources.md
|
||||
yarn
|
||||
node server/migrate.js
|
||||
yarn ts-node server/migrate.ts
|
||||
|
||||
lint:
|
||||
yarn lint
|
||||
@ -33,7 +33,7 @@ deploy: install
|
||||
mkdir -p ./cache
|
||||
git log -n 1 --pretty=format:"%H" > ./cache/version
|
||||
yarn build
|
||||
node server/migrate.js
|
||||
yarn ts-node server/migrate.ts
|
||||
ln -sfn ../data/img ./static/img-local
|
||||
ln -sfn ../data/docs ./static/docs-local
|
||||
|
||||
@ -45,4 +45,4 @@ switch:
|
||||
if [ -d ./locale/${LANG}/img/logo ]; then echo ""; else ln -s ../../_/img/logo ./locale/${LANG}/img/logo; fi
|
||||
|
||||
migrate:
|
||||
node server/migrate.js
|
||||
yarn ts-node server/migrate.ts
|
||||
|
26
README.md
26
README.md
@ -2,7 +2,7 @@
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [NodeJS](https://nodejs.org/en)
|
||||
- [NodeJS](https://nodejs.org/en) version 18.17.1
|
||||
- [Yarn](https://yarnpkg.com/getting-started/install) or other package manager
|
||||
|
||||
## Installation
|
||||
@ -176,9 +176,10 @@ Remember to also set `MAILER_OVERWRITE` to your own address
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If you're having issues with [HRM](https://webpack.js.org/concepts/hot-module-replacement/) (Hot Module Replacement) not reloading automatically:
|
||||
#### Hot Module Replacement in Nuxt development mode
|
||||
If you're having issues with [HMR](https://webpack.js.org/concepts/hot-module-replacement/) not reloading automatically:
|
||||
- The modules within `package.json` are matching the repo's `package.json`.
|
||||
- `nuxt.config.js` has the following option:
|
||||
- `nuxt.config.ts` has the following option:
|
||||
```js
|
||||
watchers: {
|
||||
webpack: {
|
||||
@ -188,6 +189,19 @@ If you're having issues with [HRM](https://webpack.js.org/concepts/hot-module-re
|
||||
}
|
||||
```
|
||||
|
||||
#### Out-of-Memory in Nuxt development mode
|
||||
If you experience a `JavaScript heap out of memory` error, it may help to disable typechecking (you can still typecheck via your editor or `yarn vue-ts`):
|
||||
- add to `nuxt.config.ts`:
|
||||
```js
|
||||
typescript: {
|
||||
typeCheck: false,
|
||||
},
|
||||
```
|
||||
|
||||
#### `ts-node` on another Node version
|
||||
If you use another node version and run into an error when using `yarn ts-node` (e.g. `Unknown file extension ".ts"`), then either use the recommended node version or use `ts-node` via an experimental loader:
|
||||
`node --loader ts-node/esm`.
|
||||
|
||||
## Translation
|
||||
|
||||
### Contributing to an existing language version
|
||||
@ -202,14 +216,14 @@ To check for missing translations, you can use the `admin/translations/missing`
|
||||
### Creating a new language version
|
||||
|
||||
Read [this](https://en.pronouns.page/new-version) first. \
|
||||
When you add a new language, remember to modify the file `./locale/locales.js` to add your language:
|
||||
When you add a new language, remember to modify the file `./locale/locales.ts` to add your language:
|
||||
```js
|
||||
// Add an object according to the following format:
|
||||
{ code: 'xx', name: 'xx', url: 'https://xx.pronouns.page', published: false, symbol: 'x', family: 'xxx' }
|
||||
new LocaleDescription('xx', 'xx', 'https://xx.pronouns.page', false, 'x', 'xxx'),
|
||||
|
||||
// Setting 'published' to true means that the language was published onto the main site.
|
||||
// For example:
|
||||
{ code: 'pt', name: 'Português', url: 'https://pt.pronouns.page', published: true, symbol: 'ã', family: 'romance' }
|
||||
new LocaleDescription('pt', 'Português', 'https://pt.pronouns.page', true, 'ã', 'romance'),
|
||||
```
|
||||
|
||||
### Current translations being worked on
|
||||
|
@ -242,9 +242,9 @@
|
||||
|
||||
<script>
|
||||
import { socialProviders } from '../src/socialProviders.js';
|
||||
import { gravatar } from '../src/helpers.js';
|
||||
import { gravatar } from '../src/helpers.ts';
|
||||
import { mapState } from 'vuex';
|
||||
import { usernameRegex } from '../src/username.js';
|
||||
import { usernameRegex } from '../src/username.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -40,7 +40,7 @@
|
||||
import adPlaceholders from '../src/adPlaceholders.js';
|
||||
import { adsInternalPerPlaceholder } from '../src/adsInternal.js';
|
||||
import { mapState } from 'vuex';
|
||||
import { randomItem } from '../src/helpers.js';
|
||||
import { randomItem } from '../src/helpers.ts';
|
||||
|
||||
const MOBILE_BREAKPOINT = 992;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fallbackAvatar, gravatar } from '../src/helpers.js';
|
||||
import { fallbackAvatar, gravatar } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -24,7 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { SourceLibrary } from '../src/classes.js';
|
||||
import { SourceLibrary } from '../src/classes.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -220,7 +220,7 @@
|
||||
|
||||
<script>
|
||||
import forbidden from '../src/forbidden.js';
|
||||
import { sleep } from '../src/helpers.js';
|
||||
import { sleep } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -67,7 +67,7 @@
|
||||
|
||||
<script>
|
||||
import { socialLinks } from '../src/contact.js';
|
||||
import { clearUrl } from '../src/helpers.js';
|
||||
import { clearUrl } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -3,7 +3,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { sleep } from '../src/helpers.js';
|
||||
import { sleep } from '../src/helpers.ts';
|
||||
|
||||
const COLOURS = [
|
||||
'#C71585',
|
||||
|
@ -99,7 +99,7 @@
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable';
|
||||
import { curry, isValidLink } from '../src/helpers.js';
|
||||
import { curry, isValidLink } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -161,8 +161,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Noun } from '../src/classes.js';
|
||||
import { buildDict } from '../src/helpers.js';
|
||||
import { Noun } from '../src/classes.ts';
|
||||
import { buildDict } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
@ -34,7 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { randomNumber, sleep } from '../src/helpers.js';
|
||||
import { randomNumber, sleep } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -190,7 +190,7 @@
|
||||
|
||||
<script>
|
||||
import { getContactLinks, getSocialLinks, getSupportLinks } from '../src/contact.js';
|
||||
import { groupBy } from '../src/helpers.js';
|
||||
import { groupBy } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -11,7 +11,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { buildImageUrl } from '../src/helpers.js';
|
||||
import { buildImageUrl } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable';
|
||||
import { curry } from '../src/helpers.js';
|
||||
import { curry } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -238,8 +238,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { InclusiveEntry } from '../src/classes.js';
|
||||
import { buildDict, clearUrl, clearLinkedText } from '../src/helpers.js';
|
||||
import { InclusiveEntry } from '../src/classes.ts';
|
||||
import { buildDict, clearUrl, clearLinkedText } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import Icon from './Icon.vue';
|
||||
import spelling from '../plugins/spelling.js';
|
||||
import { escapeHtml } from '../src/helpers.js';
|
||||
import { escapeHtml } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
mixins: [spelling],
|
||||
|
@ -52,7 +52,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { curry } from '../src/helpers.js';
|
||||
import { curry } from '../src/helpers.ts';
|
||||
import draggable from 'vuedraggable';
|
||||
|
||||
export default {
|
||||
|
@ -12,7 +12,7 @@
|
||||
<script>
|
||||
import { Day } from '../src/calendar/helpers.js';
|
||||
import { calendar } from '../src/calendar/calendar.js';
|
||||
import { ImmutableArray } from '../src/helpers.js';
|
||||
import { ImmutableArray } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -65,7 +65,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { clearUrl } from '../src/helpers.js';
|
||||
import { clearUrl } from '../src/helpers.ts';
|
||||
import LazyHydrate from 'vue-lazy-hydration';
|
||||
|
||||
export default {
|
||||
|
@ -192,7 +192,7 @@ import spelling from '../plugins/spelling.js';
|
||||
import mainPronoun from '../plugins/mainPronoun.js';
|
||||
import ClientOnly from 'vue-client-only';
|
||||
import { calendar } from '../src/calendar/calendar.js';
|
||||
import { buildImageUrl } from '../src/helpers.js';
|
||||
import { buildImageUrl } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
components: { ClientOnly },
|
||||
|
@ -12,14 +12,16 @@
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
pronunciation: { required: true, type: String },
|
||||
text: { default: false, type: Boolean },
|
||||
},
|
||||
computed: {
|
||||
voices() {
|
||||
voices(): string[] {
|
||||
if (this.$config.pronunciation.enabled) {
|
||||
return Object.keys(this.$config.pronunciation.voices);
|
||||
} else {
|
||||
@ -27,7 +29,7 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div class="input-group input-group-sm w-auto">
|
||||
<span class="input-group-text">/</span>
|
||||
<input v-model="rawPronunciation" class="form-control mw-input" :placeholder="$t('profile.pronunciation.ipa')" maxlength="255">
|
||||
<input
|
||||
v-model="rawPronunciation"
|
||||
class="form-control mw-input"
|
||||
:placeholder="$t('profile.pronunciation.ipa')"
|
||||
maxlength="255"
|
||||
>
|
||||
<span class="input-group-text">/</span>
|
||||
<PronunciationSpeaker
|
||||
v-for="voice in voices"
|
||||
@ -13,16 +18,19 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { escapePronunciationString, unescapePronunciationString } from '../src/helpers.js';
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
export default {
|
||||
import { escapePronunciationString, unescapePronunciationString } from '../src/helpers.ts';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
value: { default: null, type: String },
|
||||
value: { default: null, type: String as PropType<string | null> },
|
||||
},
|
||||
computed: {
|
||||
rawPronunciation: {
|
||||
get() {
|
||||
get(): string {
|
||||
if (this.value) {
|
||||
const phonemes = this.value.substring(1, this.value.length - 1);
|
||||
return unescapePronunciationString(phonemes);
|
||||
@ -30,7 +38,7 @@ export default {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
set(rawPronunciation) {
|
||||
set(rawPronunciation: string) {
|
||||
let pronunciation;
|
||||
if (rawPronunciation) {
|
||||
pronunciation = `/${escapePronunciationString(rawPronunciation)}/`;
|
||||
@ -41,7 +49,7 @@ export default {
|
||||
this.$emit('input', pronunciation);
|
||||
},
|
||||
},
|
||||
voices() {
|
||||
voices(): string[] {
|
||||
if (this.$config.pronunciation.enabled) {
|
||||
return Object.keys(this.$config.pronunciation.voices);
|
||||
} else {
|
||||
@ -49,5 +57,5 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -11,33 +11,35 @@
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { Base64 } from 'js-base64';
|
||||
import Vue from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
const STATE_IDLE = 'idle';
|
||||
const STATE_LOADING = 'loading';
|
||||
const STATE_PLAYING = 'playing';
|
||||
|
||||
export default {
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
pronunciation: { default: null, type: String },
|
||||
pronunciation: { default: null, type: String as PropType<string | null> },
|
||||
voice: { required: true, type: String },
|
||||
},
|
||||
data() {
|
||||
data(): { state: 'idle' | 'loading' | 'playing', sound: HTMLAudioElement | null } {
|
||||
return {
|
||||
state: STATE_IDLE,
|
||||
sound: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pronunciationLink() {
|
||||
pronunciationLink(): string | undefined {
|
||||
if (!this.pronunciation) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return `/api/pronounce/${this.voice}/${Base64.encodeURI(this.pronunciation)}`;
|
||||
},
|
||||
name() {
|
||||
name(): string | null {
|
||||
if (!this.$config.pronunciation.enabled) {
|
||||
return this.voice;
|
||||
}
|
||||
@ -50,7 +52,7 @@ export default {
|
||||
|
||||
return this.voice;
|
||||
},
|
||||
icon() {
|
||||
icon(): string {
|
||||
switch (this.state) {
|
||||
case STATE_LOADING:
|
||||
return 'spinner fa-spin';
|
||||
@ -64,6 +66,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
pronounce() {
|
||||
if (!this.pronunciationLink) {
|
||||
return;
|
||||
}
|
||||
if (this.sound && this.sound.src.endsWith(this.pronunciationLink) && !this.sound.error) {
|
||||
// reuse the sound object if it has the same source and has been loaded without an error
|
||||
this.sound.pause();
|
||||
@ -75,7 +80,7 @@ export default {
|
||||
|
||||
this.sound = new Audio(this.pronunciationLink);
|
||||
|
||||
this.sound.addEventListener('canplay', () => this.sound.play());
|
||||
this.sound.addEventListener('canplay', () => this.sound!.play());
|
||||
this.sound.addEventListener('play', () => this.state = STATE_PLAYING);
|
||||
this.sound.addEventListener('ended', () => this.state = STATE_IDLE);
|
||||
this.sound.addEventListener('error', () => this.state = STATE_IDLE);
|
||||
@ -84,5 +89,5 @@ export default {
|
||||
this.sound.load();
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import { makeId } from '../src/helpers.js';
|
||||
import { makeId } from '../src/helpers.ts';
|
||||
|
||||
const primary = '#C71585';
|
||||
const primaryDark = '#810e57';
|
||||
|
@ -24,7 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import allLocalesRaw from '../locale/locales.js';
|
||||
import allLocalesRaw from '../locale/locales.ts';
|
||||
const allLocales = ['*'];
|
||||
for (const { code } of allLocalesRaw) {
|
||||
allLocales.push(code);
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<script>
|
||||
import { getSocialLinks } from '../src/contact.js';
|
||||
import { groupBy } from '../src/helpers.js';
|
||||
import { groupBy } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -15,7 +15,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { makeId } from '../src/helpers.js';
|
||||
import { makeId } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -173,7 +173,7 @@
|
||||
|
||||
<script>
|
||||
import { pronounLibrary } from '../src/data.js';
|
||||
import { Source } from '../src/classes.js';
|
||||
import { Source } from '../src/classes.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import spelling from '../plugins/spelling.js';
|
||||
import { escapeHtml } from '../src/helpers.js';
|
||||
import { escapeHtml } from '../src/helpers.ts';
|
||||
import { safeInlineMarkdown } from '../src/simpleMarkdown.js';
|
||||
|
||||
export default {
|
||||
|
@ -92,7 +92,7 @@
|
||||
|
||||
<script>
|
||||
import { EventLevel } from '../src/calendar/helpers.js';
|
||||
import { buildImageUrl } from '../src/helpers.js';
|
||||
import { buildImageUrl } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -125,8 +125,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TermsEntry } from '../src/classes.js';
|
||||
import { buildDict, clearUrl, clearLinkedText } from '../src/helpers.js';
|
||||
import { TermsEntry } from '../src/classes.ts';
|
||||
import { buildDict, clearUrl, clearLinkedText } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
import { calendar } from '../src/calendar/calendar.js';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<ul class="list-unstyled">
|
||||
<li v-for="{ icon, label, content } in $t('links.zine.submissions.rules')" class="mb-2">
|
||||
<li v-for="{ icon, label, content } in submissionRules" :key="label" class="mb-2">
|
||||
<h4>
|
||||
<Icon :v="icon" />
|
||||
<LinkedText :text="label" />:
|
||||
@ -23,3 +23,19 @@
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
interface SubmissionRule {
|
||||
icon: string, label: string, content: string | string[]
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
computed: {
|
||||
submissionRules(): SubmissionRule[] {
|
||||
// extract translation to computed property as type casts are not allowed in template syntax for Vue 2.7
|
||||
return this.$t('links.zine.submissions.rules') as unknown as SubmissionRule[];
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -1,8 +0,0 @@
|
||||
export default {
|
||||
globals: {
|
||||
// define the config global here, but fill its properties later in the individual tests
|
||||
config: {},
|
||||
},
|
||||
testPathIgnorePatterns: ['.yarn', 'node_modules'],
|
||||
transform: {},
|
||||
};
|
23
jest.config.ts
Normal file
23
jest.config.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { Config } from 'jest';
|
||||
|
||||
const config: Config = {
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
globals: {
|
||||
// define the config global here, but fill its properties later in the individual tests
|
||||
config: {},
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
},
|
||||
testEnvironment: 'node',
|
||||
testPathIgnorePatterns: ['.yarn', 'node_modules'],
|
||||
transform: {
|
||||
'^.+\\.ts$': ['ts-jest', {
|
||||
// use isolated modules to speed up test execution; type checking happens separately
|
||||
isolatedModules: true,
|
||||
useESM: true,
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
@ -37,7 +37,7 @@
|
||||
import Vue from 'vue';
|
||||
import dark from '../plugins/dark.js';
|
||||
import sorter from 'avris-sorter';
|
||||
import { sleep } from '../src/helpers.js';
|
||||
import { sleep } from '../src/helpers.ts';
|
||||
import md5 from 'js-md5';
|
||||
|
||||
// no need to be super secure, just a sign that the page is not public
|
||||
|
2
locale/config.ts
Normal file
2
locale/config.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// TODO: replace with concrete type
|
||||
export type Config = any;
|
@ -54,7 +54,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NounDeclension } from '../../../src/classes.js';
|
||||
import { NounDeclension } from '../../../src/classes.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -1,28 +0,0 @@
|
||||
export default [
|
||||
{ code: 'de', name: 'Deutsch', url: 'https://de.pronouns.page', published: true, symbol: 'ß', family: 'germanic' },
|
||||
{ code: 'es', name: 'Español', url: 'https://pronombr.es', published: true, symbol: 'ñ', family: 'romance' },
|
||||
{ code: 'eo', name: 'Esperanto', url: 'https://eo.pronouns.page', published: false, symbol: 'ĥ', family: 'constructed' },
|
||||
{ code: 'en', name: 'English', url: 'https://en.pronouns.page', published: true, symbol: 'þ', family: 'germanic' },
|
||||
{ code: 'et', name: 'Eesti keel', url: 'https://et.pronouns.page', published: true, symbol: 'õ', family: 'finnish' },
|
||||
{ code: 'fr', name: 'Français', url: 'https://pronoms.fr', published: true, symbol: 'ç', family: 'romance' },
|
||||
{ code: 'gl', name: 'Galego', url: 'https://gl.pronouns.page', published: false, symbol: 'ñ', family: 'romance' }, // symbol duplicate with spanish
|
||||
{ code: 'he', name: 'עברית', url: 'https://he.pronouns.page', published: false, symbol: 'ע', family: 'semitic' }, // not entirely sure about the languange family
|
||||
{ code: 'it', name: 'Italiano', url: 'https://it.pronouns.page', published: false, symbol: 'à', family: 'romance' },
|
||||
{ code: 'lad', name: 'Ladino', extra: 'Djudezmo', url: 'https://lad.pronouns.page', published: true, symbol: 'ny', family: 'romance' },
|
||||
{ code: 'nl', name: 'Nederlands', url: 'https://nl.pronouns.page', published: true, symbol: 'ij', family: 'germanic' },
|
||||
{ code: 'no', name: 'Norsk', extra: 'Bokmål', url: 'https://no.pronouns.page', published: true, symbol: 'æ', family: 'germanic' }, // å might be better, but it's used for swedish
|
||||
{ code: 'pl', name: 'Polski', url: 'https://zaimki.pl', published: true, symbol: 'ą', family: 'slavic' },
|
||||
{ code: 'pt', name: 'Português', url: 'https://pt.pronouns.page', published: true, symbol: 'ã', family: 'romance' },
|
||||
{ code: 'ro', name: 'Română', url: 'https://ro.pronouns.page', published: true, symbol: 'ă', family: 'romance' },
|
||||
{ code: 'sv', name: 'Svenska', url: 'https://sv.pronouns.page', published: true, symbol: 'å', family: 'germanic' },
|
||||
{ code: 'tr', name: 'Türkçe', url: 'https://tr.pronouns.page', published: false, symbol: 'ş', family: 'turkic' },
|
||||
{ code: 'vi', name: 'Tiếng Việt', url: 'https://vi.pronouns.page', published: true, symbol: 'ớ', family: 'vietic' },
|
||||
{ code: 'ar', name: 'العربية', extra: 'الفصحى', url: 'https://ar.pronouns.page', published: false, symbol: 'ش', family: 'semitic' },
|
||||
{ code: 'ru', name: 'Русский', url: 'https://ru.pronouns.page', published: true, symbol: 'й', family: 'slavic' },
|
||||
{ code: 'ua', name: 'Українська', url: 'https://ua.pronouns.page', published: true, symbol: 'ї', family: 'slavic' },
|
||||
{ code: 'ja', name: '日本語', url: 'https://ja.pronouns.page', published: true, symbol: 'の', family: 'japonic' },
|
||||
{ code: 'ko', name: '한국어', url: 'https://ko.pronouns.page', published: false, symbol: '인', family: 'koreanic' },
|
||||
{ code: 'yi', name: 'ייִדיש', url: 'https://yi.pronouns.page', published: false, symbol: 'ש', family: 'germanic' },
|
||||
{ code: 'zh', name: '中文', url: 'https://zh.pronouns.page', published: true, symbol: '人', family: '' },
|
||||
{ code: 'tok', name: 'toki pona', url: 'https://tok.pronouns.page', published: false, symbol: '⊡', family: 'constructed' },
|
||||
];
|
59
locale/locales.ts
Normal file
59
locale/locales.ts
Normal file
@ -0,0 +1,59 @@
|
||||
export class LocaleDescription {
|
||||
code: string;
|
||||
name: string;
|
||||
url: string;
|
||||
published: boolean;
|
||||
symbol: string;
|
||||
family: string;
|
||||
extra: string | null;
|
||||
|
||||
constructor(
|
||||
code: string,
|
||||
name: string,
|
||||
url: string,
|
||||
published: boolean,
|
||||
symbol: string,
|
||||
family: string,
|
||||
extra: string | null = null,
|
||||
) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.published = published;
|
||||
this.symbol = symbol;
|
||||
this.family = family;
|
||||
this.extra = extra;
|
||||
}
|
||||
}
|
||||
|
||||
export default [
|
||||
new LocaleDescription('de', 'Deutsch', 'https://de.pronouns.page', true, 'ß', 'germanic'),
|
||||
new LocaleDescription('es', 'Español', 'https://pronombr.es', true, 'ñ', 'romance'),
|
||||
new LocaleDescription('eo', 'Esperanto', 'https://eo.pronouns.page', false, 'ĥ', 'constructed'),
|
||||
new LocaleDescription('en', 'English', 'https://en.pronouns.page', true, 'þ', 'germanic'),
|
||||
new LocaleDescription('et', 'Eesti keel', 'https://et.pronouns.page', true, 'õ', 'finnish'),
|
||||
new LocaleDescription('fr', 'Français', 'https://pronoms.fr', true, 'ç', 'romance'),
|
||||
// symbol duplicate with spanish
|
||||
new LocaleDescription('gl', 'Galego', 'https://gl.pronouns.page', false, 'ñ', 'romance'),
|
||||
// not entirely sure about the languange family
|
||||
new LocaleDescription('he', 'עברית', 'https://he.pronouns.page', false, 'ע', 'semitic'),
|
||||
new LocaleDescription('it', 'Italiano', 'https://it.pronouns.page', false, 'à', 'romance'),
|
||||
new LocaleDescription('lad', 'Ladino', 'https://lad.pronouns.page', true, 'ny', 'romance', 'Djudezmo'),
|
||||
new LocaleDescription('nl', 'Nederlands', 'https://nl.pronouns.page', true, 'ij', 'germanic'),
|
||||
// å might be better, but it's used for swedish
|
||||
new LocaleDescription('no', 'Norsk', 'https://no.pronouns.page', true, 'æ', 'germanic', 'Bokmål'),
|
||||
new LocaleDescription('pl', 'Polski', 'https://zaimki.pl', true, 'ą', 'slavic'),
|
||||
new LocaleDescription('pt', 'Português', 'https://pt.pronouns.page', true, 'ã', 'romance'),
|
||||
new LocaleDescription('ro', 'Română', 'https://ro.pronouns.page', true, 'ă', 'romance'),
|
||||
new LocaleDescription('sv', 'Svenska', 'https://sv.pronouns.page', true, 'å', 'germanic'),
|
||||
new LocaleDescription('tr', 'Türkçe', 'https://tr.pronouns.page', false, 'ş', 'turkic'),
|
||||
new LocaleDescription('vi', 'Tiếng Việt', 'https://vi.pronouns.page', true, 'ớ', 'vietic'),
|
||||
new LocaleDescription('ar', 'العربية', 'https://ar.pronouns.page', false, 'ش', 'semitic', 'الفصحى'),
|
||||
new LocaleDescription('ru', 'Русский', 'https://ru.pronouns.page', true, 'й', 'slavic'),
|
||||
new LocaleDescription('ua', 'Українська', 'https://ua.pronouns.page', true, 'ї', 'slavic'),
|
||||
new LocaleDescription('ja', '日本語', 'https://ja.pronouns.page', true, 'の', 'japonic'),
|
||||
new LocaleDescription('ko', '한국어', 'https://ko.pronouns.page', false, '인', 'koreanic'),
|
||||
new LocaleDescription('yi', 'ייִדיש', 'https://yi.pronouns.page', false, 'ש', 'germanic'),
|
||||
new LocaleDescription('zh', '中文', 'https://zh.pronouns.page', true, '人', ''),
|
||||
new LocaleDescription('tok', 'toki pona', 'https://tok.pronouns.page', false, '⊡', 'constructed'),
|
||||
];
|
@ -199,8 +199,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Noun, NounDeclension, SourceLibrary } from '../../../src/classes.js';
|
||||
import { head } from '../../../src/helpers.js';
|
||||
import { Noun, NounDeclension, SourceLibrary } from '../../../src/classes.ts';
|
||||
import { head } from '../../../src/helpers.ts';
|
||||
import NounsNav from './NounsNav.vue';
|
||||
import templates from './dukatywy.tsv';
|
||||
|
||||
|
@ -199,8 +199,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Noun, NounDeclension, SourceLibrary } from '../../../src/classes.js';
|
||||
import { head } from '../../../src/helpers.js';
|
||||
import { Noun, NounDeclension, SourceLibrary } from '../../../src/classes.ts';
|
||||
import { head } from '../../../src/helpers.ts';
|
||||
import NounsNav from './NounsNav.vue';
|
||||
import templates from './iksatywy.tsv';
|
||||
|
||||
|
@ -86,9 +86,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NounDeclension } from '../../../src/classes.js';
|
||||
import { NounDeclension } from '../../../src/classes.ts';
|
||||
import hash from '../../../plugins/hash.js';
|
||||
import { head } from '../../../src/helpers.js';
|
||||
import { head } from '../../../src/helpers.ts';
|
||||
import NounsNav from './NounsNav.vue';
|
||||
|
||||
export default {
|
||||
|
@ -92,8 +92,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Noun, SourceLibrary } from '../../../src/classes.js';
|
||||
import { head } from '../../../src/helpers.js';
|
||||
import { Noun, SourceLibrary } from '../../../src/classes.ts';
|
||||
import { head } from '../../../src/helpers.ts';
|
||||
import NounsNav from './NounsNav.vue';
|
||||
|
||||
export default {
|
||||
|
@ -49,7 +49,7 @@
|
||||
<script>
|
||||
import { pronouns } from '../../../src/data.js';
|
||||
import { getPronoun } from '../../../src/buildPronoun.js';
|
||||
import { buildDict } from '../../../src/helpers.js';
|
||||
import { buildDict } from '../../../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -56,7 +56,7 @@
|
||||
<script>
|
||||
import { pronouns } from '../../../src/data.js';
|
||||
import { getPronoun } from '../../../src/buildPronoun.js';
|
||||
import { buildDict } from '../../../src/helpers.js';
|
||||
import { buildDict } from '../../../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
2
locale/translations.ts
Normal file
2
locale/translations.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// TODO: replace with concrete type
|
||||
export type Translations = any;
|
4
locale/tsconfig.json
Normal file
4
locale/tsconfig.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
// necessary for a peculiar edge case where the symlinked locale to data/ yields an error with ESLint
|
||||
"extends": "../tsconfig.json"
|
||||
}
|
@ -56,7 +56,7 @@
|
||||
<script>
|
||||
import { pronouns } from '../../../src/data.js';
|
||||
import { getPronoun } from '../../../src/buildPronoun.js';
|
||||
import { buildDict } from '../../../src/helpers.js';
|
||||
import { buildDict } from '../../../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -1,16 +1,22 @@
|
||||
import './src/dotenv.js';
|
||||
|
||||
import { loadSuml } from './server/loader.js';
|
||||
import { loadSuml } from './server/loader.ts';
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import rtlcss from 'rtlcss';
|
||||
import { buildDict, buildList } from './src/helpers.js';
|
||||
import buildLocaleList from './src/buildLocaleList.js';
|
||||
import type { NuxtConfig } from '@nuxt/types';
|
||||
import type { IncomingMessage } from 'connect';
|
||||
import type { ServerResponse } from 'http';
|
||||
import type { Plugin as PostcssPlugin } from 'postcss';
|
||||
import { buildDict, buildList } from './src/helpers.ts';
|
||||
import buildLocaleList from './src/buildLocaleList.ts';
|
||||
import formatError from './src/error.js';
|
||||
import type { Config } from './locale/config.ts';
|
||||
import type { Translations } from './locale/translations.ts';
|
||||
|
||||
const config = loadSuml('config');
|
||||
const translations = loadSuml('translations');
|
||||
const config = loadSuml('config') as Config;
|
||||
const translations = loadSuml('translations') as Translations;
|
||||
|
||||
const locale = config.locale;
|
||||
const locales = buildLocaleList(locale);
|
||||
@ -44,15 +50,15 @@ const allVersionsUrls = buildList(function*() {
|
||||
yield 'https://test.pronouns.page';
|
||||
} else {
|
||||
yield 'https://pronouns.page';
|
||||
for (const loc in locales) {
|
||||
yield locales[loc].url;
|
||||
for (const localeDescription of Object.values(locales)) {
|
||||
yield localeDescription.url;
|
||||
}
|
||||
}
|
||||
});
|
||||
process.env.ALL_LOCALES_URLS = allVersionsUrls.join(',');
|
||||
|
||||
const buildFlags = () => {
|
||||
const flags = [];
|
||||
const buildFlags = (): Record<string, string> => {
|
||||
const flags: [string, string][] = [];
|
||||
for (const flag of fs.readdirSync(`${__dirname}/static/flags/`)) {
|
||||
let flagDisplay = flag
|
||||
.replace(new RegExp('\.png$'), '')
|
||||
@ -87,17 +93,15 @@ const buildFlags = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const postCssPlugins = [
|
||||
autoprefixer,
|
||||
const postCssPlugins: PostcssPlugin[] = [
|
||||
autoprefixer(),
|
||||
];
|
||||
|
||||
if (config.dir === 'rtl') {
|
||||
postCssPlugins.push(rtlcss);
|
||||
postCssPlugins.push(rtlcss() as PostcssPlugin);
|
||||
}
|
||||
|
||||
const getAllFiles = function (dirPath, arrayOfFiles) {
|
||||
arrayOfFiles = arrayOfFiles || [];
|
||||
|
||||
const getAllFiles = (dirPath: string, arrayOfFiles: string[] = []): string[] => {
|
||||
fs.readdirSync(dirPath).forEach(function (file) {
|
||||
if (fs.statSync(`${dirPath}/${file}`).isDirectory()) {
|
||||
arrayOfFiles = getAllFiles(`${dirPath}/${file}`, arrayOfFiles);
|
||||
@ -108,18 +112,18 @@ const getAllFiles = function (dirPath, arrayOfFiles) {
|
||||
|
||||
return arrayOfFiles;
|
||||
};
|
||||
const jsons = {};
|
||||
const jsons: Record<string, unknown> = {};
|
||||
for (const file of getAllFiles(`${__dirname}/data/docs`)) {
|
||||
if (!file.endsWith('.json')) {
|
||||
continue;
|
||||
}
|
||||
jsons[path.relative(`${__dirname}/data/docs`, file)] = JSON.parse(fs.readFileSync(file));
|
||||
jsons[path.relative(`${__dirname}/data/docs`, file)] = JSON.parse(fs.readFileSync(file).toString());
|
||||
}
|
||||
|
||||
|
||||
const hostname = process.env.HOST ?? '0.0.0.0';
|
||||
const port = parseInt(process.env.PORT ?? '3000');
|
||||
export default {
|
||||
const nuxtConfig: NuxtConfig = {
|
||||
server: {
|
||||
host: hostname, // listen on any host name
|
||||
port,
|
||||
@ -163,14 +167,21 @@ export default {
|
||||
],
|
||||
plugins: [
|
||||
{ src: '~/plugins/axios.js' },
|
||||
{ src: '~/plugins/globals.js' },
|
||||
{ src: '~/plugins/auth.js' },
|
||||
{ src: '~/plugins/globals.ts' },
|
||||
{ src: '~/plugins/auth.ts' },
|
||||
{ src: '~/plugins/datepicker.js', ssr: false },
|
||||
{ src: '~/plugins/track.js', ssr: false },
|
||||
{ src: '~/plugins/browserDetect.js' },
|
||||
],
|
||||
components: true,
|
||||
buildModules: [],
|
||||
buildModules: [
|
||||
'@nuxt/typescript-build',
|
||||
],
|
||||
loaders: {
|
||||
ts: {
|
||||
configFile: path.resolve(__dirname, 'tsconfig.json'),
|
||||
},
|
||||
},
|
||||
modules: [
|
||||
'@privyid/nuxt-csrf',
|
||||
'@nuxtjs/pwa',
|
||||
@ -227,7 +238,7 @@ export default {
|
||||
},
|
||||
},
|
||||
extend(config) {
|
||||
config.module.rules.push({
|
||||
config.module!.rules.push({
|
||||
test: /\.csv|\.tsv$/,
|
||||
loader: 'csv-loader',
|
||||
options: {
|
||||
@ -237,19 +248,19 @@ export default {
|
||||
delimiter: '\t',
|
||||
},
|
||||
});
|
||||
config.module.rules.push({
|
||||
config.module!.rules.push({
|
||||
test: /\.suml$/,
|
||||
loader: 'suml-loader',
|
||||
});
|
||||
config.module.rules.push({
|
||||
config.module!.rules.push({
|
||||
test: /\.md$/,
|
||||
use: ['html-loader', 'markdown-loader'],
|
||||
});
|
||||
config.module.rules.push({
|
||||
config.module!.rules.push({
|
||||
test: /\.ya?ml$/,
|
||||
use: 'yaml-loader',
|
||||
});
|
||||
config.module.rules.push({
|
||||
config.module!.rules.push({
|
||||
test: /\.js$/,
|
||||
loader: 'string-replace-loader',
|
||||
options: {
|
||||
@ -276,32 +287,35 @@ export default {
|
||||
transpile: ['markdown-it'],
|
||||
},
|
||||
env: {
|
||||
ENV: process.env.ENV,
|
||||
BASE_URL: process.env.BASE_URL,
|
||||
ENV: process.env.ENV!,
|
||||
BASE_URL: process.env.BASE_URL!,
|
||||
HOME_URL: process.env.HOME_URL || 'https://pronouns.page',
|
||||
TITLE: title,
|
||||
PUBLIC_KEY: fs.readFileSync(`${__dirname}/keys/public.pem`).toString(),
|
||||
CONFIG: config,
|
||||
LOCALE: config.locale,
|
||||
// @ts-expect-error: Nuxt checks for string, but object works fine
|
||||
LOCALES: locales,
|
||||
// @ts-expect-error: Nuxt checks for string, but string[] works fine
|
||||
FLAGS: buildFlags(),
|
||||
// @ts-expect-error: Nuxt checks for string, but string[] works fine
|
||||
FLAGS_ASTERISK: ['Heteroromantic', 'Heterosexual', 'Monoamorous', 'Monogamous', 'Cis Ally', 'Straight Ally'],
|
||||
BUCKET: `https://${process.env.AWS_S3_BUCKET}.s3-${process.env.AWS_REGION}.amazonaws.com`,
|
||||
CLOUDFRONT: process.env.CLOUDFRONT,
|
||||
STATS_FILE: process.env.STATS_FILE,
|
||||
TURNSTILE_SITEKEY: process.env.TURNSTILE_SITEKEY,
|
||||
CLOUDFRONT: process.env.CLOUDFRONT!,
|
||||
STATS_FILE: process.env.STATS_FILE!,
|
||||
TURNSTILE_SITEKEY: process.env.TURNSTILE_SITEKEY!,
|
||||
ALL_LOCALES_URLS: process.env.ALL_LOCALES_URLS,
|
||||
LOGO: logo,
|
||||
MIN_AGE: config.ageLimit || 13,
|
||||
JSONS: JSON.stringify(jsons),
|
||||
PLAUSIBLE_API_HOST: process.env.PLAUSIBLE_API_HOST,
|
||||
HEARTBEAT_LINK: process.env.HEARTBEAT_LINK,
|
||||
VERSION: version,
|
||||
PLAUSIBLE_API_HOST: process.env.PLAUSIBLE_API_HOST!,
|
||||
HEARTBEAT_LINK: process.env.HEARTBEAT_LINK!,
|
||||
VERSION: version!,
|
||||
KEYWORDS: keywords,
|
||||
},
|
||||
serverMiddleware: [
|
||||
'~/server/no-ssr.js',
|
||||
'~/server/index.js',
|
||||
'~/server/no-ssr.ts',
|
||||
'~/server/index.ts',
|
||||
],
|
||||
axios: {
|
||||
baseURL: `${process.env.BASE_URL}/api`,
|
||||
@ -459,7 +473,7 @@ export default {
|
||||
hooks: {
|
||||
render: {
|
||||
errorMiddleware(app) {
|
||||
app.use((err, req, res, next) => {
|
||||
app.use((err: unknown, req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => {
|
||||
if (err) {
|
||||
console.error(formatError(err, req));
|
||||
}
|
||||
@ -469,3 +483,5 @@ export default {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default nuxtConfig;
|
26
package.json
26
package.json
@ -9,7 +9,7 @@
|
||||
"start": "nuxt start",
|
||||
"export": "nuxt export",
|
||||
"serve": "nuxt serve",
|
||||
"lint": "eslint --ext .js,.json,.suml,.yml,.vue --fix .",
|
||||
"lint": "eslint --ext .js,.json,.suml,.ts,.yml,.vue --fix .",
|
||||
"test": "node --experimental-vm-modules $(yarn bin jest)"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -81,7 +81,24 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-pro": "git+ssh://git@gitlab.com:Avris/FontAwesomePro.git",
|
||||
"@stylistic/eslint-plugin-js": "^1.5.1",
|
||||
"@nuxt/types": "2.17.2",
|
||||
"@nuxt/typescript-build": "^3.0.2",
|
||||
"@stylistic/eslint-plugin": "^1.5.4",
|
||||
"@types/autoprefixer": "^10.2.0",
|
||||
"@types/cookie-parser": "^1.4.6",
|
||||
"@types/express-session": "^1.17.10",
|
||||
"@types/js-md5": "^0.7.2",
|
||||
"@types/jsonwebtoken": "^8.5.9",
|
||||
"@types/luxon": "^1.27.1",
|
||||
"@types/node": "^20.11.5",
|
||||
"@types/node-fetch": "^2.6.11",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/papaparse": "^5.3.14",
|
||||
"@types/rtlcss": "^3.1.2",
|
||||
"@types/speakeasy": "^2.0.10",
|
||||
"@types/webpack": "^4.41.38",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"avris-daemonise": "^0.0.2",
|
||||
"bootstrap": "^5.3.1",
|
||||
"clipboard": "^2.0.6",
|
||||
@ -89,6 +106,7 @@
|
||||
"csv-loader": "^3.0.3",
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-formatter-gitlab": "^5.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-jsonc": "^2.11.2",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
@ -107,6 +125,10 @@
|
||||
"sharp": "^0.31.3",
|
||||
"string-replace-loader": "^2.3.0",
|
||||
"suml-loader": "^0.1.1",
|
||||
"ts-jest": "^29.1.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vue-tsc": "^1.8.27",
|
||||
"webpack": "^4.47.0",
|
||||
"yaml-loader": "^0.8.0"
|
||||
},
|
||||
|
@ -1,8 +1,22 @@
|
||||
import Vue from 'vue';
|
||||
import { isGranted, parseUserJwt } from '../src/helpers.js';
|
||||
import cookieSettings from '../src/cookieSettings.js';
|
||||
import type { JwtPayload } from 'jsonwebtoken';
|
||||
import type { Store } from 'vuex';
|
||||
import { isGranted, parseUserJwt } from '../src/helpers.ts';
|
||||
import cookieSettings from '../src/cookieSettings.ts';
|
||||
import type { User } from '../src/user.ts';
|
||||
import type { RootState } from '../store/index.ts';
|
||||
|
||||
export default ({ app, store }) => {
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
$user(): User | null;
|
||||
$isGranted(area: string, locale?: string | null): boolean;
|
||||
$accounts(): void;
|
||||
$setToken(token: string): void;
|
||||
$removeToken(username?: string | null): void;
|
||||
}
|
||||
}
|
||||
|
||||
export default ({ app, store }: { app: Vue, store: Store<RootState> }): void => {
|
||||
const token = app.$cookies.get('token');
|
||||
if (token) {
|
||||
store.commit('setToken', token);
|
||||
@ -11,42 +25,42 @@ export default ({ app, store }) => {
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$user = (_) => store.state.user;
|
||||
Vue.prototype.$isGranted = (area = '', locale = null) => {
|
||||
return store.state.user &&
|
||||
store.state.user.authenticated &&
|
||||
Vue.prototype.$user = (): User | null => store.state.user;
|
||||
Vue.prototype.$isGranted = (area = '', locale = null): boolean => {
|
||||
return !!store.state.user &&
|
||||
!!store.state.user.authenticated &&
|
||||
isGranted(store.state.user, locale || app.$config.locale, area)
|
||||
;
|
||||
};
|
||||
|
||||
const getAccounts = (fallback = null) => {
|
||||
const getAccounts = (fallback: string | null = null): Record<string, JwtPayload> => {
|
||||
const tokens = (window.localStorage.getItem('account-tokens') || fallback || '').split('|').filter((x) => !!x);
|
||||
const accounts = {};
|
||||
const accounts: Record<string, JwtPayload> = {};
|
||||
for (const token of tokens) {
|
||||
const account = parseUserJwt(token);
|
||||
const account = parseUserJwt(token) as JwtPayload;
|
||||
if (account.username && account.authenticated) {
|
||||
accounts[account.username] = { token, account };
|
||||
}
|
||||
}
|
||||
return accounts;
|
||||
};
|
||||
const saveAccounts = (accounts) => {
|
||||
const saveAccounts = (accounts: Record<string, JwtPayload>): void => {
|
||||
store.commit('setAccounts', accounts);
|
||||
window.localStorage.setItem('account-tokens', Object.values(accounts).map((x) => x.token)
|
||||
.join('|'));
|
||||
};
|
||||
|
||||
Vue.prototype.$accounts = () => {
|
||||
Vue.prototype.$accounts = (): void => {
|
||||
saveAccounts(getAccounts(store.state.token));
|
||||
};
|
||||
Vue.prototype.$setToken = (token) => {
|
||||
Vue.prototype.$setToken = (token: string): void => {
|
||||
const accounts = getAccounts();
|
||||
|
||||
const usernameBefore = store.state.user?.username;
|
||||
|
||||
store.commit('setToken', token);
|
||||
if (token) {
|
||||
const account = parseUserJwt(token);
|
||||
const account = parseUserJwt(token) as JwtPayload;
|
||||
if (account.username && account.authenticated) {
|
||||
accounts[account.username] = { token, account };
|
||||
}
|
||||
@ -63,7 +77,7 @@ export default ({ app, store }) => {
|
||||
bc.postMessage(usernameAfter);
|
||||
}
|
||||
};
|
||||
Vue.prototype.$removeToken = (username = null) => {
|
||||
Vue.prototype.$removeToken = (username: string | null = null): void => {
|
||||
const accounts = getAccounts();
|
||||
|
||||
if (store.state.user) {
|
3
plugins/data.d.ts
vendored
Normal file
3
plugins/data.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare module '*/translations.suml' {
|
||||
export default unknown;
|
||||
}
|
@ -1,13 +1,42 @@
|
||||
import Vue from 'vue';
|
||||
import type { NuxtRuntimeConfig } from '@nuxt/types/config/runtime';
|
||||
import type { Store } from 'vuex';
|
||||
import { Translator } from '../src/translator.js';
|
||||
import { buildDict } from '../src/helpers.js';
|
||||
import { buildDict } from '../src/helpers.ts';
|
||||
import { DateTime, Settings } from 'luxon';
|
||||
import { decodeTime } from 'ulid';
|
||||
import type { Pronoun } from '../src/classes.ts';
|
||||
import type { LocaleDescription } from '../locale/locales.ts';
|
||||
import type { RootState } from '../store/index.ts';
|
||||
|
||||
import translations from '../data/translations.suml';
|
||||
import baseTranslations from '../locale/_base/translations.suml';
|
||||
|
||||
export default ({ app, store }) => {
|
||||
declare global {
|
||||
interface Window {
|
||||
fusetag: any;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
// properties from other dependencies
|
||||
router: any;
|
||||
$cookies: any;
|
||||
|
||||
$config: NuxtRuntimeConfig;
|
||||
$eventHub: Vue;
|
||||
$base: string;
|
||||
$translator: Translator;
|
||||
$t(key: string, params?: Record<string, string>, warn?: boolean): string;
|
||||
$te(key: string, fallback?: boolean): boolean;
|
||||
$translateForPronoun(str: string, pronoun: Pronoun): string;
|
||||
$locales: Record<string, LocaleDescription>;
|
||||
$loadScript(name: string, src: string): Promise<unknown>;
|
||||
}
|
||||
}
|
||||
|
||||
export default ({ app, store }: { app: Vue, store: Store<RootState> }): void => {
|
||||
Vue.prototype.$eventHub = new Vue();
|
||||
|
||||
Vue.prototype.$base = process.env.BASE_URL;
|
||||
@ -15,8 +44,8 @@ export default ({ app, store }) => {
|
||||
const translator = new Translator(translations, baseTranslations, app.$config);
|
||||
Vue.prototype.$translator = translator;
|
||||
app.$translator = translator; // it should be accessible like this from the previous line, but for some reason it's not, hence this ugly workaround
|
||||
Vue.prototype.$t = (key, params = {}, warn = false) => translator.translate(key, params, warn);
|
||||
Vue.prototype.$te = (key, fallback = false) => {
|
||||
Vue.prototype.$t = (key: string, params = {}, warn = false): string => translator.translate(key, params, warn);
|
||||
Vue.prototype.$te = (key: string, fallback = false): boolean => {
|
||||
if (translator.has(key)) {
|
||||
return true;
|
||||
}
|
||||
@ -25,7 +54,7 @@ export default ({ app, store }) => {
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Vue.prototype.$translateForPronoun = (str, pronoun) => {
|
||||
Vue.prototype.$translateForPronoun = (str: string, pronoun: Pronoun): string => {
|
||||
let translation = translator.translate(`flags.${str.replace(/ /g, '_').replace(/'/g, '*')}`, {}, false) || str;
|
||||
if (pronoun) {
|
||||
translation = pronoun.format(translation);
|
||||
@ -35,9 +64,9 @@ export default ({ app, store }) => {
|
||||
|
||||
Vue.prototype.$locales = buildDict(function* () {
|
||||
if (app.$config.locale !== '_') {
|
||||
yield [app.$config.locale, process.env.LOCALES[app.$config.locale]];
|
||||
yield [app.$config.locale, process.env.LOCALES![app.$config.locale]];
|
||||
}
|
||||
for (const [locale, localeDescription] of Object.entries(process.env.LOCALES)) {
|
||||
for (const [locale, localeDescription] of Object.entries(process.env.LOCALES!)) {
|
||||
if (locale !== app.$config.locale) {
|
||||
yield [locale, localeDescription];
|
||||
}
|
||||
@ -50,14 +79,15 @@ export default ({ app, store }) => {
|
||||
store.commit('showTranslationMode');
|
||||
}
|
||||
|
||||
Vue.prototype.$loadScript = (name, src, nonce = undefined) => {
|
||||
Vue.prototype.$loadScript = (name: string, src: string, nonce: string | undefined = undefined) => {
|
||||
if (!process.client || document.querySelectorAll(`script.${name}-script`).length > 0) {
|
||||
return new Promise((resolve) => {
|
||||
resolve();
|
||||
resolve(null);
|
||||
});
|
||||
}
|
||||
|
||||
let resolveFn; let rejectFn;
|
||||
let resolveFn: ((this: GlobalEventHandlers, event: Event) => any) | null = null;
|
||||
let rejectFn: OnErrorEventHandler = null;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
resolveFn = resolve;
|
||||
rejectFn = reject;
|
||||
@ -83,12 +113,12 @@ export default ({ app, store }) => {
|
||||
Settings.defaultLocale = 'en';
|
||||
}
|
||||
|
||||
Vue.prototype.$datetime = (timestamp) => {
|
||||
Vue.prototype.$datetime = (timestamp: number): string => {
|
||||
const dt = DateTime.fromSeconds(timestamp);
|
||||
return dt.toFormat('y-MM-dd HH:mm');
|
||||
};
|
||||
|
||||
Vue.prototype.$ulidTime = (ulid) => {
|
||||
Vue.prototype.$ulidTime = (ulid: string): number => {
|
||||
return decodeTime(ulid) / 1000;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { clearUrl } from '../src/helpers.js';
|
||||
import { clearUrl } from '../src/helpers.ts';
|
||||
|
||||
const LINK_PROVIDERS = {
|
||||
twitter: {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { mapState } from 'vuex';
|
||||
import zhConverter from 'zh_cn_zh_tw';
|
||||
import futurus from 'avris-futurus';
|
||||
import { escapeHtml } from '../src/helpers.js';
|
||||
import { escapeHtml } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
|
@ -13,7 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
head() {
|
||||
|
@ -227,7 +227,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -75,7 +75,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -72,7 +72,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app, route }) {
|
||||
|
@ -22,7 +22,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
head() {
|
||||
|
@ -46,7 +46,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -139,7 +139,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { DateTime } from 'luxon';
|
||||
import gm from 'avris-generator';
|
||||
import { min, max, closed, MONTHS, AREAS, TRANSFER_METHODS } from '../src/timesheets.js';
|
||||
|
@ -95,7 +95,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { DateTime } from 'luxon';
|
||||
import { min, max, MONTHS, PERIODS } from '../src/timesheets.js';
|
||||
|
||||
|
@ -131,7 +131,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deepSet, head } from '../src/helpers.js';
|
||||
import { deepSet, head } from '../src/helpers.ts';
|
||||
import Suml from 'suml';
|
||||
|
||||
export default {
|
||||
|
@ -42,7 +42,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -128,7 +128,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { socialProviders } from '../src/socialProviders.js';
|
||||
|
||||
export default {
|
||||
|
@ -64,7 +64,7 @@
|
||||
|
||||
<script>
|
||||
import { examples, pronouns, pronounLibrary } from '../src/data.js';
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -40,7 +40,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
function get_profile(route_part, param) {
|
||||
return ['GET', `/api/profile/${route_part}/{${param}}?version=2`, {
|
||||
|
@ -17,7 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, clearLinkedText } from '../src/helpers.js';
|
||||
import { head, clearLinkedText } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -16,7 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -28,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import parseMarkdown from '../src/parseMarkdown.js';
|
||||
import Columnist from 'avris-columnist';
|
||||
|
||||
|
@ -80,7 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { calendar } from '../src/calendar/calendar.js';
|
||||
import { Day } from '../src/calendar/helpers.js';
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { calendar } from '../src/calendar/calendar.js';
|
||||
import { Day } from '../src/calendar/helpers.js';
|
||||
|
||||
|
@ -211,7 +211,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { buildDict, head, shuffle } from '../src/helpers.js';
|
||||
import { buildDict, head, shuffle } from '../src/helpers.ts';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export default {
|
||||
|
@ -91,7 +91,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, groupBy } from '../src/helpers.js';
|
||||
import { head, groupBy } from '../src/helpers.ts';
|
||||
import { getContactLinks, getSocialLinks } from '../src/contact.js';
|
||||
|
||||
export default {
|
||||
|
@ -95,7 +95,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
<script>
|
||||
import EnglishTable from '../data/pronouns/EnglishTable.vue';
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
components: { EnglishTable },
|
||||
|
@ -51,7 +51,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
@ -19,7 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
@ -14,7 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import parseMarkdown from '../src/parseMarkdown.js';
|
||||
|
||||
export default {
|
||||
|
@ -34,7 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
head() {
|
||||
|
@ -19,7 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, clearLinkedText } from '../src/helpers.js';
|
||||
import { head, clearLinkedText } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
|
@ -115,9 +115,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, buildDict } from '../src/helpers.js';
|
||||
import { head, buildDict } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
import { Name } from '../src/classes.js';
|
||||
import { Name } from '../src/classes.ts';
|
||||
|
||||
export default {
|
||||
mixins: [hash],
|
||||
|
@ -33,7 +33,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import NounsNav from '../data/nouns/NounsNav.vue';
|
||||
import NounsExtra from '../data/nouns/NounsExtra.vue';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
@ -41,8 +41,8 @@
|
||||
|
||||
<script>
|
||||
import { people } from '../src/data.js';
|
||||
import { head } from '../src/helpers.js';
|
||||
import { SourceLibrary } from '../src/classes.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import { SourceLibrary } from '../src/classes.ts';
|
||||
|
||||
export default {
|
||||
async asyncData({ app }) {
|
||||
|
@ -254,7 +254,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, sleep } from '../src/helpers.js';
|
||||
import { head, sleep } from '../src/helpers.ts';
|
||||
import opinions from '../src/opinions.js';
|
||||
import mainPronoun from '../plugins/mainPronoun.js';
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
|
||||
export default {
|
||||
layout: 'basic',
|
||||
|
@ -352,7 +352,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head, buildList, buildDict, isValidLink } from '../src/helpers.js';
|
||||
import { head, buildList, buildDict, isValidLink } from '../src/helpers.ts';
|
||||
import { pronouns, pronounLibrary } from '../src/data.js';
|
||||
import { buildPronoun } from '../src/buildPronoun.js';
|
||||
import link from '../plugins/link.js';
|
||||
|
@ -117,10 +117,10 @@
|
||||
<script>
|
||||
import { examples, pronouns, pronounLibrary } from '../src/data.js';
|
||||
import { buildPronoun } from '../src/buildPronoun.js';
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import GrammarTables from '../data/pronouns/GrammarTables.vue';
|
||||
import LinkedText from '../components/LinkedText.vue';
|
||||
import { SourceLibrary } from '../src/classes.js';
|
||||
import { SourceLibrary } from '../src/classes.ts';
|
||||
|
||||
export default {
|
||||
components: { LinkedText, GrammarTables },
|
||||
|
@ -256,7 +256,7 @@
|
||||
|
||||
<script>
|
||||
import { examples, pronouns, pronounLibrary } from '../src/data.js';
|
||||
import { ExamplePart, Pronoun } from '../src/classes.js';
|
||||
import { ExamplePart, Pronoun } from '../src/classes.ts';
|
||||
import Compressor from '../src/compressor.js';
|
||||
import MORPHEMES from '../data/pronouns/morphemes.js';
|
||||
import { mapState } from 'vuex';
|
||||
|
@ -161,8 +161,8 @@
|
||||
|
||||
<script>
|
||||
import { pronouns, pronounLibrary } from '../src/data.js';
|
||||
import { Source, SourceLibrary } from '../src/classes.js';
|
||||
import { head } from '../src/helpers.js';
|
||||
import { Source, SourceLibrary } from '../src/classes.ts';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
@ -134,7 +134,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import spelling from '../plugins/spelling.js';
|
||||
|
||||
export default {
|
||||
|
@ -21,7 +21,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { head } from '../src/helpers.js';
|
||||
import { head } from '../src/helpers.ts';
|
||||
import hash from '../plugins/hash.js';
|
||||
|
||||
export default {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user