From bab3d5910ab119dd1b14bcd53c79f3f31bc1017d Mon Sep 17 00:00:00 2001 From: Blake Newman Date: Tue, 5 Apr 2016 16:10:48 +0100 Subject: [PATCH] [Feature] Added support for linting style tags within html files - Added component option resolving (async to sync conversion) - Added grammar styles for embedded css - Added option to enable html linting --- lib/index.js | 50 +++++++++++++++---- spec/fixtures/html/good.html | 5 ++ .../html/stylelint-config-standard.html | 3 ++ spec/linter-stylelint-spec.js | 32 ++++++++++++ 4 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 spec/fixtures/html/good.html create mode 100644 spec/fixtures/html/stylelint-config-standard.html diff --git a/lib/index.js b/lib/index.js index 46c77616..bd0f4d20 100644 --- a/lib/index.js +++ b/lib/index.js @@ -25,12 +25,19 @@ export const config = { description: 'Either .stylelintrc or stylelint.config.js', type: 'boolean', default: false + }, + enableHtmlLinting: { + title: 'Enable linting of styles within html', + description: 'Turn on linting of your styles tages within html files.', + type: 'boolean', + default: false } }; let useStandard; let presetConfig; let disableWhenNoConfig; +let enableHtmlLinting; let subscriptions; function createRange(editor, data) { @@ -52,6 +59,9 @@ export function activate() { subscriptions.add(atom.config.observe('linter-stylelint.disableWhenNoConfig', value => { disableWhenNoConfig = value; })); + subscriptions.add(atom.config.observe('linter-stylelint.enableHtmlLinting', value => { + enableHtmlLinting = value; + })); } export function deactivate() { @@ -108,16 +118,29 @@ function runStylelint(editor, options, filePath) { } export function provideLinter() { + const grammarScopes = [ + 'source.css', + 'source.scss', + 'source.css.scss', + 'source.less', + 'source.css.less', + 'source.css.postcss' + ]; + if (enableHtmlLinting) { + grammarScopes.push( + 'source.css.embedded.html', + 'source.css.scss.embedded.html', + 'source.scss.embedded.html', + 'source.css.postcss.embedded.html', + 'source.postcss.embedded.html', + 'source.css.less.embedded.html', + 'source.less.embedded.html' + ); + } + return { name: 'stylelint', - grammarScopes: [ - 'source.css', - 'source.scss', - 'source.css.scss', - 'source.less', - 'source.css.less', - 'source.css.postcss' - ], + grammarScopes, scope: 'file', lintOnFly: true, lint: editor => { @@ -140,18 +163,23 @@ export function provideLinter() { code: text, codeFilename: filePath, config: rules, - configBasedir: dirname(filePath) + configBasedir: dirname(filePath), + extractStyleTagsFromHtml: enableHtmlLinting }; if ( scopes.indexOf('source.css.scss') !== -1 || - scopes.indexOf('source.scss') !== -1 + scopes.indexOf('source.scss') !== -1 || + scopes.indexOf('source.css.scss.embedded.html') !== -1 || + scopes.indexOf('source.scss.embedded.html') !== -1 ) { options.syntax = 'scss'; } if ( scopes.indexOf('source.css.less') !== -1 || - scopes.indexOf('source.less') !== -1 + scopes.indexOf('source.less') !== -1 || + scopes.indexOf('source.css.less.embedded.html') !== -1 || + scopes.indexOf('source.less.embedded.html') !== -1 ) { options.syntax = 'less'; } diff --git a/spec/fixtures/html/good.html b/spec/fixtures/html/good.html new file mode 100644 index 00000000..1cccda5c --- /dev/null +++ b/spec/fixtures/html/good.html @@ -0,0 +1,5 @@ + diff --git a/spec/fixtures/html/stylelint-config-standard.html b/spec/fixtures/html/stylelint-config-standard.html new file mode 100644 index 00000000..514fcbbf --- /dev/null +++ b/spec/fixtures/html/stylelint-config-standard.html @@ -0,0 +1,3 @@ + diff --git a/spec/linter-stylelint-spec.js b/spec/linter-stylelint-spec.js index f1413ea2..1a917e4d 100644 --- a/spec/linter-stylelint-spec.js +++ b/spec/linter-stylelint-spec.js @@ -14,6 +14,9 @@ const invalidConfigPath = path.join(__dirname, 'fixtures', 'invalid-config', 'st const lessDir = path.join(__dirname, 'fixtures', 'less'); const goodLess = path.join(lessDir, 'good.less'); const configStandardLessPath = path.join(lessDir, 'stylelint-config-standard.less'); +const htmlDir = path.join(__dirname, 'fixtures', 'html'); +const goodHtml = path.join(htmlDir, 'good.html'); +const configStandardHtmlPath = path.join(htmlDir, 'stylelint-config-standard.html'); const goodPostCSS = path.join(__dirname, 'fixtures', 'postcss', 'styles.pcss'); const issuesPostCSS = path.join(__dirname, 'fixtures', 'postcss', 'issues.pcss'); @@ -24,6 +27,7 @@ describe('The stylelint provider for Linter', () => { atom.workspace.destroyActivePaneItem(); atom.config.set('linter-stylelint.useStandard', true); atom.config.set('linter-stylelint.disableWhenNoConfig', false); + atom.config.set('linter-stylelint.enableHtmlLinting', false); waitsForPromise(() => Promise.all([ @@ -213,6 +217,34 @@ describe('The stylelint provider for Linter', () => { }); }); + describe('works with HTML files and', () => { + it('works with stylelint-config-standard', () => { + atom.config.set('linter-stylelint.enableHtmlLinting', true); + waitsForPromise(() => + atom.workspace.open(configStandardHtmlPath).then(editor => lint(editor)).then(messages => { + expect(messages.length).toBeGreaterThan(0); + + // test only the first error + expect(messages[0].type).toBe('Error'); + expect(messages[0].severity).toBe('error'); + expect(messages[0].text).toBe('Unexpected empty block (block-no-empty)'); + expect(messages[0].filePath).toBe(configStandardHtmlPath); + expect(messages[0].range).toEqual([[1, 7], [1, 9]]); + }) + ); + }); + + it('finds nothing wrong with a valid file', () => { + atom.config.set('linter-stylelint.enableHtmlLinting', true); + waitsForPromise(() => + atom.workspace.open(goodHtml).then(editor => lint(editor)).then(messages => { + expect(messages.length).toBe(0); + }) + ); + }); + }); + + describe('works with PostCSS files and', () => { it('works with stylelint-config-standard', () => { waitsForPromise(() =>