@learnpack/learnpack 5.0.6 → 5.0.8

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.
Files changed (71) hide show
  1. package/README.md +17 -17
  2. package/bin/run +17 -17
  3. package/bin/run.cmd +3 -3
  4. package/lib/commands/audit.js +30 -21
  5. package/lib/commands/clean.js +3 -3
  6. package/lib/commands/download.js +3 -3
  7. package/lib/commands/init.js +29 -4
  8. package/lib/commands/login.js +3 -3
  9. package/lib/commands/logout.js +3 -3
  10. package/lib/utils/rigoActions.d.ts +5 -0
  11. package/lib/utils/rigoActions.js +15 -1
  12. package/oclif.manifest.json +1 -1
  13. package/package.json +152 -152
  14. package/src/commands/audit.ts +449 -443
  15. package/src/commands/clean.ts +29 -29
  16. package/src/commands/download.ts +61 -61
  17. package/src/commands/init.ts +40 -12
  18. package/src/commands/login.ts +42 -42
  19. package/src/commands/logout.ts +43 -43
  20. package/src/commands/test.ts +85 -85
  21. package/src/index.ts +1 -1
  22. package/src/managers/config/allowed_files.ts +29 -29
  23. package/src/managers/gitpod.ts +84 -84
  24. package/src/managers/server/index.ts +78 -78
  25. package/src/managers/telemetry.ts +353 -353
  26. package/src/managers/test.ts +83 -83
  27. package/src/models/audit.ts +16 -16
  28. package/src/models/config-manager.ts +23 -23
  29. package/src/models/counter.ts +11 -11
  30. package/src/models/errors.ts +22 -22
  31. package/src/models/exercise-obj.ts +29 -29
  32. package/src/models/file.ts +5 -5
  33. package/src/models/findings.ts +18 -18
  34. package/src/models/flags.ts +10 -10
  35. package/src/models/front-matter.ts +11 -11
  36. package/src/models/gitpod-data.ts +19 -19
  37. package/src/models/language.ts +4 -4
  38. package/src/models/package.ts +7 -7
  39. package/src/models/plugin-config.ts +17 -17
  40. package/src/models/success-types.ts +1 -1
  41. package/src/plugin/command/compile.ts +17 -17
  42. package/src/plugin/command/test.ts +30 -30
  43. package/src/plugin/index.ts +6 -6
  44. package/src/plugin/plugin.ts +94 -94
  45. package/src/plugin/utils.ts +87 -87
  46. package/src/types/node-fetch.d.ts +1 -1
  47. package/src/ui/download.ts +71 -71
  48. package/src/utils/BaseCommand.ts +48 -48
  49. package/src/utils/SessionCommand.ts +43 -43
  50. package/src/utils/audit.ts +393 -393
  51. package/src/utils/errors.ts +117 -117
  52. package/src/utils/exercisesQueue.ts +51 -51
  53. package/src/utils/fileQueue.ts +199 -199
  54. package/src/utils/misc.ts +23 -23
  55. package/src/utils/osOperations.ts +79 -79
  56. package/src/utils/rigoActions.ts +27 -0
  57. package/src/utils/templates/gitignore.txt +19 -19
  58. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +24 -24
  59. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +24 -24
  60. package/src/utils/templates/incremental/.vscode/schema.json +121 -121
  61. package/src/utils/templates/incremental/.vscode/settings.json +13 -13
  62. package/src/utils/templates/incremental/README.ejs +4 -4
  63. package/src/utils/templates/incremental/README.es.ejs +4 -4
  64. package/src/utils/templates/isolated/.vscode/schema.json +121 -121
  65. package/src/utils/templates/isolated/.vscode/settings.json +13 -13
  66. package/src/utils/templates/isolated/README.ejs +4 -4
  67. package/src/utils/templates/isolated/README.es.ejs +4 -4
  68. package/src/utils/templates/no-grading/README.ejs +4 -4
  69. package/src/utils/templates/no-grading/README.es.ejs +4 -4
  70. package/src/utils/validators.ts +18 -18
  71. package/src/utils/watcher.ts +27 -27
@@ -1,29 +1,29 @@
1
- // import {flags} from '@oclif/command'
2
- import Console from "../utils/console"
3
- import SessionCommand from "../utils/SessionCommand"
4
-
5
- class CleanCommand extends SessionCommand {
6
- static description = `Clean the configuration object
7
- ...
8
- Extra documentation goes here
9
- `
10
-
11
- static flags: any = {
12
- // name: flags.string({char: 'n', description: 'name to print'}),
13
- }
14
-
15
- async init() {
16
- const { flags } = this.parse(CleanCommand)
17
- await this.initSession(flags)
18
- }
19
-
20
- async run() {
21
- const { flags } = this.parse(CleanCommand)
22
-
23
- this.configManager?.clean()
24
-
25
- Console.success("Package cleaned successfully, ready to publish")
26
- }
27
- }
28
-
29
- export default CleanCommand
1
+ // import {flags} from '@oclif/command'
2
+ import Console from "../utils/console"
3
+ import SessionCommand from "../utils/SessionCommand"
4
+
5
+ class CleanCommand extends SessionCommand {
6
+ static description = `Clean the configuration object
7
+ ...
8
+ Extra documentation goes here
9
+ `
10
+
11
+ static flags: any = {
12
+ // name: flags.string({char: 'n', description: 'name to print'}),
13
+ }
14
+
15
+ async init() {
16
+ const { flags } = this.parse(CleanCommand)
17
+ await this.initSession(flags)
18
+ }
19
+
20
+ async run() {
21
+ const { flags } = this.parse(CleanCommand)
22
+
23
+ this.configManager?.clean()
24
+
25
+ Console.success("Package cleaned successfully, ready to publish")
26
+ }
27
+ }
28
+
29
+ export default CleanCommand
@@ -1,61 +1,61 @@
1
- import { Command /* , flags */ } from "@oclif/command"
2
- // import fetch from 'node-fetch'
3
- import { clone } from "../managers/file"
4
- import Console from "../utils/console"
5
- import api from "../utils/api"
6
- import { askPackage } from "../ui/download"
7
- // const BaseCommand = require('../utils/BaseCommand');
8
-
9
- class DownloadCommand extends Command {
10
- static description = `Describe the command here
11
- ...
12
- Extra documentation goes here
13
- `
14
- static flags: any = {
15
- // name: flags.string({char: 'n', description: 'name to print'}),
16
- }
17
-
18
- static args = [
19
- {
20
- name: "package", // name of arg to show in help and reference with args[name]
21
- required: false, // make the arg required with `required: true`
22
- description:
23
- "The unique string that identifies this package on learnpack", // help description
24
- hidden: false, // hide this arg from help
25
- },
26
- ]
27
- // async init() {
28
- // const {flags} = this.parse(DownloadCommand)
29
- // await this.initSession(flags)
30
- // }
31
-
32
- async run() {
33
- const { /* flags, */ args } = this.parse(DownloadCommand)
34
- // start watching for file changes
35
- let _package: string = args.package
36
- if (!_package) {
37
- _package = (await askPackage()) as string
38
- }
39
-
40
- if (!_package) {
41
- return null
42
- }
43
-
44
- try {
45
- const packageInfo = await api.getAllPackages({ slug: _package })
46
- if (packageInfo.results.length === 0)
47
- Console.error(`Package ${_package} not found`)
48
- else
49
- clone(packageInfo.results[0].repository)
50
- .then(_result => {
51
- Console.success("Successfully downloaded")
52
- Console.info(
53
- `You can now CD into the folder like this: $ cd ${_package}`
54
- )
55
- })
56
- .catch(error => Console.error(error.message || error))
57
- } catch {}
58
- }
59
- }
60
-
61
- export default DownloadCommand
1
+ import { Command /* , flags */ } from "@oclif/command"
2
+ // import fetch from 'node-fetch'
3
+ import { clone } from "../managers/file"
4
+ import Console from "../utils/console"
5
+ import api from "../utils/api"
6
+ import { askPackage } from "../ui/download"
7
+ // const BaseCommand = require('../utils/BaseCommand');
8
+
9
+ class DownloadCommand extends Command {
10
+ static description = `Describe the command here
11
+ ...
12
+ Extra documentation goes here
13
+ `
14
+ static flags: any = {
15
+ // name: flags.string({char: 'n', description: 'name to print'}),
16
+ }
17
+
18
+ static args = [
19
+ {
20
+ name: "package", // name of arg to show in help and reference with args[name]
21
+ required: false, // make the arg required with `required: true`
22
+ description:
23
+ "The unique string that identifies this package on learnpack", // help description
24
+ hidden: false, // hide this arg from help
25
+ },
26
+ ]
27
+ // async init() {
28
+ // const {flags} = this.parse(DownloadCommand)
29
+ // await this.initSession(flags)
30
+ // }
31
+
32
+ async run() {
33
+ const { /* flags, */ args } = this.parse(DownloadCommand)
34
+ // start watching for file changes
35
+ let _package: string = args.package
36
+ if (!_package) {
37
+ _package = (await askPackage()) as string
38
+ }
39
+
40
+ if (!_package) {
41
+ return null
42
+ }
43
+
44
+ try {
45
+ const packageInfo = await api.getAllPackages({ slug: _package })
46
+ if (packageInfo.results.length === 0)
47
+ Console.error(`Package ${_package} not found`)
48
+ else
49
+ clone(packageInfo.results[0].repository)
50
+ .then(_result => {
51
+ Console.success("Successfully downloaded")
52
+ Console.info(
53
+ `You can now CD into the folder like this: $ cd ${_package}`
54
+ )
55
+ })
56
+ .catch(error => Console.error(error.message || error))
57
+ } catch {}
58
+ }
59
+ }
60
+
61
+ export default DownloadCommand
@@ -17,6 +17,7 @@ import {
17
17
  getExercisesNames,
18
18
  generateImage,
19
19
  downloadImage,
20
+ generateCourseIntroduction,
20
21
  } from "../utils/rigoActions"
21
22
 
22
23
  const slugify = (text: string) => {
@@ -52,6 +53,21 @@ function getFilenameFromUrl(url: string) {
52
53
  return path.basename(url)
53
54
  }
54
55
 
56
+ async function createPreviewReadme(
57
+ tutorialDir: string,
58
+ packageInfo: PackageInfo,
59
+ rigoToken: string,
60
+ readmeContents: string[]
61
+ ) {
62
+ const readmeFilename = `README.md`
63
+
64
+ const readmeContent = await generateCourseIntroduction(rigoToken, {
65
+ course_title: packageInfo.title.us,
66
+ lessons_context: readmeContents.join("\n"),
67
+ })
68
+ fs.writeFileSync(path.join(tutorialDir, readmeFilename), readmeContent.answer)
69
+ }
70
+
55
71
  type PackageInfo = {
56
72
  grading: string
57
73
  difficulty: string
@@ -213,6 +229,10 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
213
229
  "Images generated successfully! 🎉 Your tutorial will be ready soon!"
214
230
  )
215
231
 
232
+ Console.info("Creating preview readme...")
233
+
234
+ await createPreviewReadme(tutorialDir, packageInfo, rigoToken, readmeContents)
235
+
216
236
  return true
217
237
  }
218
238
 
@@ -334,18 +354,26 @@ class InitComand extends BaseCommand {
334
354
  // Creating README files
335
355
  for (const language of languages) {
336
356
  const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`
337
- const readmeTemplatePath = path.resolve(
338
- templatesDir,
339
- `${readmeFilename}.ejs`
340
- )
341
- const readmeContent = eta.render(
342
- fs.readFileSync(readmeTemplatePath, "utf-8"),
343
- packageInfo
344
- )
345
- fs.writeFileSync(
346
- path.join(tutorialDir, `${readmeFilename}.md`),
347
- readmeContent
348
- )
357
+ // const readmeTemplatePath = path.resolve(
358
+ // templatesDir,
359
+ // `${readmeFilename}.ejs`
360
+ // )
361
+
362
+ // const readmeObject = {
363
+ // title: packageInfo.title.us,
364
+ // description: packageInfo.description.us,
365
+ // grading: packageInfo.grading,
366
+ // difficulty: packageInfo.difficulty,
367
+ // duration: packageInfo.duration,
368
+ // }
369
+ // const readmeContent = eta.render(
370
+ // fs.readFileSync(readmeTemplatePath, "utf-8"),
371
+ // readmeObject
372
+ // )
373
+ // fs.writeFileSync(
374
+ // path.join(tutorialDir, `${readmeFilename}.md`),
375
+ // readmeContent
376
+ // )
349
377
  if (fs.existsSync(path.join(tutorialDir, `${readmeFilename}.ejs`)))
350
378
  fs.removeSync(path.join(tutorialDir, `${readmeFilename}.ejs`))
351
379
  }
@@ -1,42 +1,42 @@
1
- import SessionCommand from "../utils/SessionCommand"
2
- import SessionManager from "../managers/session"
3
- import Console from "../utils/console"
4
-
5
- class LoginCommand extends SessionCommand {
6
- static description = `Describe the command here
7
- ...
8
- Extra documentation goes here
9
- `
10
-
11
- static flags: any = {
12
- // name: flags.string({char: 'n', description: 'name to print'}),
13
- }
14
-
15
- static args = [
16
- {
17
- name: "package", // name of arg to show in help and reference with args[name]
18
- required: false, // make the arg required with `required: true`
19
- description:
20
- "The unique string that identifies this package on learnpack", // help description
21
- hidden: false, // hide this arg from help
22
- },
23
- ]
24
-
25
- async init() {
26
- const { flags } = this.parse(LoginCommand)
27
- await this.initSession(flags)
28
- }
29
-
30
- async run() {
31
- /* const {flags, args} = */ this.parse(LoginCommand)
32
-
33
- try {
34
- await SessionManager.login()
35
- } catch (error) {
36
- Console.error("Error trying to authenticate")
37
- Console.error((error as TypeError).message || (error as string))
38
- }
39
- }
40
- }
41
-
42
- export default LoginCommand
1
+ import SessionCommand from "../utils/SessionCommand"
2
+ import SessionManager from "../managers/session"
3
+ import Console from "../utils/console"
4
+
5
+ class LoginCommand extends SessionCommand {
6
+ static description = `Describe the command here
7
+ ...
8
+ Extra documentation goes here
9
+ `
10
+
11
+ static flags: any = {
12
+ // name: flags.string({char: 'n', description: 'name to print'}),
13
+ }
14
+
15
+ static args = [
16
+ {
17
+ name: "package", // name of arg to show in help and reference with args[name]
18
+ required: false, // make the arg required with `required: true`
19
+ description:
20
+ "The unique string that identifies this package on learnpack", // help description
21
+ hidden: false, // hide this arg from help
22
+ },
23
+ ]
24
+
25
+ async init() {
26
+ const { flags } = this.parse(LoginCommand)
27
+ await this.initSession(flags)
28
+ }
29
+
30
+ async run() {
31
+ /* const {flags, args} = */ this.parse(LoginCommand)
32
+
33
+ try {
34
+ await SessionManager.login()
35
+ } catch (error) {
36
+ Console.error("Error trying to authenticate")
37
+ Console.error((error as TypeError).message || (error as string))
38
+ }
39
+ }
40
+ }
41
+
42
+ export default LoginCommand
@@ -1,43 +1,43 @@
1
- // import {Command, flags} from '@oclif/command'
2
- // import { prompt } from "enquirer"
3
- // import fetch from 'node-fetch'
4
- import SessionCommand from "../utils/SessionCommand"
5
- import SessionManager from "../managers/session"
6
- // import Console from '../utils/console'
7
- // import { replace } from 'node-emoji'
8
- // import { validURL } from "../utils/validators"
9
- // const BaseCommand from '../utils/BaseCommand');
10
-
11
- class LogoutCommand extends SessionCommand {
12
- static description = `Describe the command here
13
- ...
14
- Extra documentation goes here
15
- `
16
-
17
- static flags: any = {
18
- // name: flags.string({char: 'n', description: 'name to print'}),
19
- }
20
-
21
- static args = [
22
- {
23
- name: "package", // name of arg to show in help and reference with args[name]
24
- required: false, // make the arg required with `required: true`
25
- description:
26
- "The unique string that identifies this package on learnpack", // help description
27
- hidden: false, // hide this arg from help
28
- },
29
- ]
30
-
31
- async init() {
32
- const { flags } = this.parse(LogoutCommand)
33
- await this.initSession(flags)
34
- }
35
-
36
- async run() {
37
- // const {flags, args} = this.parse(LogoutCommand)
38
-
39
- SessionManager.destroy()
40
- }
41
- }
42
-
43
- export default LogoutCommand
1
+ // import {Command, flags} from '@oclif/command'
2
+ // import { prompt } from "enquirer"
3
+ // import fetch from 'node-fetch'
4
+ import SessionCommand from "../utils/SessionCommand"
5
+ import SessionManager from "../managers/session"
6
+ // import Console from '../utils/console'
7
+ // import { replace } from 'node-emoji'
8
+ // import { validURL } from "../utils/validators"
9
+ // const BaseCommand from '../utils/BaseCommand');
10
+
11
+ class LogoutCommand extends SessionCommand {
12
+ static description = `Describe the command here
13
+ ...
14
+ Extra documentation goes here
15
+ `
16
+
17
+ static flags: any = {
18
+ // name: flags.string({char: 'n', description: 'name to print'}),
19
+ }
20
+
21
+ static args = [
22
+ {
23
+ name: "package", // name of arg to show in help and reference with args[name]
24
+ required: false, // make the arg required with `required: true`
25
+ description:
26
+ "The unique string that identifies this package on learnpack", // help description
27
+ hidden: false, // hide this arg from help
28
+ },
29
+ ]
30
+
31
+ async init() {
32
+ const { flags } = this.parse(LogoutCommand)
33
+ await this.initSession(flags)
34
+ }
35
+
36
+ async run() {
37
+ // const {flags, args} = this.parse(LogoutCommand)
38
+
39
+ SessionManager.destroy()
40
+ }
41
+ }
42
+
43
+ export default LogoutCommand
@@ -1,85 +1,85 @@
1
- import Console from "../utils/console"
2
- import SessionCommand from "../utils/SessionCommand"
3
- import socket from "../managers/socket"
4
-
5
- import createServer from "../managers/server"
6
- import ExercisesQueue from "../utils/exercisesQueue"
7
- import { IExercise } from "../models/exercise-obj"
8
-
9
- class TestCommand extends SessionCommand {
10
- async init() {
11
- const { flags } = this.parse(TestCommand)
12
- await this.initSession(flags)
13
- }
14
-
15
- async run() {
16
- const {
17
- args: { exerciseSlug },
18
- } = this.parse(TestCommand)
19
-
20
- // Build exercises index
21
- this.configManager?.buildIndex()
22
-
23
- let exercises: IExercise[] | undefined = []
24
-
25
- // test all exercises
26
- !exerciseSlug ?
27
- (exercises = this.configManager?.getAllExercises()) :
28
- (exercises = [this.configManager!.getExercise(exerciseSlug)])
29
-
30
- const exercisesQueue = new ExercisesQueue(exercises)
31
-
32
- const configObject = this.configManager?.get()
33
-
34
- let hasFailed = false
35
- let failedTestsCount = 0
36
- let successTestsCount = 0
37
- const testsToRunCount = exercisesQueue.size()
38
-
39
- configObject!.config!.testingFinishedCallback = ({ result }) => {
40
- if (result === "failed") {
41
- hasFailed = true
42
- failedTestsCount++
43
- } else {
44
- successTestsCount++
45
- }
46
-
47
- if (exercisesQueue.isEmpty()) {
48
- Console.info(
49
- `${testsToRunCount} test${testsToRunCount > 1 ? "s" : ""} runned`
50
- )
51
- Console.success(
52
- `${successTestsCount} test${successTestsCount > 1 ? "s" : ""} passed`
53
- )
54
- Console.error(
55
- `${failedTestsCount} test${failedTestsCount > 1 ? "s" : ""} failed`
56
- )
57
-
58
- process.exit(hasFailed ? 1 : 0)
59
- } else {
60
- exercisesQueue.pop()!.test!(this.config, config!, socket)
61
- }
62
- }
63
-
64
- const config = configObject?.config
65
-
66
- const server = await createServer(configObject!, this.configManager!, true)
67
-
68
- socket.start(config!, server, true)
69
-
70
- exercisesQueue.pop()!.test!(this.config, config!, socket)
71
- }
72
- }
73
-
74
- TestCommand.description = `Test exercises`
75
-
76
- TestCommand.args = [
77
- {
78
- name: "exerciseSlug",
79
- required: false,
80
- description: "The name of the exercise to test",
81
- hidden: false,
82
- },
83
- ]
84
-
85
- export default TestCommand
1
+ import Console from "../utils/console"
2
+ import SessionCommand from "../utils/SessionCommand"
3
+ import socket from "../managers/socket"
4
+
5
+ import createServer from "../managers/server"
6
+ import ExercisesQueue from "../utils/exercisesQueue"
7
+ import { IExercise } from "../models/exercise-obj"
8
+
9
+ class TestCommand extends SessionCommand {
10
+ async init() {
11
+ const { flags } = this.parse(TestCommand)
12
+ await this.initSession(flags)
13
+ }
14
+
15
+ async run() {
16
+ const {
17
+ args: { exerciseSlug },
18
+ } = this.parse(TestCommand)
19
+
20
+ // Build exercises index
21
+ this.configManager?.buildIndex()
22
+
23
+ let exercises: IExercise[] | undefined = []
24
+
25
+ // test all exercises
26
+ !exerciseSlug ?
27
+ (exercises = this.configManager?.getAllExercises()) :
28
+ (exercises = [this.configManager!.getExercise(exerciseSlug)])
29
+
30
+ const exercisesQueue = new ExercisesQueue(exercises)
31
+
32
+ const configObject = this.configManager?.get()
33
+
34
+ let hasFailed = false
35
+ let failedTestsCount = 0
36
+ let successTestsCount = 0
37
+ const testsToRunCount = exercisesQueue.size()
38
+
39
+ configObject!.config!.testingFinishedCallback = ({ result }) => {
40
+ if (result === "failed") {
41
+ hasFailed = true
42
+ failedTestsCount++
43
+ } else {
44
+ successTestsCount++
45
+ }
46
+
47
+ if (exercisesQueue.isEmpty()) {
48
+ Console.info(
49
+ `${testsToRunCount} test${testsToRunCount > 1 ? "s" : ""} runned`
50
+ )
51
+ Console.success(
52
+ `${successTestsCount} test${successTestsCount > 1 ? "s" : ""} passed`
53
+ )
54
+ Console.error(
55
+ `${failedTestsCount} test${failedTestsCount > 1 ? "s" : ""} failed`
56
+ )
57
+
58
+ process.exit(hasFailed ? 1 : 0)
59
+ } else {
60
+ exercisesQueue.pop()!.test!(this.config, config!, socket)
61
+ }
62
+ }
63
+
64
+ const config = configObject?.config
65
+
66
+ const server = await createServer(configObject!, this.configManager!, true)
67
+
68
+ socket.start(config!, server, true)
69
+
70
+ exercisesQueue.pop()!.test!(this.config, config!, socket)
71
+ }
72
+ }
73
+
74
+ TestCommand.description = `Test exercises`
75
+
76
+ TestCommand.args = [
77
+ {
78
+ name: "exerciseSlug",
79
+ required: false,
80
+ description: "The name of the exercise to test",
81
+ hidden: false,
82
+ },
83
+ ]
84
+
85
+ export default TestCommand
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export * from '@oclif/command'
1
+ export * from '@oclif/command'
@@ -1,29 +1,29 @@
1
- const extensions = {
2
- extensions: [
3
- "py",
4
- "java",
5
- "py",
6
- "ruby",
7
- "html",
8
- "css",
9
- "htm",
10
- "php", // images
11
- "js",
12
- "jsx",
13
- "ts", // images
14
- "sh",
15
- "bash", // images
16
- "json",
17
- "yml",
18
- "yaml",
19
- "csv",
20
- "xml", // file storage extensions
21
- "txt",
22
- "text",
23
- "markdown",
24
- "readme", // compressed files
25
- ],
26
- names: ["package.json", "package-lock.json"],
27
- }
28
-
29
- export default extensions
1
+ const extensions = {
2
+ extensions: [
3
+ "py",
4
+ "java",
5
+ "py",
6
+ "ruby",
7
+ "html",
8
+ "css",
9
+ "htm",
10
+ "php", // images
11
+ "js",
12
+ "jsx",
13
+ "ts", // images
14
+ "sh",
15
+ "bash", // images
16
+ "json",
17
+ "yml",
18
+ "yaml",
19
+ "csv",
20
+ "xml", // file storage extensions
21
+ "txt",
22
+ "text",
23
+ "markdown",
24
+ "readme", // compressed files
25
+ ],
26
+ names: ["package.json", "package-lock.json"],
27
+ }
28
+
29
+ export default extensions