├── .browserslistrc
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── components
│ ├── molecules
│ │ ├── VChart.vue
│ │ └── VHeading.vue
│ ├── organisms
│ │ ├── ChartPane.vue
│ │ ├── MainPageHeader.vue
│ │ └── UserNameInput.vue
│ └── pages
│ │ └── MainPage.vue
├── libs
│ └── rating-chart.ts
├── main.ts
├── router.ts
├── shims-tsx.d.ts
├── shims-vue.d.ts
├── styles
│ └── simple-reset.css
├── types
│ ├── contest-history.ts
│ ├── contest-information.ts
│ └── submission.ts
└── vuex
│ ├── modules
│ ├── contest-history.ts
│ ├── contest-information.ts
│ └── submission.ts
│ └── store.ts
└── tsconfig.json
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{js,jsx,ts,tsx,vue}]
2 | indent_style = space
3 | indent_size = 2
4 | end_of_line = lf
5 | trim_trailing_whitespace = true
6 | insert_final_newline = true
7 | max_line_length = 100
8 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: ['plugin:vue/essential', '@vue/airbnb', '@vue/typescript'],
7 | rules: {
8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
10 | semi: 0,
11 | 'class-methods-use-this': 0,
12 | 'object-curly-newline': 0,
13 | 'import/prefer-default-export': 0,
14 | 'max-len': [1, 120],
15 | 'comma-dangle': 0,
16 | },
17 | parserOptions: {
18 | parser: '@typescript-eslint/parser',
19 | },
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "trailingComma": "es5",
4 | "tabWidth": 2,
5 | "semi": false,
6 | "singleQuote": true
7 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 havveFn
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # atcoder-charts
2 |
3 | [atcoder-charts](https://atcoder-charts.netlify.com/)
4 |
5 | > no longer maintained.
6 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app',
4 | ],
5 | };
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "atcoder-charts",
3 | "version": "1.0.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@types/chart.js": "^2.7.56",
12 | "axios": "^0.19.0",
13 | "chart.js": "^2.8.0",
14 | "chartjs-plugin-annotation": "^0.5.7",
15 | "core-js": "^2.6.5",
16 | "pug": "^2.0.4",
17 | "pug-loader": "^2.4.0",
18 | "pug-plain-loader": "^1.0.0",
19 | "vue": "^2.6.10",
20 | "vue-class-component": "^7.0.2",
21 | "vue-property-decorator": "^8.1.0",
22 | "vue-router": "^3.0.3",
23 | "vuex": "^3.1.1",
24 | "vuex-module-decorators": "^0.9.9"
25 | },
26 | "devDependencies": {
27 | "@vue/cli-plugin-babel": "^3.9.0",
28 | "@vue/cli-plugin-eslint": "^3.9.0",
29 | "@vue/cli-plugin-typescript": "^3.9.0",
30 | "@vue/cli-service": "^3.9.0",
31 | "@vue/eslint-config-airbnb": "^4.0.0",
32 | "@vue/eslint-config-typescript": "^4.0.0",
33 | "babel-eslint": "^10.0.1",
34 | "eslint": "^5.16.0",
35 | "eslint-plugin-vue": "^5.0.0",
36 | "sass": "^1.18.0",
37 | "sass-loader": "^7.1.0",
38 | "typescript": "^3.4.3",
39 | "vue-template-compiler": "^2.6.10"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tars0x9752/atcoder-charts/f0c7023616437bfcc583aa1030fce72cff9736d5/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | AtCoder Charts
11 |
12 |
13 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 | .app
3 | router-view
4 |
5 |
6 |
19 |
20 |
48 |
--------------------------------------------------------------------------------
/src/components/molecules/VChart.vue:
--------------------------------------------------------------------------------
1 |
2 | .v-chart(:style="styles")
3 | canvas(ref="canvas")
4 |
5 |
6 |
60 |
61 |
67 |
--------------------------------------------------------------------------------
/src/components/molecules/VHeading.vue:
--------------------------------------------------------------------------------
1 |
2 | .v-heading(:style="styles")
3 | h1.text {{ text }}
4 |
5 |
6 |
24 |
25 |
45 |
--------------------------------------------------------------------------------
/src/components/organisms/ChartPane.vue:
--------------------------------------------------------------------------------
1 |
2 | .organism-chart-pane(:style="styles")
3 | v-chart(
4 | :data="data"
5 | :options="options"
6 | :type="type"
7 | )
8 |
9 |
10 |
35 |
36 |
50 |
--------------------------------------------------------------------------------
/src/components/organisms/MainPageHeader.vue:
--------------------------------------------------------------------------------
1 |
2 | .organism-main-page-header
3 | .container
4 | h1.title {{ title }}
5 | .links
6 | a.link.github(
7 | target="_blank"
8 | :href="github"
9 | ) GitHub
10 | a.link.twitter(
11 | target="_blank"
12 | :href="twitter"
13 | ) Twitter
14 |
15 |
16 |
29 |
30 |
79 |
--------------------------------------------------------------------------------
/src/components/organisms/UserNameInput.vue:
--------------------------------------------------------------------------------
1 |
2 | .organism-user-name-input(:style="styles")
3 | .flex
4 | .focus-marker-base
5 | transition(name="focus-marker")
6 | .focus-marker(v-if="isFocused")
7 | .container
8 | input.input(
9 | ref="input"
10 | v-model="inputText"
11 | type="text"
12 | spellcheck="false"
13 | :placeholder="placeholder"
14 | :maxlength="maxlength"
15 | @mouseover="onHover"
16 | @mouseleave="onMouseLeave"
17 | @focus="onFocus"
18 | @blur="onBlur"
19 | @keydown.prevent.enter="onEnter"
20 | )
21 | .base-border
22 | .accent-border
23 | .button-container
24 | transition(name="button")
25 | .button(
26 | v-if="isFocused"
27 | @click="onEnter"
28 | )
29 | transition(name="fade")
30 | p.button-text(v-if="!isFetching") Fetch
31 | .stripe-loading(v-else)
32 |
33 |
34 |
136 |
137 |
310 |
--------------------------------------------------------------------------------
/src/components/pages/MainPage.vue:
--------------------------------------------------------------------------------
1 |
2 | .main-page
3 | main-page-header#top(
4 | :title="title"
5 | )
6 | user-name-input(
7 | :margin-top="usernameInputMarginTop"
8 | :input-width="usernameInputWidth"
9 | :is-fetching="isFetching"
10 | @input="onUsernameInput"
11 | )
12 | .charts(v-if="isChartPaneVisible")
13 | .rating-chart#rating-chart
14 | v-heading(:text="`Rating and Performance History`")
15 | chart-pane(
16 | :data="ratingChartData"
17 | :options="ratingChartOptions"
18 | :type="`line`"
19 | )
20 |
21 |
22 |
91 |
92 |
102 |
--------------------------------------------------------------------------------
/src/libs/rating-chart.ts:
--------------------------------------------------------------------------------
1 | import 'chartjs-plugin-annotation'
2 | import { ChartData, ChartOptions } from 'chart.js'
3 | import { ContestHistory } from '@/types/contest-history'
4 |
5 | export const createRatingChart = (contestHistory: ContestHistory) => {
6 | const ratedList = contestHistory.filter(contestResult => contestResult.isRated)
7 |
8 | const ratings = ratedList.map(rated => rated.newRating)
9 |
10 | const performances = ratedList.map(rated => rated.performance)
11 |
12 | const labels = ratedList.map(rated => `${rated.contestName}`)
13 |
14 | const data: ChartData = {
15 | labels,
16 | datasets: [
17 | {
18 | label: 'Rating',
19 | type: 'line',
20 | data: ratings,
21 | fill: false,
22 | lineTension: 0,
23 | backgroundColor: '#00a9a5',
24 | borderColor: '#00a9a5',
25 | borderWidth: 2,
26 | },
27 | {
28 | label: 'Performance',
29 | type: 'line',
30 | data: performances,
31 | fill: false,
32 | lineTension: 0.3,
33 | backgroundColor: '#00a9a5CC',
34 | borderColor: '#00a9a5CC',
35 | borderWidth: 1,
36 | borderDash: [10, 5],
37 | pointStyle: 'rectRot',
38 | pointRadius: 3,
39 | pointBackgroundColor: '#fff',
40 | },
41 | ],
42 | }
43 |
44 | const createRegion = (
45 | yMin: number,
46 | yMax: number,
47 | backgroundColor: string,
48 | borderColor: string
49 | ) => ({
50 | type: 'box',
51 | xScaleID: 'x0',
52 | yScaleID: 'y0',
53 | xMin: labels[0],
54 | xMax: labels[labels.length - 1],
55 | yMin,
56 | yMax,
57 | backgroundColor,
58 | borderColor,
59 | borderWidth: 0,
60 | })
61 |
62 | const brownRegion = createRegion(400, 799, '#AF81691A', '#AF816900')
63 |
64 | const grennRegion = createRegion(800, 1199, '#419D781A', '#419D7800')
65 |
66 | const lightBlueRegion = createRegion(1200, 1599, '#29CCF41A', '#29CCF400')
67 |
68 | const blueRegion = createRegion(1600, 1999, '#266DD31A', '#266DD300')
69 |
70 | const yellowRegion = createRegion(2000, 2399, '#FFED4C1A', '#FFED4C00')
71 |
72 | const orangeRegion = createRegion(2400, 2799, '#FF90001A', '#FF900000')
73 |
74 | const redRegion = createRegion(2800, 9999, '#ED254E1A', '#ED254E00')
75 |
76 | const options: ChartOptions = {
77 | annotation: {
78 | drawTime: 'beforeDatasetsDraw',
79 | annotations: [
80 | brownRegion,
81 | grennRegion,
82 | lightBlueRegion,
83 | blueRegion,
84 | yellowRegion,
85 | orangeRegion,
86 | redRegion,
87 | ],
88 | },
89 | responsive: true,
90 | maintainAspectRatio: true,
91 | legend: {
92 | display: false,
93 | },
94 | tooltips: {
95 | displayColors: false,
96 | callbacks: {
97 | afterLabel: tooltipItem => labels[tooltipItem.index!],
98 | },
99 | },
100 | hover: {
101 | mode: 'point',
102 | },
103 | scales: {
104 | xAxes: [
105 | {
106 | id: 'x0',
107 | ticks: {
108 | callback: (_, i) => `#${i + 1}`,
109 | },
110 | },
111 | ],
112 | yAxes: [
113 | {
114 | id: 'y0',
115 | },
116 | ],
117 | },
118 | } as ChartOptions
119 |
120 | return {
121 | ratingChartData: data,
122 | ratingChartOptions: options,
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from '@/App.vue'
3 | import router from '@/router'
4 | import store from '@/vuex/store'
5 |
6 | Vue.config.productionTip = false
7 |
8 | new Vue({
9 | router,
10 | store,
11 | render: h => h(App),
12 | }).$mount('#app')
13 |
--------------------------------------------------------------------------------
/src/router.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import MainPage from '@/components/pages/MainPage.vue'
4 |
5 | const Path = {
6 | MainPage: '/',
7 | }
8 |
9 | Vue.use(Router)
10 |
11 | export default new Router({
12 | routes: [
13 | {
14 | path: Path.MainPage,
15 | component: MainPage,
16 | },
17 | {
18 | path: '*',
19 | component: MainPage,
20 | },
21 | ],
22 | })
23 |
--------------------------------------------------------------------------------
/src/shims-tsx.d.ts:
--------------------------------------------------------------------------------
1 | import Vue, { VNode } from 'vue';
2 |
3 | declare global {
4 | namespace JSX {
5 | // tslint:disable no-empty-interface
6 | interface Element extends VNode {}
7 | // tslint:disable no-empty-interface
8 | interface ElementClass extends Vue {}
9 | interface IntrinsicElements {
10 | [elem: string]: any
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue';
3 |
4 | export default Vue;
5 | }
6 |
--------------------------------------------------------------------------------
/src/styles/simple-reset.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | font-size: 16px;
4 | }
5 |
6 | *,
7 | *:before,
8 | *:after {
9 | box-sizing: inherit;
10 | }
11 |
12 | body,
13 | div,
14 | h1,
15 | h2,
16 | h3,
17 | h4,
18 | h5,
19 | h6,
20 | p,
21 | span,
22 | ol,
23 | ul,
24 | input {
25 | margin: 0;
26 | padding: 0;
27 | outline: 0;
28 | font-weight: normal;
29 | }
30 |
31 | a {
32 | text-decoration: none;
33 | }
34 |
35 | ol,
36 | ul {
37 | list-style: none;
38 | }
39 |
40 | img {
41 | max-width: 100%;
42 | height: auto;
43 | }
44 |
--------------------------------------------------------------------------------
/src/types/contest-history.ts:
--------------------------------------------------------------------------------
1 | export interface RawContestResult {
2 | IsRated: boolean
3 | Place: number
4 | OldRating: number
5 | NewRating: number
6 | Performance: number
7 | InnerPerformance: number
8 | ContestScreenName: string
9 | ContestName: string
10 | EndTime: string
11 | }
12 |
13 | export interface ContestResult {
14 | isRated: boolean
15 | place: number
16 | oldRating: number
17 | newRating: number
18 | performance: number
19 | innerPerformance: number
20 | contestScreenName: string
21 | contestName: string
22 | endTime: string
23 | }
24 |
25 | export type RawContestHistory = RawContestResult[]
26 |
27 | export type ContestHistory = ContestResult[]
28 |
--------------------------------------------------------------------------------
/src/types/contest-information.ts:
--------------------------------------------------------------------------------
1 | /* eslint camelcase: 0 */
2 |
3 | export interface ContestInformation {
4 | id: string
5 | title: string
6 | start_epoch_second: number
7 | rate_change: string
8 | duration_second: number
9 | }
10 |
--------------------------------------------------------------------------------
/src/types/submission.ts:
--------------------------------------------------------------------------------
1 | /* eslint camelcase: 0 */
2 |
3 | export interface Submission {
4 | id: number
5 | epoch_second: number
6 | problem_id: string
7 | contest_id: string
8 | user_id: string
9 | language: string
10 | point: number
11 | length: number
12 | result: Result
13 | execution_time: number
14 | }
15 |
16 | export enum Result {
17 | AC = 'AC',
18 | WA = 'WA',
19 | TLE = 'TLE',
20 | CE = 'CE',
21 | RE = 'RE',
22 | }
23 |
--------------------------------------------------------------------------------
/src/vuex/modules/contest-history.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
3 | import store from '@/vuex/store'
4 | import {
5 | RawContestResult,
6 | ContestResult,
7 | ContestHistory,
8 | RawContestHistory,
9 | } from '@/types/contest-history'
10 |
11 | const netlifyFunctions = 'https://havefn-atcoder-api.netlify.app/.netlify/functions/'
12 |
13 | const httpClient = axios.create({
14 | baseURL: netlifyFunctions,
15 | })
16 |
17 | const formatRawData = (raw: RawContestResult) => {
18 | const {
19 | IsRated,
20 | Place,
21 | OldRating,
22 | NewRating,
23 | Performance,
24 | InnerPerformance,
25 | ContestScreenName,
26 | ContestName,
27 | EndTime,
28 | } = raw
29 |
30 | const camel: ContestResult = {
31 | isRated: IsRated,
32 | place: Place,
33 | oldRating: OldRating,
34 | newRating: NewRating,
35 | performance: Performance,
36 | innerPerformance: InnerPerformance,
37 | contestScreenName: ContestScreenName,
38 | contestName: ContestName,
39 | endTime: EndTime,
40 | }
41 |
42 | return camel
43 | }
44 |
45 | @Module({ dynamic: true, name: 'ContestHistoryModule', store, namespaced: true })
46 | class ContestHistoryModule extends VuexModule {
47 | private contestHistory: ContestHistory | null = null
48 |
49 | get getContestHistory(): ContestHistory | null {
50 | return this.contestHistory
51 | }
52 |
53 | @Mutation
54 | setContestHistory(contestHistory: ContestHistory | null) {
55 | this.contestHistory = contestHistory
56 | }
57 |
58 | @Action({ rawError: true })
59 | async fetchContestHistory(username: string) {
60 | if (!username) {
61 | throw new Error('username required')
62 | }
63 |
64 | const res = await httpClient.get(`/history?user=${username}`)
65 |
66 | const rawContestHistory: RawContestHistory = res.data
67 |
68 | const contestHistory: ContestHistory = rawContestHistory.map(formatRawData)
69 |
70 | this.setContestHistory(contestHistory)
71 | }
72 | }
73 |
74 | export const contestHistoryModule = getModule(ContestHistoryModule)
75 |
--------------------------------------------------------------------------------
/src/vuex/modules/contest-information.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
3 | import store from '@/vuex/store'
4 | import { ContestInformation } from '@/types/contest-information'
5 |
6 | const httpClient = axios.create({
7 | baseURL: 'https://kenkoooo.com/atcoder/resources/contests.json',
8 | })
9 |
10 | @Module({ dynamic: true, name: 'ContestInformationModule', store, namespaced: true })
11 | class ContestInformationModule extends VuexModule {
12 | private contestInformations: ContestInformation[] | null = null
13 |
14 | get getContestInformations(): ContestInformation[] | null {
15 | return this.contestInformations
16 | }
17 |
18 | @Mutation
19 | setContestInformations(contestInformations: ContestInformation[] | null) {
20 | this.contestInformations = contestInformations
21 | }
22 |
23 | @Action({ rawError: true })
24 | async fetchContestInformation() {
25 | const res = await httpClient.get('/')
26 |
27 | const contestInformations = res.data
28 |
29 | this.setContestInformations(contestInformations)
30 | }
31 | }
32 |
33 | export const contestInformationModule = getModule(ContestInformationModule)
34 |
--------------------------------------------------------------------------------
/src/vuex/modules/submission.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
3 | import store from '@/vuex/store'
4 | import { Submission } from '@/types/submission'
5 |
6 | const httpClient = axios.create({
7 | baseURL: 'https://kenkoooo.com/atcoder/atcoder-api',
8 | })
9 |
10 | @Module({ dynamic: true, name: 'SubmissionModule', store, namespaced: true })
11 | class SubmissionModule extends VuexModule {
12 | private submissions: Submission[] | null = null
13 |
14 | get getSubmissions(): Submission[] | null {
15 | return this.submissions
16 | }
17 |
18 | @Mutation
19 | setSubmissions(submissions: Submission[] | null) {
20 | this.submissions = submissions
21 | }
22 |
23 | @Action({ rawError: true })
24 | async fetchSubmissions(username: string) {
25 | if (!username) {
26 | throw new Error('username required')
27 | }
28 |
29 | const res = await httpClient.get('/results', {
30 | params: {
31 | user: username,
32 | },
33 | })
34 |
35 | const submissions: Submission[] = res.data
36 |
37 | this.setSubmissions(submissions)
38 | }
39 | }
40 |
41 | export const submissionModule = getModule(SubmissionModule)
42 |
--------------------------------------------------------------------------------
/src/vuex/store.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | type RootState = object
7 |
8 | export { RootState }
9 |
10 | export default new Vuex.Store({})
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "types": [
15 | "webpack-env"
16 | ],
17 | "paths": {
18 | "@/*": [
19 | "src/*"
20 | ]
21 | },
22 | "lib": [
23 | "esnext",
24 | "dom",
25 | "dom.iterable",
26 | "scripthost"
27 | ]
28 | },
29 | "include": [
30 | "src/**/*.ts",
31 | "src/**/*.tsx",
32 | "src/**/*.vue",
33 | "tests/**/*.ts",
34 | "tests/**/*.tsx"
35 | ],
36 | "exclude": [
37 | "node_modules"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------