@w5s/mrm-preset 1.0.0-alpha.9 → 1.0.0

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 (53) hide show
  1. package/.turbo/turbo-build.log +6 -1
  2. package/.turbo/turbo-docs.log +9 -43
  3. package/.turbo/turbo-format.log +6 -0
  4. package/.turbo/turbo-lint.log +6 -52
  5. package/.turbo/turbo-prepare.log +1 -0
  6. package/.turbo/turbo-test.log +28 -21
  7. package/CHANGELOG.md +186 -42
  8. package/README.md +7 -7
  9. package/bootstrap/README.md +1 -1
  10. package/bootstrap/index.js +14 -38
  11. package/ci/_gitlab/AutoDevops.gitlab-ci.yml +1 -2
  12. package/ci/_gitlab/AutoDevopsInclude.gitlab-ci.yml +19 -19
  13. package/ci/_gitlab/Renovate.gitlab-ci.yml +6 -6
  14. package/ci/github.js +53 -0
  15. package/ci/gitlab.js +1 -2
  16. package/ci/index.js +7 -2
  17. package/commitlint/index.js +8 -2
  18. package/config.json +2 -1
  19. package/contributing/index.js +1 -1
  20. package/core/commitlint.js +5 -5
  21. package/core/cspell.js +2 -11
  22. package/core/eslint.js +25 -6
  23. package/core/git.js +4 -23
  24. package/core/githooks.js +13 -21
  25. package/core/githubCI.js +56 -0
  26. package/core/jest.js +26 -36
  27. package/core/jsonFile.js +8 -7
  28. package/core/lintStaged.js +3 -3
  29. package/core/npm.js +15 -13
  30. package/core/pkg.js +71 -14
  31. package/core/project.js +6 -0
  32. package/core/semanticRelease.js +3 -3
  33. package/core/turbo.js +52 -0
  34. package/core/typedoc.js +3 -3
  35. package/core/vitest.js +77 -0
  36. package/core/vscode.js +15 -5
  37. package/cspell/index.js +35 -14
  38. package/editorconfig/index.js +19 -9
  39. package/eslint/index.js +90 -47
  40. package/githooks/index.js +16 -12
  41. package/gitignore/index.js +1 -1
  42. package/lang/.eslintrc.json +1 -3
  43. package/lang/index.js +73 -36
  44. package/lang/templates/index.spec.ts +3 -2
  45. package/lang/templates/index.ts +1 -2
  46. package/licenses/index.js +26 -0
  47. package/package.json +21 -14
  48. package/postconfigure/index.js +11 -3
  49. package/project/index.js +253 -171
  50. package/release/index.js +5 -5
  51. package/renovate/index.js +4 -3
  52. package/tsconfig.json +3 -6
  53. package/{jest → vitest}/index.js +3 -3
package/core/jest.js CHANGED
@@ -1,8 +1,7 @@
1
- /* eslint-disable no-template-curly-in-string */
2
1
  const { packageJson } = require('mrm-core');
3
- const pkg = require('./pkg');
4
- const npm = require('./npm');
5
- const project = require('./project');
2
+ const pkg = require('./pkg.js');
3
+ const npm = require('./npm.js');
4
+ const project = require('./project.js');
6
5
 
7
6
  /**
8
7
  * @param {{
@@ -13,57 +12,48 @@ function jest({ state }) {
13
12
  const packageFileDefault = packageJson();
14
13
  const hasJest = state === 'present';
15
14
  const hasWorkspaces = pkg.hasWorkspaces(packageFileDefault);
16
- const hasTypescript = pkg.hasDependency(packageFileDefault, 'typescript', 'dev');
17
15
 
18
16
  pkg.withPackageJson((packageFile) => {
19
- if (hasJest) {
20
- if (hasWorkspaces) {
21
- pkg.value(packageFile, {
22
- path: 'jest',
23
- state: 'present',
24
- update: () => ({
17
+ const ignorePatterns = ['/node_modules/', '/docs/', '/lib/', '/build/', '/.cache/', '/public/'];
18
+
19
+ pkg.value(packageFile, {
20
+ path: 'jest',
21
+ state: hasJest ? 'present' : 'absent',
22
+ update: hasWorkspaces
23
+ ? () => ({
25
24
  preset: 'es-jest',
26
25
  projects: packageFile
27
26
  .get('workspaces.packages', packageFile.get('workspaces', []))
28
27
  .map((/** @type {string} */ workspace) => `<rootDir>/${workspace}`),
29
- }),
30
- });
31
- } else {
32
- const ignorePatterns = ['/node_modules/', '/docs/', '/lib/', '/build/', '/.cache/', '/public/'];
33
- packageFile.merge({
34
- jest: {
28
+ })
29
+ : (config) => ({
30
+ ...config,
35
31
  preset: 'es-jest',
36
32
  coveragePathIgnorePatterns: ignorePatterns,
37
33
  testPathIgnorePatterns: ignorePatterns,
38
- },
39
- });
40
- }
41
- } else {
42
- packageFile.unset('jest');
43
- }
44
-
34
+ }),
35
+ default: {},
36
+ });
45
37
  pkg.script(packageFile, {
46
- name: project.coverage,
47
- script: hasWorkspaces ? pkg.emptyScript : 'jest --coverage',
48
- state: !hasJest || hasWorkspaces ? 'default' : 'present',
38
+ name: `${project.coverage}:root`,
39
+ update: (/** @type {string|undefined} */ _) => (hasWorkspaces ? _ : 'jest --coverage'),
40
+ state: 'present',
41
+ default: undefined, // pkg.emptyScript,
49
42
  });
50
43
  pkg.script(packageFile, {
51
- name: project.test,
52
- script: hasWorkspaces ? pkg.emptyScript : 'jest',
53
- state: !hasJest || hasWorkspaces ? 'default' : 'present',
44
+ name: `${project.test}:root`,
45
+ update: (/** @type {string|undefined} */ _) => (hasWorkspaces ? _ : 'jest'),
46
+ state: 'present',
47
+ default: undefined, // pkg.emptyScript,
54
48
  });
55
49
  });
50
+
56
51
  // Dependencies
57
52
  npm.dependency({
58
53
  dev: true,
59
- name: ['jest', 'es-jest'],
54
+ name: ['jest', 'es-jest', '@jest/globals'],
60
55
  state: hasJest ? 'present' : 'absent',
61
56
  });
62
- npm.dependency({
63
- dev: true,
64
- name: ['@types/jest'],
65
- state: hasJest && hasTypescript ? 'present' : 'absent',
66
- });
67
57
 
68
58
  // vscodeSnippets({
69
59
  // name: 'jest',
package/core/jsonFile.js CHANGED
@@ -41,16 +41,17 @@ function setValue(jsonFile, path, pathValue) {
41
41
  */
42
42
  function value(jsonFile, { state, path, default: defaultValue, update: nextValue }) {
43
43
  if (state === 'present') {
44
- if (nextValue != null) {
45
- const resolvedValue = typeof nextValue === 'function' ? nextValue(getValue(jsonFile, path)) : nextValue;
46
- if (resolvedValue != null) {
47
- setValue(jsonFile, path, resolvedValue);
44
+ let currentValue = getValue(jsonFile, path);
45
+
46
+ if (currentValue == null) {
47
+ currentValue = typeof defaultValue === 'function' ? defaultValue() : defaultValue;
48
+ if (currentValue != null) {
49
+ setValue(jsonFile, path, currentValue);
48
50
  }
49
51
  }
50
52
 
51
- const currentValue = getValue(jsonFile, path);
52
- if (currentValue == null) {
53
- const resolvedValue = typeof defaultValue === 'function' ? defaultValue() : defaultValue;
53
+ if (nextValue != null) {
54
+ const resolvedValue = typeof nextValue === 'function' ? nextValue(getValue(jsonFile, path)) : nextValue;
54
55
  if (resolvedValue != null) {
55
56
  setValue(jsonFile, path, resolvedValue);
56
57
  }
@@ -1,6 +1,6 @@
1
- const pkg = require('./pkg');
2
- const npm = require('./npm');
3
- const jsonFile = require('./jsonFile');
1
+ const pkg = require('./pkg.js');
2
+ const npm = require('./npm.js');
3
+ const jsonFile = require('./jsonFile.js');
4
4
 
5
5
  /**
6
6
  * @typedef {Record<string, string|string[]>} LintStagedConfig
package/core/npm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable default-param-last */
2
- /* eslint-disable no-use-before-define */
2
+
3
3
  /* eslint-disable import/no-extraneous-dependencies */
4
4
  /* cSpell: disable */
5
5
  // @ts-check
@@ -24,18 +24,20 @@ const MrmError = require('mrm-core/src/error');
24
24
  const { yaml, json } = require('mrm-core');
25
25
 
26
26
  /**
27
- * @typedef Options
28
- * @property {boolean} [dev]
29
- * @property {boolean} [yarn]
30
- * @property {Record<string, string>} [versions]
27
+ * @typedef {{
28
+ * dev?: boolean,
29
+ * yarn?: boolean,
30
+ * versions?: Record<string, string>,
31
+ * }} Options
31
32
  */
32
33
 
33
34
  /**
34
- * @typedef RunOptions
35
- * @property {boolean} [dev]
36
- * @property {boolean} [remove]
37
- * @property {boolean} [stdio]
38
- * @property {string} [cwd]
35
+ * @typedef {{
36
+ * dev?: boolean,
37
+ * remove?: boolean,
38
+ * stdio?: boolean,
39
+ * cwd?: string,
40
+ * }} RunOptions
39
41
  */
40
42
 
41
43
  /**
@@ -166,7 +168,7 @@ function getVersionedDep(dep, versions) {
166
168
  /**
167
169
  *
168
170
  * @param {Options} options
169
- * @returns {Record<string, string>}
171
+ * @returns {Record<string, string>} - map of package names to versions
170
172
  */
171
173
  function getOwnDependencies(options) {
172
174
  const pkg = packageJson({
@@ -181,7 +183,7 @@ function getOwnDependencies(options) {
181
183
  * Return version of installed npm package
182
184
  *
183
185
  * @param {string} name
184
- * @returns {string}
186
+ * @returns {string} - version
185
187
  */
186
188
  function getInstalledVersion(name) {
187
189
  return json(`./node_modules/${name}/package.json`).get('version');
@@ -194,7 +196,7 @@ function getInstalledVersion(name) {
194
196
  * @param {string[]} deps
195
197
  * @param {Record<string, string>} versions
196
198
  * @param {Options} options
197
- * @returns {string[]}
199
+ * @returns {string[]} - list of not installed dependencies
198
200
  */
199
201
  function getUnsatisfiedDeps(deps, versions, options) {
200
202
  const ownDependencies = getOwnDependencies(options);
package/core/pkg.js CHANGED
@@ -1,16 +1,37 @@
1
1
  /* cSpell: disable */
2
2
  // @ts-check
3
3
 
4
+ /**
5
+ * @typedef {string|boolean|number|null|Array<unknown>|Record<string, unknown>} JsonValue
6
+ */
7
+
4
8
  // @ts-ignore
5
9
  const { intersect } = require('semver-intersect');
6
- const { packageJson, file } = require('mrm-core');
7
- const jsonFile = require('./jsonFile');
10
+ const { packageJson, file, json } = require('mrm-core');
11
+ const glob = require('glob');
12
+ const path = require('node:path');
13
+ const jsonFile = require('./jsonFile.js');
8
14
 
9
15
  /**
10
16
  * An empty placeholder for npm script
11
17
  */
12
18
  const emptyScript = ':';
13
19
 
20
+ /**
21
+ * @param {import('mrm-core').Json} packageFile
22
+ * @returns {'application'|'library'|'workspace'} the archetype value
23
+ */
24
+ function archetype(packageFile) {
25
+ if (hasWorkspaces(packageFile)) {
26
+ return 'workspace';
27
+ }
28
+ if (packageFile.get('private') === true || (packageFile.get('main') == null && packageFile.get('exports'))) {
29
+ return 'application';
30
+ }
31
+
32
+ return 'library';
33
+ }
34
+
14
35
  /**
15
36
  * @param {(pkg: import('mrm-core').PackageJson) => void} block
16
37
  */
@@ -21,26 +42,58 @@ function withPackageJson(block) {
21
42
  }
22
43
 
23
44
  /**
24
- * @param {import('mrm-core').PackageJson} packageFile
45
+ * @param {import("mrm-core").Json} packageFile
46
+ * @returns {string[]} - The list of workspace matchers
47
+ */
48
+ function listWorkspaceMatchers(packageFile) {
49
+ return packageFile.get('workspaces.packages', packageFile.get('workspaces', []));
50
+ }
51
+
52
+ /**
53
+ * @param {(workspace: {
54
+ * projectDir: string;
55
+ * packageFile: import("mrm-core").Json;
56
+ * }) => void} fn
57
+ */
58
+ function forEachWorkspace(fn) {
59
+ const packageRoot = packageJson();
60
+ const workspacesMatchers = listWorkspaceMatchers(packageRoot);
61
+
62
+ for (const workspaceMatcher of workspacesMatchers) {
63
+ const directories = glob.sync(workspaceMatcher);
64
+ directories.forEach((directory) => {
65
+ const packageFile = json(path.join(directory, 'package.json'));
66
+ fn({
67
+ projectDir: directory,
68
+ packageFile,
69
+ });
70
+ packageFile.save();
71
+ });
72
+ }
73
+ }
74
+
75
+ /**
76
+ * @template {undefined|JsonValue} T
77
+ * @param {import('mrm-core').Json} packageFile
25
78
  * @param {{
26
79
  * name: string,
27
- * state: 'present'|'absent'|'default',
28
- * script: string,
80
+ * state: 'present'|'absent',
81
+ * update?: T | ((previousValue: T) => T)
82
+ * default?: T | (() => T)
29
83
  * }} options
30
84
  */
31
- function script(packageFile, { name, state, script: scriptName }) {
32
- if (state === 'absent') {
33
- packageFile.removeScript(name);
34
- } else if (state === 'present' || (state === 'default' && !packageFile.getScript(name))) {
35
- packageFile.setScript(name, scriptName);
36
- }
85
+ function script(packageFile, options) {
86
+ jsonFile.value(packageFile, {
87
+ ...options,
88
+ path: ['scripts', options.name],
89
+ });
37
90
  }
38
91
 
39
92
  const defaultManager = 'npm';
40
93
 
41
94
  /**
42
95
  * @param {import('mrm-core').PackageJson} packageFile
43
- * @returns {'yarn'|'npm'}
96
+ * @returns {'yarn'|'npm'} - The manager used by the package
44
97
  */
45
98
  function manager(packageFile) {
46
99
  if (packageFile.get('packagerManager')) {
@@ -60,7 +113,7 @@ function manager(packageFile) {
60
113
 
61
114
  /**
62
115
  *
63
- * @param {import('mrm-core').PackageJson} packageFile
116
+ * @param {import('mrm-core').Json} packageFile
64
117
  */
65
118
  function hasWorkspaces(packageFile) {
66
119
  return Boolean(packageFile.get('workspaces'));
@@ -88,7 +141,7 @@ function hasDependency(packageFile, packageName, dependencyType) {
88
141
 
89
142
  /**
90
143
  *
91
- * @param {import('mrm-core').PackageJson} packageFile
144
+ * @param {import('mrm-core').Json} packageFile
92
145
  * @param {Record<string, string>} engineVersionMap
93
146
  */
94
147
  function engineMinVersion(packageFile, engineVersionMap) {
@@ -110,15 +163,19 @@ function engineMinVersion(packageFile, engineVersionMap) {
110
163
  Object.keys(engineVersionMap).map((engineName) => [engineName, engineConstraint(engineName)])
111
164
  ),
112
165
  });
166
+ return packageFile.get('engines');
113
167
  }
114
168
 
115
169
  module.exports = {
116
170
  ...jsonFile,
117
171
  emptyScript,
172
+ archetype,
118
173
  script,
119
174
  manager,
120
175
  engineMinVersion,
121
176
  hasDependency,
122
177
  hasWorkspaces,
123
178
  withPackageJson,
179
+ forEachWorkspace,
180
+ listWorkspaceMatchers,
124
181
  };
package/core/project.js CHANGED
@@ -1,3 +1,5 @@
1
+ /** @type {'docs'} */
2
+ const docs = 'docs';
1
3
  /** @type {'install'} */
2
4
  const install = 'install';
3
5
  /** @type {'prepare'} */
@@ -24,6 +26,8 @@ const validate = 'validate';
24
26
  const release = 'release';
25
27
  /** @type {'rescue'} */
26
28
  const rescue = 'rescue';
29
+ /** @type {'spellcheck'} */
30
+ const spellcheck = 'spellcheck';
27
31
 
28
32
  /**
29
33
  * @param {string} taskName
@@ -41,6 +45,7 @@ function post(taskName) {
41
45
 
42
46
  module.exports = {
43
47
  build,
48
+ docs,
44
49
  prepare,
45
50
  develop,
46
51
  clean,
@@ -55,4 +60,5 @@ module.exports = {
55
60
  rescue,
56
61
  test,
57
62
  validate,
63
+ spellcheck,
58
64
  };
@@ -1,6 +1,6 @@
1
- const npm = require('./npm');
2
- const pkg = require('./pkg');
3
- const jsonFile = require('./jsonFile');
1
+ const npm = require('./npm.js');
2
+ const pkg = require('./pkg.js');
3
+ const jsonFile = require('./jsonFile.js');
4
4
 
5
5
  /**
6
6
  * @typedef {{
package/core/turbo.js ADDED
@@ -0,0 +1,52 @@
1
+ const { json } = require('mrm-core');
2
+ const npm = require('./npm.js');
3
+ const jsonFile = require('./jsonFile.js');
4
+
5
+ /**
6
+ * @typedef {{
7
+ * $schema: string,
8
+ * pipeline?: Record<string, unknown>,
9
+ * globalDependencies?: Array<string>,
10
+ * }} TurboConfig
11
+ */
12
+
13
+ /**
14
+ * @param {{
15
+ * state: 'present'|'absent',
16
+ * update: (config: TurboConfig) => TurboConfig
17
+ * }} options
18
+ */
19
+ function turbo({ state, update }) {
20
+ const hasTurbo = state === 'present';
21
+ const turboFile = json('turbo.json');
22
+
23
+ if (hasTurbo) {
24
+ jsonFile.value(turboFile, {
25
+ path: undefined,
26
+ state,
27
+ update,
28
+ /** @type {TurboConfig} */
29
+ default: {
30
+ $schema: 'https://turborepo.org/schema.json',
31
+ },
32
+ });
33
+
34
+ /**
35
+ * Otherwise save the file with content
36
+ */
37
+ turboFile.save();
38
+ } else {
39
+ turboFile.delete();
40
+ }
41
+
42
+ // Dependencies
43
+ npm.dependency({
44
+ dev: true,
45
+ name: ['turbo'],
46
+ state: hasTurbo ? 'present' : 'absent',
47
+ });
48
+ }
49
+
50
+ module.exports = {
51
+ turbo,
52
+ };
package/core/typedoc.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const { packageJson, json } = require('mrm-core');
2
- const pkg = require('./pkg');
3
- const npm = require('./npm');
4
- const jsonFile = require('./jsonFile');
2
+ const pkg = require('./pkg.js');
3
+ const npm = require('./npm.js');
4
+ const jsonFile = require('./jsonFile.js');
5
5
 
6
6
  /**
7
7
  * @typedef {{
package/core/vitest.js ADDED
@@ -0,0 +1,77 @@
1
+ const { file, packageJson } = require('mrm-core');
2
+ const fs = require('node:fs');
3
+ const pkg = require('./pkg.js');
4
+ const npm = require('./npm.js');
5
+ const project = require('./project.js');
6
+
7
+ /**
8
+ * @param {{
9
+ * state: 'present'|'absent'
10
+ * }} options
11
+ */
12
+ function vitest({ state }) {
13
+ const hasVitest = state === 'present';
14
+ const hasWorkspace = pkg.hasWorkspaces(packageJson());
15
+ const vitestScript = 'vitest run';
16
+ const update = (/** @type {string|undefined} */ _) =>
17
+ hasVitest ? vitestScript : _ === vitestScript ? pkg.emptyScript : _;
18
+
19
+ // Dependencies
20
+ npm.dependency({
21
+ dev: true,
22
+ name: ['vite', 'vitest'],
23
+ state: hasVitest ? 'present' : 'absent',
24
+ });
25
+
26
+ /** @type {string|undefined} */
27
+ let viteVersion;
28
+ /** @type {string|undefined} */
29
+ let vitestVersion;
30
+ pkg.withPackageJson((packageFile) => {
31
+ viteVersion = packageFile.get('devDependencies.vite');
32
+ vitestVersion = packageFile.get('devDependencies.vitest');
33
+ pkg.script(packageFile, {
34
+ name: `${project.test}:root`,
35
+ update,
36
+ state: hasWorkspace ? 'absent' : 'present',
37
+ });
38
+ });
39
+
40
+ pkg.forEachWorkspace(({ projectDir, packageFile }) => {
41
+ const hasSrc = fs.existsSync(`${projectDir}/src`);
42
+ const packageState = hasVitest && hasSrc ? 'present' : 'absent';
43
+ pkg.value(packageFile, {
44
+ path: 'devDependencies.vite',
45
+ state: packageState,
46
+ update: (_) => _ ?? viteVersion,
47
+ });
48
+ pkg.value(packageFile, {
49
+ path: 'devDependencies.vitest',
50
+ state: packageState,
51
+ update: (_) => _ ?? vitestVersion,
52
+ });
53
+ pkg.script(packageFile, {
54
+ name: `${project.test}:src`,
55
+ update,
56
+ state: packageState,
57
+ });
58
+ const viteConfig = file(`${projectDir}/vite.config.ts`);
59
+ if (packageState === 'absent') {
60
+ viteConfig.delete();
61
+ } else if (!viteConfig.exists()) {
62
+ viteConfig.save(
63
+ `/// <reference types="vitest" />
64
+ import { defineConfig } from 'vite';
65
+
66
+ export default defineConfig({
67
+ test: {},
68
+ });
69
+ `
70
+ );
71
+ }
72
+ });
73
+ }
74
+
75
+ module.exports = {
76
+ vitest,
77
+ };
package/core/vscode.js CHANGED
@@ -1,13 +1,23 @@
1
1
  const { json } = require('mrm-core');
2
2
 
3
3
  /**
4
- * @param {Array<string>} recommendations
4
+ * @param {{
5
+ * name: string,
6
+ * state: 'present'|'absent',
7
+ * }} recommendation
5
8
  */
6
- function vscodeRecommendedExtension(recommendations) {
9
+ function vscodeRecommendedExtension(recommendation) {
7
10
  const packageFile = json('.vscode/extensions.json');
8
- packageFile.merge({
9
- recommendations,
10
- });
11
+ if (recommendation.state === 'present') {
12
+ packageFile.merge({
13
+ recommendations: [recommendation.name],
14
+ });
15
+ } else {
16
+ packageFile.set(
17
+ 'recommendations',
18
+ packageFile.get('recommendations', []).filter((/** @type {string} */ _) => _ !== recommendation.name)
19
+ );
20
+ }
11
21
  packageFile.save();
12
22
  }
13
23
  exports.vscodeRecommendedExtension = vscodeRecommendedExtension;
package/cspell/index.js CHANGED
@@ -1,25 +1,46 @@
1
- const { cspell } = require('../core/cspell');
1
+ const { cspell } = require('../core/cspell.js');
2
+ const project = require('../core/project.js');
3
+ const pkg = require('../core/pkg.js');
4
+ const npm = require('../core/npm.js');
2
5
 
3
6
  function task() {
7
+ const preset = '@w5s/cspell-config';
4
8
  cspell({
5
9
  state: 'present',
6
10
  update: (_) => ({
7
11
  ..._,
8
- ignorePaths: Array.from(
9
- new Set([
10
- '**/build/**',
11
- '**/lib/**',
12
- '**/node_modules/**',
13
- '**/package.json',
14
- '**/package-lock.json',
15
- '**/yarn.lock',
16
- '**/*.log',
17
- '**/CHANGELOG.md',
18
- ...(_.ignorePaths || []),
19
- ])
20
- ),
12
+ import: [preset],
21
13
  }),
22
14
  });
15
+ npm.dependency({
16
+ dev: true,
17
+ name: [preset],
18
+ state: 'present',
19
+ });
20
+
21
+ pkg.withPackageJson((packageFile) => {
22
+ const hasWorkspaces = pkg.hasWorkspaces(packageFile);
23
+ const workspaceMatchers = pkg.listWorkspaceMatchers(packageFile);
24
+ pkg.script(packageFile, {
25
+ name: project.spellcheck,
26
+ update: `turbo run spellcheck`,
27
+ state: 'present',
28
+ });
29
+ pkg.script(packageFile, {
30
+ name: `${project.spellcheck}:root`,
31
+ update: `cspell --no-progress '**' ${
32
+ hasWorkspaces ? `${workspaceMatchers.map((_) => `--exclude='${_}/**'`).join(' ')}` : ''
33
+ }`,
34
+ state: 'present',
35
+ });
36
+ });
37
+ pkg.forEachWorkspace(({ packageFile }) => {
38
+ pkg.script(packageFile, {
39
+ name: project.spellcheck,
40
+ update: `cspell --no-progress '**'`,
41
+ state: 'present',
42
+ });
43
+ });
23
44
  }
24
45
 
25
46
  task.description = 'Adds CSpell support';
@@ -1,6 +1,6 @@
1
1
  const { ini } = require('mrm-core');
2
2
  const createDebug = require('debug');
3
- const { vscodeRecommendedExtension } = require('../core/vscode');
3
+ const { vscodeRecommendedExtension } = require('../core/vscode.js');
4
4
 
5
5
  /**
6
6
  *
@@ -26,7 +26,7 @@ function createEditorConfig(defaults) {
26
26
 
27
27
  /**
28
28
  * @param {string} section
29
- * @param existing
29
+ * @param {defaults} existing
30
30
  */
31
31
  function mergeSection(section, existing = {}) {
32
32
  return Object.assign(existing, defaults[section] || {});
@@ -43,7 +43,10 @@ function createEditorConfig(defaults) {
43
43
 
44
44
  editorConfigFile.save();
45
45
 
46
- vscodeRecommendedExtension(['editorconfig.editorconfig']);
46
+ vscodeRecommendedExtension({
47
+ name: 'editorconfig.editorconfig',
48
+ state: 'present',
49
+ });
47
50
  }
48
51
 
49
52
  task.description = 'Adds EditorConfig file';
@@ -66,31 +69,38 @@ module.exports = createEditorConfig({
66
69
  spaces_around_operators: true,
67
70
  trim_trailing_whitespace: true,
68
71
  },
69
- '*.json': {
72
+ '*.{json,json5,webmanifest}': {
70
73
  indent_size: 2,
71
74
  indent_style: 'space',
72
75
  insert_final_newline: 'ignore',
73
76
  },
74
- '*.yml': {
77
+ '*.{yml,yaml}': {
75
78
  indent_size: 2,
76
79
  indent_style: 'space',
77
80
  },
78
- '*.{bat,reg,ps1,vbs,cs,,fs,ahk}': {
81
+ '*.{bat,reg,ps1,vbs,cs,cmd,fs,ahk}': {
79
82
  end_of_line: 'crlf',
80
83
  },
81
- '*.{css,scss,less}': {
84
+ '*.{sh,zsh}': {
85
+ end_of_line: 'lf',
86
+ },
87
+ '*.{css,sass,scss,less,pcss}': {
82
88
  indent_size: 2,
83
89
  indent_style: 'space',
84
90
  max_line_length: 120,
85
91
  quote_type: 'single',
86
92
  },
87
- '*.{js,jsx,ts,tsx,js.hbs}': {
93
+ '*.{js,jsx,jsm,ts,tsx,cjs,cjs,cjsx,cts,ctsx,mjs,mts,mtsx,js.hbs}': {
88
94
  indent_size: 2,
89
95
  indent_style: 'space',
90
96
  max_line_length: 120,
91
97
  quote_type: 'single',
92
98
  },
93
- '*.{md,mdwn,mdown,markdown,apib}': {
99
+ '*.{htm,html,svg,vue}': {
100
+ indent_size: 2,
101
+ indent_style: 'space',
102
+ },
103
+ '*.{md,mdwn,mdown,markdown,mdx,apib}': {
94
104
  indent_size: 4,
95
105
  indent_style: 'space',
96
106
  insert_final_newline: true,