@learnpack/learnpack 5.0.54 → 5.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -12
- package/lib/commands/serve.d.ts +7 -0
- package/lib/commands/serve.js +277 -0
- package/lib/managers/server/routes.js +2 -0
- package/lib/utils/api.js +1 -1
- package/lib/utils/cloudStorage.d.ts +8 -0
- package/lib/utils/cloudStorage.js +17 -0
- package/oclif.manifest.json +1 -1
- package/package.json +4 -1
- package/src/commands/serve.ts +371 -0
- package/src/creator/README.md +54 -0
- package/src/creator/eslint.config.js +28 -0
- package/src/creator/index.html +13 -0
- package/src/creator/package-lock.json +4659 -0
- package/src/creator/package.json +41 -0
- package/src/creator/public/vite.svg +1 -0
- package/src/creator/src/App.css +42 -0
- package/src/creator/src/App.tsx +221 -0
- package/src/creator/src/assets/react.svg +1 -0
- package/src/creator/src/assets/svgs.tsx +88 -0
- package/src/creator/src/components/Loader.tsx +28 -0
- package/src/creator/src/components/Login.tsx +263 -0
- package/src/creator/src/components/SelectableCard.tsx +30 -0
- package/src/creator/src/components/StepWizard.tsx +77 -0
- package/src/creator/src/components/SyllabusEditor.tsx +431 -0
- package/src/creator/src/index.css +68 -0
- package/src/creator/src/main.tsx +19 -0
- package/src/creator/src/utils/configTypes.ts +122 -0
- package/src/creator/src/utils/constants.ts +2 -0
- package/src/creator/src/utils/lib.ts +36 -0
- package/src/creator/src/utils/rigo.ts +391 -0
- package/src/creator/src/utils/store.ts +78 -0
- package/src/creator/src/vite-env.d.ts +1 -0
- package/src/creator/tsconfig.app.json +26 -0
- package/src/creator/tsconfig.json +7 -0
- package/src/creator/tsconfig.node.json +24 -0
- package/src/creator/vite.config.ts +13 -0
- package/src/creatorDist/assets/index-D92OoEoU.js +23719 -0
- package/src/creatorDist/assets/index-tt9JBVY0.css +987 -0
- package/src/creatorDist/index.html +14 -0
- package/src/creatorDist/vite.svg +1 -0
- package/src/managers/server/routes.ts +3 -0
- package/src/ui/_app/app.css +1 -0
- package/src/ui/_app/app.js +3025 -0
- package/src/ui/_app/favicon.ico +0 -0
- package/src/ui/_app/index.html +109 -0
- package/src/ui/_app/index.html.backup +91 -0
- package/src/ui/_app/learnpack.svg +7 -0
- package/src/ui/_app/logo-192.png +0 -0
- package/src/ui/_app/logo-512.png +0 -0
- package/src/ui/_app/logo.png +0 -0
- package/src/ui/_app/manifest.webmanifest +21 -0
- package/src/ui/_app/sw.js +30 -0
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +1 -1
- package/src/utils/cloudStorage.ts +24 -0
- package/src/utils/convertCreds.js +30 -0
@@ -0,0 +1,391 @@
|
|
1
|
+
import { RIGOBOT_HOST } from "./constants"
|
2
|
+
import axios from "axios"
|
3
|
+
import frontMatter from "front-matter"
|
4
|
+
import { syllable } from "syllable"
|
5
|
+
|
6
|
+
import * as yaml from "js-yaml"
|
7
|
+
|
8
|
+
type TInteractiveCreationInputs = {
|
9
|
+
courseInfo: string
|
10
|
+
prevInteractions: string
|
11
|
+
}
|
12
|
+
export const interactiveCreation = async (
|
13
|
+
token: string,
|
14
|
+
inputs: TInteractiveCreationInputs
|
15
|
+
) => {
|
16
|
+
const response = await axios.post(
|
17
|
+
`${RIGOBOT_HOST}/v1/prompting/completion/390/`,
|
18
|
+
{
|
19
|
+
inputs: inputs,
|
20
|
+
include_purpose_objective: false,
|
21
|
+
execute_async: false,
|
22
|
+
},
|
23
|
+
{
|
24
|
+
headers: {
|
25
|
+
"Content-Type": "application/json",
|
26
|
+
Authorization: "Token " + token,
|
27
|
+
},
|
28
|
+
}
|
29
|
+
)
|
30
|
+
|
31
|
+
return response.data
|
32
|
+
}
|
33
|
+
|
34
|
+
type TCreateReadmeInputs = {
|
35
|
+
title: string
|
36
|
+
output_lang: string
|
37
|
+
list_of_exercises: string
|
38
|
+
tutorial_description: string
|
39
|
+
include_quiz: string
|
40
|
+
lesson_description: string
|
41
|
+
}
|
42
|
+
|
43
|
+
export const createReadme = async (
|
44
|
+
token: string,
|
45
|
+
inputs: TCreateReadmeInputs
|
46
|
+
) => {
|
47
|
+
try {
|
48
|
+
const response = await axios.post(
|
49
|
+
`${RIGOBOT_HOST}/v1/prompting/completion/423/`,
|
50
|
+
{
|
51
|
+
inputs,
|
52
|
+
include_purpose_objective: false,
|
53
|
+
execute_async: false,
|
54
|
+
},
|
55
|
+
{
|
56
|
+
headers: {
|
57
|
+
"Content-Type": "application/json",
|
58
|
+
Authorization: "Token " + token,
|
59
|
+
},
|
60
|
+
}
|
61
|
+
)
|
62
|
+
return response.data
|
63
|
+
} catch (error) {
|
64
|
+
console.error(error)
|
65
|
+
return null
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
type TCreateCodingReadmeInputs = {
|
70
|
+
tutorial_description: string
|
71
|
+
list_of_exercises: string
|
72
|
+
output_lang: string
|
73
|
+
title: string
|
74
|
+
lesson_description: string
|
75
|
+
}
|
76
|
+
export const createCodingReadme = async (
|
77
|
+
token: string,
|
78
|
+
inputs: TCreateCodingReadmeInputs
|
79
|
+
) => {
|
80
|
+
const response = await axios.post(
|
81
|
+
`${RIGOBOT_HOST}/v1/prompting/completion/489/`,
|
82
|
+
{ inputs, include_purpose_objective: false, execute_async: false },
|
83
|
+
{
|
84
|
+
headers: {
|
85
|
+
"Content-Type": "application/json",
|
86
|
+
Authorization: "Token " + token,
|
87
|
+
},
|
88
|
+
}
|
89
|
+
)
|
90
|
+
|
91
|
+
return response.data
|
92
|
+
}
|
93
|
+
|
94
|
+
type TReadmeCreatorInputs = {
|
95
|
+
tutorial_description: string
|
96
|
+
list_of_exercises: string
|
97
|
+
output_lang: string
|
98
|
+
title: string
|
99
|
+
lesson_description: string
|
100
|
+
kind: string
|
101
|
+
}
|
102
|
+
|
103
|
+
export const readmeCreator = async (
|
104
|
+
token: string,
|
105
|
+
inputs: TReadmeCreatorInputs
|
106
|
+
) => {
|
107
|
+
if (inputs.kind === "quiz" || inputs.kind === "read") {
|
108
|
+
const createReadmeInputs: TCreateReadmeInputs = {
|
109
|
+
title: inputs.title,
|
110
|
+
output_lang: inputs.output_lang,
|
111
|
+
list_of_exercises: inputs.list_of_exercises,
|
112
|
+
tutorial_description: inputs.tutorial_description,
|
113
|
+
include_quiz: inputs.kind === "quiz" ? "true" : "false",
|
114
|
+
lesson_description: inputs.lesson_description,
|
115
|
+
}
|
116
|
+
return createReadme(token, createReadmeInputs)
|
117
|
+
}
|
118
|
+
|
119
|
+
if (inputs.kind === "code") {
|
120
|
+
return createCodingReadme(token, {
|
121
|
+
title: inputs.title,
|
122
|
+
output_lang: inputs.output_lang,
|
123
|
+
list_of_exercises: inputs.list_of_exercises,
|
124
|
+
tutorial_description: inputs.tutorial_description,
|
125
|
+
lesson_description: inputs.lesson_description,
|
126
|
+
})
|
127
|
+
}
|
128
|
+
|
129
|
+
throw new Error("Invalid kind of lesson")
|
130
|
+
}
|
131
|
+
|
132
|
+
type TEstimateReadingTimeReturns = {
|
133
|
+
minutes: number
|
134
|
+
words: number
|
135
|
+
}
|
136
|
+
|
137
|
+
export const estimateReadingTime = (
|
138
|
+
text: string,
|
139
|
+
wordsPerMinute = 150
|
140
|
+
): TEstimateReadingTimeReturns => {
|
141
|
+
const words = text.trim().split(/\s+/).length
|
142
|
+
const minutes = words / wordsPerMinute
|
143
|
+
|
144
|
+
if (minutes < 1) {
|
145
|
+
if (words === 0)
|
146
|
+
return {
|
147
|
+
minutes: 1,
|
148
|
+
words,
|
149
|
+
}
|
150
|
+
} else {
|
151
|
+
return {
|
152
|
+
minutes,
|
153
|
+
words,
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
return {
|
158
|
+
minutes: 1,
|
159
|
+
words,
|
160
|
+
}
|
161
|
+
}
|
162
|
+
|
163
|
+
type TFKGLResult = {
|
164
|
+
text: string
|
165
|
+
fkgl: number
|
166
|
+
}
|
167
|
+
|
168
|
+
export function checkReadability(
|
169
|
+
markdown: string,
|
170
|
+
wordsPerMinute = 200,
|
171
|
+
maxMinutes = 1
|
172
|
+
): {
|
173
|
+
newMarkdown: string
|
174
|
+
exceedsThreshold: boolean
|
175
|
+
minutes: number
|
176
|
+
body: string
|
177
|
+
fkglResult: TFKGLResult
|
178
|
+
// readingEase: number
|
179
|
+
} {
|
180
|
+
const parsed = frontMatter(markdown)
|
181
|
+
|
182
|
+
const fkglResult = fleschKincaidGrade(parsed.body)
|
183
|
+
|
184
|
+
const readingTime = estimateReadingTime(parsed.body, wordsPerMinute)
|
185
|
+
|
186
|
+
// const readingEase = estimateReadingEase(parsed.body)
|
187
|
+
let attributes = parsed.attributes ? parsed.attributes : {}
|
188
|
+
|
189
|
+
if (typeof parsed.attributes !== "object") {
|
190
|
+
attributes = {}
|
191
|
+
}
|
192
|
+
|
193
|
+
const updatedAttributes = {
|
194
|
+
...attributes,
|
195
|
+
readingTime,
|
196
|
+
fkglResult: fkglResult.fkgl,
|
197
|
+
}
|
198
|
+
|
199
|
+
let yamlFrontMatter = ""
|
200
|
+
try {
|
201
|
+
yamlFrontMatter = yaml.dump(updatedAttributes).trim()
|
202
|
+
} catch {
|
203
|
+
// Console.error("Error dumping YAML front matter")
|
204
|
+
return {
|
205
|
+
newMarkdown: "",
|
206
|
+
exceedsThreshold: false,
|
207
|
+
minutes: 0,
|
208
|
+
body: "",
|
209
|
+
fkglResult,
|
210
|
+
// readingEase: 0,
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
const newMarkdown = `---\n${yamlFrontMatter}\n---\n\n${parsed.body}`
|
215
|
+
|
216
|
+
return {
|
217
|
+
newMarkdown,
|
218
|
+
exceedsThreshold: readingTime.minutes > maxMinutes,
|
219
|
+
minutes: readingTime.minutes,
|
220
|
+
body: parsed.body,
|
221
|
+
fkglResult,
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
export function extractImagesFromMarkdown(markdown: string) {
|
226
|
+
const imageRegex = /!\[([^\]]*)]\(([^)]+)\)/g
|
227
|
+
const images = []
|
228
|
+
let match
|
229
|
+
|
230
|
+
while ((match = imageRegex.exec(markdown)) !== null) {
|
231
|
+
const altText = match[1]
|
232
|
+
const url = match[2]
|
233
|
+
images.push({ alt: altText, url: url })
|
234
|
+
}
|
235
|
+
|
236
|
+
return images
|
237
|
+
}
|
238
|
+
|
239
|
+
export function estimateDuration(listOfSteps: string[]): number {
|
240
|
+
let duration = 0
|
241
|
+
|
242
|
+
for (const step of listOfSteps) {
|
243
|
+
if (step.includes("[READ:")) {
|
244
|
+
duration += 2
|
245
|
+
} else if (step.includes("[QUIZ:")) {
|
246
|
+
duration += 3
|
247
|
+
} else if (step.includes("[CODE:")) {
|
248
|
+
duration += 5
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
return duration
|
253
|
+
}
|
254
|
+
|
255
|
+
export function extractTextFromMarkdown(mdContent: string): string {
|
256
|
+
return mdContent
|
257
|
+
.replace(/!\[.*?]\(.*?\)/g, "") // Remove images
|
258
|
+
.replace(/\[.*?]\(.*?\)/g, "") // Remove links
|
259
|
+
.replace(/(```[\S\s]*?```|`.*?`)/g, "") // Remove inline & block code
|
260
|
+
.replace(/^#.*$/gm, "") // Remove headings
|
261
|
+
.replace(/(\*{1,2}|_{1,2})/g, "") // Remove bold/italic markers
|
262
|
+
.replace(/>\s?/g, "") // Remove blockquotes
|
263
|
+
.replace(/[*-]\s+/g, "") // Remove bullets from lists
|
264
|
+
.trim()
|
265
|
+
}
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Splits a paragraph into words and separates each word into syllables.
|
269
|
+
* @param paragraph The input paragraph.
|
270
|
+
* @returns An array of words, each split into syllables.
|
271
|
+
*/
|
272
|
+
export function splitIntoSyllables(paragraph: string): string[] {
|
273
|
+
const words = paragraph.split(/\s+/)
|
274
|
+
const syllables: string[] = []
|
275
|
+
|
276
|
+
for (const word of words) {
|
277
|
+
syllables.push(...splitWordIntoSyllables(word))
|
278
|
+
}
|
279
|
+
|
280
|
+
return syllables
|
281
|
+
}
|
282
|
+
|
283
|
+
/**
|
284
|
+
* Splits a word into its syllables using a basic estimation.
|
285
|
+
* @param word The word to split.
|
286
|
+
* @returns An array of syllables.
|
287
|
+
*/
|
288
|
+
export function splitWordIntoSyllables(word: string): string[] {
|
289
|
+
const syllableCount = syllable(word)
|
290
|
+
|
291
|
+
// Simple heuristic: Split word into equal parts (not perfect, better with a dictionary-based approach)
|
292
|
+
if (syllableCount <= 1) return [word]
|
293
|
+
|
294
|
+
const approxLength = Math.ceil(word.length / syllableCount)
|
295
|
+
const syllables: string[] = []
|
296
|
+
for (let i = 0; i < word.length; i += approxLength) {
|
297
|
+
// eslint-disable-next-line
|
298
|
+
syllables.push(word.substring(i, i + approxLength))
|
299
|
+
}
|
300
|
+
|
301
|
+
return syllables
|
302
|
+
}
|
303
|
+
|
304
|
+
/**
|
305
|
+
* Extracts words from a given paragraph.
|
306
|
+
* @param paragraph The input text.
|
307
|
+
* @returns An array of words.
|
308
|
+
*/
|
309
|
+
export function extractWords(paragraph: string): string[] {
|
310
|
+
const words = paragraph.match(/\b\w+\b/g) // Match words using regex
|
311
|
+
return words ? words : [] // Return words or an empty array if none found
|
312
|
+
}
|
313
|
+
|
314
|
+
/**
|
315
|
+
* Calculates the Flesch-Kincaid Grade Level (FKGL) for a given text.
|
316
|
+
* @param text The input paragraph.
|
317
|
+
* @returns The FKGL score.
|
318
|
+
*/
|
319
|
+
export function fleschKincaidGrade(text: string): TFKGLResult {
|
320
|
+
const processableText = extractTextFromMarkdown(text)
|
321
|
+
const words = extractWords(processableText)
|
322
|
+
const numWords = words.length
|
323
|
+
const numSentences = countSentences(processableText)
|
324
|
+
const numSyllables = words.reduce((total, word) => total + syllable(word), 0)
|
325
|
+
|
326
|
+
if (numWords === 0 || numSentences === 0) {
|
327
|
+
return {
|
328
|
+
text,
|
329
|
+
fkgl: 0,
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
const fkgl =
|
334
|
+
// eslint-disable-next-line
|
335
|
+
0.39 * (numWords / numSentences) + 11.8 * (numSyllables / numWords) - 15.59
|
336
|
+
|
337
|
+
return {
|
338
|
+
text,
|
339
|
+
fkgl: parseFloat(fkgl.toFixed(2)),
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
/**
|
344
|
+
* Counts the number of sentences in a given text.
|
345
|
+
* @param text The input paragraph.
|
346
|
+
* @returns The total number of sentences.
|
347
|
+
*/
|
348
|
+
export function countSentences(text: string): number {
|
349
|
+
const sentences = text
|
350
|
+
.split(/[!.?]+/)
|
351
|
+
.filter((sentence) => sentence.trim().length > 0)
|
352
|
+
return sentences.length
|
353
|
+
}
|
354
|
+
|
355
|
+
export function howManyDifficultParagraphs(
|
356
|
+
paragraphs: TFKGLResult[],
|
357
|
+
maxFKGL: number
|
358
|
+
): number {
|
359
|
+
return paragraphs.filter((paragraph) => paragraph.fkgl > maxFKGL).length
|
360
|
+
}
|
361
|
+
|
362
|
+
type TReduceReadmeInputs = {
|
363
|
+
lesson: string
|
364
|
+
number_of_words: string
|
365
|
+
expected_number_words: string
|
366
|
+
fkgl_results: string
|
367
|
+
expected_grade_level: string
|
368
|
+
}
|
369
|
+
export async function makeReadmeReadable(
|
370
|
+
rigoToken: string,
|
371
|
+
inputs: TReduceReadmeInputs
|
372
|
+
) {
|
373
|
+
try {
|
374
|
+
const response = await axios.post(
|
375
|
+
`${RIGOBOT_HOST}/v1/prompting/completion/588/`,
|
376
|
+
{ inputs, include_purpose_objective: false, execute_async: false },
|
377
|
+
{
|
378
|
+
headers: {
|
379
|
+
"Content-Type": "application/json",
|
380
|
+
Authorization: "Token " + rigoToken,
|
381
|
+
},
|
382
|
+
}
|
383
|
+
)
|
384
|
+
|
385
|
+
return response.data
|
386
|
+
} catch (error) {
|
387
|
+
console.error(error)
|
388
|
+
// Console.debug(error)
|
389
|
+
return null
|
390
|
+
}
|
391
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { create } from "zustand"
|
2
|
+
import { persist } from "zustand/middleware"
|
3
|
+
import { Lesson } from "../components/SyllabusEditor"
|
4
|
+
|
5
|
+
export type FormState = {
|
6
|
+
description: string
|
7
|
+
duration: number
|
8
|
+
targetAudience: string
|
9
|
+
hasContentIndex: boolean
|
10
|
+
contentIndex: string
|
11
|
+
isCompleted: boolean
|
12
|
+
currentStep: number
|
13
|
+
title?: string
|
14
|
+
}
|
15
|
+
|
16
|
+
type Auth = {
|
17
|
+
bcToken: string
|
18
|
+
rigoToken: string
|
19
|
+
userId: string
|
20
|
+
}
|
21
|
+
type Syllabus = {
|
22
|
+
lessons: Lesson[]
|
23
|
+
courseInfo: FormState
|
24
|
+
}
|
25
|
+
|
26
|
+
type Store = {
|
27
|
+
auth: Auth
|
28
|
+
formState: FormState
|
29
|
+
setAuth: (auth: Auth) => void
|
30
|
+
syllabus: Syllabus
|
31
|
+
setSyllabus: (syllabus: Partial<Syllabus>) => void
|
32
|
+
setFormState: (formState: Partial<FormState>) => void
|
33
|
+
}
|
34
|
+
|
35
|
+
const useStore = create<Store>()(
|
36
|
+
persist(
|
37
|
+
(set) => ({
|
38
|
+
auth: {
|
39
|
+
bcToken: "",
|
40
|
+
rigoToken: "",
|
41
|
+
userId: "",
|
42
|
+
},
|
43
|
+
formState: {
|
44
|
+
description: "",
|
45
|
+
duration: 0,
|
46
|
+
targetAudience: "",
|
47
|
+
hasContentIndex: false,
|
48
|
+
contentIndex: "",
|
49
|
+
isCompleted: false,
|
50
|
+
currentStep: 0,
|
51
|
+
},
|
52
|
+
setFormState: (formState: Partial<FormState>) =>
|
53
|
+
set((state) => ({ formState: { ...state.formState, ...formState } })),
|
54
|
+
|
55
|
+
syllabus: {
|
56
|
+
lessons: [],
|
57
|
+
courseInfo: {
|
58
|
+
description: "",
|
59
|
+
duration: 0,
|
60
|
+
targetAudience: "",
|
61
|
+
hasContentIndex: false,
|
62
|
+
contentIndex: "",
|
63
|
+
isCompleted: false,
|
64
|
+
currentStep: 0,
|
65
|
+
title: "",
|
66
|
+
},
|
67
|
+
},
|
68
|
+
setSyllabus: (syllabus: Partial<Syllabus>) =>
|
69
|
+
set((state) => ({ syllabus: { ...state.syllabus, ...syllabus } })),
|
70
|
+
setAuth: (auth: Auth) => set({ auth }),
|
71
|
+
}),
|
72
|
+
{
|
73
|
+
name: "syllabus-storage",
|
74
|
+
}
|
75
|
+
)
|
76
|
+
)
|
77
|
+
|
78
|
+
export default useStore
|
@@ -0,0 +1 @@
|
|
1
|
+
/// <reference types="vite/client" />
|
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
4
|
+
"target": "ES2020",
|
5
|
+
"useDefineForClassFields": true,
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
7
|
+
"module": "ESNext",
|
8
|
+
"skipLibCheck": true,
|
9
|
+
|
10
|
+
/* Bundler mode */
|
11
|
+
"moduleResolution": "bundler",
|
12
|
+
"allowImportingTsExtensions": true,
|
13
|
+
"isolatedModules": true,
|
14
|
+
"moduleDetection": "force",
|
15
|
+
"noEmit": true,
|
16
|
+
"jsx": "react-jsx",
|
17
|
+
|
18
|
+
/* Linting */
|
19
|
+
"strict": true,
|
20
|
+
"noUnusedLocals": true,
|
21
|
+
"noUnusedParameters": true,
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
23
|
+
"noUncheckedSideEffectImports": true
|
24
|
+
},
|
25
|
+
"include": ["src"]
|
26
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
4
|
+
"target": "ES2022",
|
5
|
+
"lib": ["ES2023"],
|
6
|
+
"module": "ESNext",
|
7
|
+
"skipLibCheck": true,
|
8
|
+
|
9
|
+
/* Bundler mode */
|
10
|
+
"moduleResolution": "bundler",
|
11
|
+
"allowImportingTsExtensions": true,
|
12
|
+
"isolatedModules": true,
|
13
|
+
"moduleDetection": "force",
|
14
|
+
"noEmit": true,
|
15
|
+
|
16
|
+
/* Linting */
|
17
|
+
"strict": true,
|
18
|
+
"noUnusedLocals": true,
|
19
|
+
"noUnusedParameters": true,
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
21
|
+
"noUncheckedSideEffectImports": true
|
22
|
+
},
|
23
|
+
"include": ["vite.config.ts"]
|
24
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { defineConfig } from "vite"
|
2
|
+
import react from "@vitejs/plugin-react-swc"
|
3
|
+
import tailwindcss from "@tailwindcss/vite"
|
4
|
+
|
5
|
+
// https://vite.dev/config/
|
6
|
+
export default defineConfig({
|
7
|
+
plugins: [react(), tailwindcss()],
|
8
|
+
base: "/creator/",
|
9
|
+
build: {
|
10
|
+
outDir: "../creatorDist",
|
11
|
+
emptyOutDir: true,
|
12
|
+
},
|
13
|
+
})
|