gscan 4.41.0 → 4.42.1

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 CHANGED
@@ -10,29 +10,26 @@ It is actively capable of dealing with the current and last major versions of Gh
10
10
 
11
11
  GScan works on a system of rules. Each rule has a way to check whether it passes or fails and has help content which describes how to fix it. Each rule is also marked with an error level:
12
12
 
13
- - **recommendation** = these are things the dev might want to know about
14
- - **warning** = usually used for deprecations, things that will be errors in the next version
15
- - **error** = anything that makes the theme invalid or incompatible with the current version of Ghost
13
+ - Errors: issues that will cause your theme to not work properly. These must be fixed.
14
+ - Warnings: these are usually related to deprecated features. These should be fixed.
15
+ - Recommendations: these are advisories about best practice. Fixing these will improve your theme.
16
+ - Features: detected features which may impact on compatibility. Nothing to do!
16
17
 
17
18
  In addition, an **error** can be marked as **fatal**. A **fatal error** means, left unchecked a Ghost publication would throw 500 errors on certain pages because of the detected out-of-date or erroneous code.
18
19
 
19
- In Ghost, we call GScan on boot. If any fatal errors are detected in Ghost(Pro) and in Ghost-CLI we call GScan as part of major upgrades. The upgrade will not be allowed to continue if any fatal errors are detected.
20
-
21
- Errors are only marked as **fatal errors** if they would cause errors, and therefore should block a boot or an upgrade.
20
+ ## Usage
22
21
 
23
- ### Tooling
24
- When developing new rules or testing gscan following tools are great to have in the toolbelt:
25
- - [astexplorer](https://astexplorer.net) - absolutely awesome Handlebars AST fiddler, helpful when testing out new ideas and exploring what's possible through AST parser;
22
+ There are 4 ways to use gscan to validate your theme:
26
23
 
27
- ## Usage
24
+ ### 1. Inside Ghost
28
25
 
29
- There are 3 ways to use gscan to validate your theme:
26
+ Gscan is pre-installed in Ghost. If there are theme errors, Ghost will show them on boot in the console logs and in the UI (Ghost Admin).
30
27
 
31
- ### 1. Web usage
28
+ ### 2. Web usage
32
29
 
33
30
  Visit https://gscan.ghost.org and upload your zip to our online version of Gscan.
34
31
 
35
- ### 2. CLI usage
32
+ ### 3. CLI usage
36
33
 
37
34
  Install using yarn / npm:
38
35
 
@@ -48,21 +45,21 @@ To run a local zip file through the checks:
48
45
 
49
46
  By default, GScan scans themes for the latest Ghost version compatibility. You can also specify a Ghost version by using the following parameters (for Ghost 1.0, 2.0, 3.0, 4.0 and 5.0):
50
47
 
51
- `--v1` or `-1`
52
- `--v2` or `-2`
53
- `--v3` or `-3`
48
+ `--v1` or `-1`
49
+ `--v2` or `-2`
50
+ `--v3` or `-3`
54
51
  `--v4` or `-4` or `--canary`
55
- `--v5` or `-5`
52
+ `--v5` or `-5`
56
53
 
57
54
  Use the `--canary` parameter to check for the upcoming Ghost version.
58
55
 
59
56
  Examples:
60
57
 
61
- `gscan /path/to/theme.zip -z1` - scan a theme in a zip file for Ghost 1.0 compatibility
62
- `gscan /path/to/theme/directory --v2` - can a theme in a directory for Ghost 2.0 compatibility
63
- `gscan /path/to/theme/directory --canary` - scan a theme for the upcoming version of Ghost
58
+ `gscan /path/to/theme.zip -z1` - scan a theme in a zip file for Ghost 1.0 compatibility
59
+ `gscan /path/to/theme/directory --v2` - can a theme in a directory for Ghost 2.0 compatibility
60
+ `gscan /path/to/theme/directory --canary` - scan a theme for the upcoming version of Ghost
64
61
 
65
- ### 3. Lib usage
62
+ ### 4. Lib usage
66
63
 
67
64
  Install using yarn/npm and then:
68
65
 
@@ -98,14 +95,11 @@ gscan.checkZip({
98
95
 
99
96
  - `yarn ship`
100
97
 
101
- ## Result types:
102
-
103
- - Errors: these are issues which will cause your theme to not work properly. These must be fixed.
104
- - Warnings: these are usually related to deprecated features. These should be fixed.
105
- - Recommendations: these are advisories about best practice. Fixing these will improve your theme.
106
- - Features: detected features which may impact on compatibility. Nothing to do :)
98
+ ### Tools
99
+ When developing new rules or testing gscan following tools are great to have in the toolbelt:
100
+ - [astexplorer](https://astexplorer.net) - absolutely awesome Handlebars AST fiddler, helpful when testing out new ideas and exploring what's possible through AST parser;
107
101
 
108
- ## Still To Do:
102
+ ## To Do
109
103
 
110
104
  - Support for running the checks against a GitHub repository
111
105
  - Many, many more checks
@@ -1,5 +1,6 @@
1
1
  const Rule = require('./base');
2
2
  const {getPartialName} = require('../helpers');
3
+ const {normalizePath} = require('../../utils');
3
4
 
4
5
  module.exports = class MarkUsedPartials extends Rule {
5
6
  _markUsedPartials(node) {
@@ -8,6 +9,7 @@ module.exports = class MarkUsedPartials extends Rule {
8
9
  if (nodeName) {
9
10
  this.scanner.context.partials.push({
10
11
  node: nodeName,
12
+ normalizedName: normalizePath(nodeName),
11
13
  type: node.type,
12
14
  loc: node.loc,
13
15
  parameters: node.params ? node.params.map(p => p.original) : null
package/lib/checker.js CHANGED
@@ -22,7 +22,7 @@ const labsEnabledHelpers = {
22
22
  * @param {Object=} [options.labs] object containing boolean flags for enabled labs features
23
23
  * @returns {Promise<Object>}
24
24
  */
25
- const check = function checkAll(themePath, options = {}) {
25
+ const check = async function checkAll(themePath, options = {}) {
26
26
  // Require checks late to avoid loading all until used
27
27
  const checks = requireDir('./checks');
28
28
  const passedVersion = _.get(options, 'checkVersion', versions.default);
@@ -44,27 +44,33 @@ const check = function checkAll(themePath, options = {}) {
44
44
 
45
45
  // Require readTheme late to avoid loading entire AST parser until used
46
46
  const readTheme = require('./read-theme');
47
- return readTheme(themePath)
48
- .then(function (theme) {
49
- // set the major version to check
50
- theme.checkedVersion = versions[version].major;
51
-
52
- return Promise.all(_.values(checks).map(async (checkFunction) => {
53
- const now = Date.now();
54
- const result = await checkFunction(theme, options, themePath);
55
- debug(checkFunction.name, 'took', Date.now() - now, 'ms');
56
- return result;
57
- })).then(() => theme);
58
- })
59
- .catch((error) => {
60
- throw new errors.ValidationError({
61
- message: 'Failed theme files check',
62
- help: 'Your theme file structure is corrupted or contains errors',
63
- errorDetails: error.message,
64
- context: options.themeName,
65
- err: error
66
- });
47
+
48
+ try {
49
+ const theme = await readTheme(themePath);
50
+
51
+ // set the major version to check
52
+ theme.checkedVersion = versions[version].major;
53
+
54
+ const timeBeforeChecks = Date.now();
55
+
56
+ for (const checkName in checks) {
57
+ const now = Date.now();
58
+ await checks[checkName](theme, options, themePath);
59
+ debug(checkName, 'took', Date.now() - now, 'ms');
60
+ }
61
+
62
+ debug('All checks took', Date.now() - timeBeforeChecks, 'ms');
63
+
64
+ return theme;
65
+ } catch (err) {
66
+ throw new errors.ValidationError({
67
+ message: 'Failed theme files check',
68
+ help: 'Your theme file structure is corrupted or contains errors',
69
+ errorDetails: err.message,
70
+ context: options.themeName,
71
+ err
67
72
  });
73
+ }
68
74
  };
69
75
 
70
76
  const checkZip = async function checkZip(path, options) {
@@ -2,7 +2,6 @@ const _ = require('lodash');
2
2
  const spec = require('../specs');
3
3
  const versions = require('../utils').versions;
4
4
  const ASTLinter = require('../ast-linter');
5
- const {normalizePath} = require('../utils');
6
5
 
7
6
  function processFileFunction(files, failures, theme, partialsFound) {
8
7
  const processedFiles = [];
@@ -61,7 +60,8 @@ function processFileFunction(files, failures, theme, partialsFound) {
61
60
  linter.partials.forEach((partial) => {
62
61
  const partialName = partial.node;
63
62
  partialsFound[partialName] = true;
64
- const file = files.find(f => normalizePath(f.file) === `partials/${normalizePath(partialName)}.hbs`);
63
+
64
+ const file = files.find(f => f.normalizedFile === `partials/${partial.normalizedName}.hbs`);
65
65
  if (file) {
66
66
  // Find all inline partial declaration that were within the partial usage block
67
67
  const childrenInlinePartials = [...parentInlinePartials];
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const spec = require('../specs');
3
- const {versions, normalizePath, getPackageJSON} = require('../utils');
3
+ const {versions, getPackageJSON} = require('../utils');
4
4
  const ASTLinter = require('../ast-linter');
5
5
 
6
6
  function processFileFunction(files, failures, rules) {
@@ -30,8 +30,8 @@ function processFileFunction(files, failures, rules) {
30
30
  });
31
31
  }
32
32
 
33
- linter.partials.forEach(({node: partial}) => {
34
- const file = files.find(f => normalizePath(f.file) === `partials/${normalizePath(partial)}.hbs`);
33
+ linter.partials.forEach(({normalizedName}) => {
34
+ const file = files.find(f => f.normalizedFile === `partials/${normalizedName}.hbs`);
35
35
  if (file) {
36
36
  processFile(linter, file);
37
37
  }
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const spec = require('../specs');
3
- const {versions, normalizePath} = require('../utils');
3
+ const {versions} = require('../utils');
4
4
  const ASTLinter = require('../ast-linter');
5
5
 
6
6
  function getRules(id, options) {
@@ -103,8 +103,8 @@ function parseWithAST({theme, log, file, rules, callback}){
103
103
  callback(linter);
104
104
  }
105
105
 
106
- linter.partials.forEach(({node: partial}) => {
107
- const partialFile = theme.files.find(f => normalizePath(f.file) === `partials/${normalizePath(partial)}.hbs`);
106
+ linter.partials.forEach(({normalizedName}) => {
107
+ const partialFile = theme.files.find(f => f.normalizedFile === `partials/${normalizedName}.hbs`);
108
108
  if (partialFile) {
109
109
  processFile(partialFile);
110
110
  }
@@ -1,6 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const spec = require('../specs');
3
- const {versions, normalizePath} = require('../utils');
3
+ const {versions} = require('../utils');
4
4
  const ASTLinter = require('../ast-linter');
5
5
 
6
6
  function getRules(id, options) {
@@ -104,8 +104,8 @@ function parseWithAST({theme, log, file, rules, callback}) {
104
104
  callback(linter);
105
105
  }
106
106
 
107
- linter.partials.forEach(({node: partial}) => {
108
- const partialFile = theme.files.find(f => normalizePath(f.file) === `partials/${normalizePath(partial)}.hbs`);
107
+ linter.partials.forEach(({normalizedName}) => {
108
+ const partialFile = theme.files.find(f => f.normalizedFile === `partials/${normalizedName}.hbs`);
109
109
  if (partialFile) {
110
110
  processFile(partialFile);
111
111
  }
@@ -2,7 +2,6 @@ const _ = require('lodash');
2
2
  const spec = require('../specs');
3
3
  const versions = require('../utils').versions;
4
4
  const ASTLinter = require('../ast-linter');
5
- const {normalizePath} = require('../utils');
6
5
 
7
6
  function processFileFunction(files, failures, theme, partialsFound) {
8
7
  const processedFiles = [];
@@ -61,7 +60,7 @@ function processFileFunction(files, failures, theme, partialsFound) {
61
60
  linter.partials.forEach((partial) => {
62
61
  const partialName = partial.node;
63
62
  partialsFound[partialName] = true;
64
- const file = files.find(f => normalizePath(f.file) === `partials/${normalizePath(partialName)}.hbs`);
63
+ const file = files.find(f => f.normalizedFile === `partials/${partial.normalizedName}.hbs`);
65
64
  if (file) {
66
65
  // Find all inline partial declaration that were within the partial usage block
67
66
  const childrenInlinePartials = [...parentInlinePartials];
package/lib/read-theme.js CHANGED
@@ -3,6 +3,7 @@ const _ = require('lodash');
3
3
  const os = require('os');
4
4
  const path = require('path');
5
5
  const ASTLinter = require('./ast-linter');
6
+ const {normalizePath} = require('./utils');
6
7
 
7
8
  const ignore = [
8
9
  'node_modules',
@@ -31,6 +32,7 @@ const readThemeStructure = function readThemeFiles(themePath, subPath, arr) {
31
32
  var makeResult = function makeResult(result, subFilePath, ext, symlink) {
32
33
  result.push({
33
34
  file: subFilePath,
35
+ normalizedFile: normalizePath(subFilePath),
34
36
  ext,
35
37
  symlink
36
38
  });
package/lib/specs/v4.js CHANGED
@@ -54,7 +54,7 @@ let rules = {
54
54
  'GS010-PJ-CUST-THEME-TOTAL-SETTINGS': {
55
55
  level: 'error',
56
56
  rule: '<code>package.json</code> property <code>"config.custom"</code> contains too many settings',
57
- details: oneLineTrim`Remove key from <code>"config.custom"</code> in your <code>package.json</code> to have less than or exactly 15 settings.<br>
57
+ details: oneLineTrim`Remove key from <code>"config.custom"</code> in your <code>package.json</code> to have less than or exactly 20 settings.<br>
58
58
  Check the <a href="${docsBaseUrl}structure/#packagejson" target=_blank><code>package.json</code> documentation</a> for further information.`
59
59
  },
60
60
  'GS010-PJ-CUST-THEME-SETTINGS-CASE': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gscan",
3
- "version": "4.41.0",
3
+ "version": "4.42.1",
4
4
  "description": "Scans Ghost themes looking for errors, deprecations, features and compatibility",
5
5
  "keywords": [
6
6
  "ghost",
@@ -13,6 +13,9 @@
13
13
  "type": "git",
14
14
  "url": "git@github.com:TryGhost/gscan.git"
15
15
  },
16
+ "publishConfig": {
17
+ "registry": "https://registry.npmjs.org/"
18
+ },
16
19
  "engines": {
17
20
  "node": "^14.18.0 || ^16.13.0 || ^18.12.1"
18
21
  },
@@ -80,5 +83,14 @@
80
83
  "lib",
81
84
  "bin",
82
85
  "app"
83
- ]
86
+ ],
87
+ "renovate": {
88
+ "extends": [
89
+ "@tryghost:quietJS",
90
+ "@tryghost:automergeDevDependencies"
91
+ ],
92
+ "ignoreDeps": [
93
+ "validator"
94
+ ]
95
+ }
84
96
  }