markuplint
Advanced tools
Comparing version 0.16.2 to 0.17.0
#!/usr/bin/env node | ||
const meow = require('meow'); | ||
const getStdin = require('get-stdin'); | ||
@@ -14,5 +15,9 @@ const { verify, verifyFile } = require('../lib/'); | ||
Options | ||
--ruleset, -r Ruleset file path | ||
--no-color, -c output no color | ||
--ruleset, -r Ruleset file path. | ||
--no-color, -c Output no color. | ||
--format, -f FORMAT Output format. Support "JSON" only. Default "JSON". | ||
--help, -h Show help. | ||
--version, -v Show version. | ||
Examples | ||
@@ -22,13 +27,16 @@ $ markuplint verifyee.html --ruleset path/to/.markuplintrc | ||
`, | ||
{ | ||
flags: { | ||
ruleset: { | ||
type: 'string', | ||
alias: 'r', | ||
}, | ||
'no-color': { | ||
alias: 'c', | ||
}, | ||
{ | ||
flags: { | ||
ruleset: { | ||
type: 'string', | ||
alias: 'r', | ||
}, | ||
} | ||
'no-color': { | ||
alias: 'c', | ||
}, | ||
format: { | ||
alias: 'f', | ||
}, | ||
}, | ||
} | ||
); | ||
@@ -47,28 +55,39 @@ | ||
for (const filePath of cli.input) { | ||
const { html, reports } = await verifyFile(filePath, cli.flags.ruleset); | ||
await standardReporter(filePath, reports, html, !cli.flags.noColor); | ||
const { html, reports } = await verifyFile(filePath, null, cli.flags.ruleset); | ||
await output(filePath, reports, html, cli.flags); | ||
} | ||
process.stdout.write('🎉 markuplint CLI done.'); | ||
})(); | ||
} else { | ||
stdinStopWhenEmpty(); | ||
const readline = require('readline'); | ||
const { getRuleset } = require('../lib/ruleset'); | ||
const { getRuleModules } = require('../lib/rule'); | ||
const lines = []; | ||
const reader = readline.createInterface({ input: process.stdin }); | ||
reader.on('line', lines.push); | ||
reader.on('close', async () => { | ||
const html = lines.join('\n'); | ||
const ruleset = cli.flags.ruleset || await getRuleset(process.cwd()); | ||
const rules = await getRuleModules(); | ||
const reports = await verify(html, ruleset, rules); | ||
await standardReporter('STDIN_DATA', reports, html); | ||
}); | ||
} | ||
/** */ | ||
function stdinStopWhenEmpty () { | ||
const id = setImmediate(() => cli.showHelp()); | ||
process.stdin.on('data', () => clearImmediate(id)); | ||
getStdin().then(async (stdin) => { | ||
const Ruleset = require('../lib/ruleset/').default; | ||
const { getRuleModules } = require('../lib/rule'); | ||
const html = stdin; | ||
if (!html) { | ||
return; | ||
} | ||
const rules = await getRuleModules(); | ||
const ruleset = await Ruleset.create(cli.flags.ruleset || process.cwd(), rules); | ||
const reports = await verify(html, ruleset, rules); | ||
await output('STDIN_DATA', reports, html, cli.flags); | ||
}); | ||
/** | ||
* | ||
*/ | ||
async function output (filePath, reports, html, flags) { | ||
if (flags.format) { | ||
const format = flags.format === true ? 'json' : flags.format; | ||
switch (format.toLowerCase()) { | ||
case 'json': { | ||
process.stdout.write(JSON.stringify(reports, null, 2)); | ||
break; | ||
} | ||
default: { | ||
throw new Error(`Unsupported output format "${cli.flags.format}"`); | ||
} | ||
} | ||
} else { | ||
await standardReporter(filePath, reports, html, !flags.noColor); | ||
} | ||
} |
import { CustomRule, VerifiedResult } from './rule'; | ||
import { ConfigureFileJSON } from './ruleset'; | ||
import { ConfigureFileJSON } from './ruleset/JSONInterface'; | ||
export declare function verify(html: string, config: ConfigureFileJSON, rules: CustomRule[], locale?: string): Promise<VerifiedResult[]>; | ||
export declare function verifyOnWorkspace(html: string, workspace?: string): Promise<VerifiedResult[]>; | ||
export declare function verifyFile(filePath: string, rules?: CustomRule[], locale?: string): Promise<{ | ||
export declare function verifyFile(filePath: string, rules?: CustomRule[], configFileOrDir?: string, locale?: string): Promise<{ | ||
html: string; | ||
reports: VerifiedResult[]; | ||
}>; |
@@ -29,11 +29,17 @@ "use strict"; | ||
exports.verifyOnWorkspace = verifyOnWorkspace; | ||
async function verifyFile(filePath, rules, locale) { | ||
async function verifyFile(filePath, rules, configFileOrDir, locale) { | ||
if (!locale) { | ||
locale = await osLocale_1.default(); | ||
} | ||
const absFilePath = path.resolve(filePath); | ||
const parsedPath = path.parse(absFilePath); | ||
const dir = path.dirname(absFilePath); | ||
rules = rules || await rule_1.getRuleModules(); | ||
const ruleset = await ruleset_1.default.create(dir, rules); | ||
let ruleset; | ||
if (configFileOrDir) { | ||
ruleset = await ruleset_1.default.create(configFileOrDir, rules); | ||
} | ||
else { | ||
const absFilePath = path.resolve(filePath); | ||
const parsedPath = path.parse(absFilePath); | ||
const dir = path.dirname(absFilePath); | ||
ruleset = await ruleset_1.default.create(dir, rules); | ||
} | ||
const html = await readFile(filePath, 'utf-8'); | ||
@@ -40,0 +46,0 @@ const core = new core_1.default(html, ruleset, locale); |
@@ -1,2 +0,3 @@ | ||
import Ruleset, { ConfigureFileJSONRules } from '../ruleset'; | ||
import Ruleset from '../ruleset'; | ||
import { ConfigureFileJSONRules } from '../ruleset/JSONInterface'; | ||
import { CustomRule, RuleConfig } from '../rule'; | ||
@@ -3,0 +4,0 @@ export interface Location { |
import { Document } from './parser'; | ||
import Ruleset, { ConfigureFileJSONRuleOption } from './ruleset'; | ||
import Ruleset from './ruleset'; | ||
import { ConfigureFileJSONRuleOption } from './ruleset/JSONInterface'; | ||
export interface VerifyReturn { | ||
@@ -4,0 +5,0 @@ level: RuleLevel; |
import { CustomRule } from '../../rule'; | ||
declare const _default: CustomRule<null, null>; | ||
export declare type Value = 'always' | 'never'; | ||
declare const _default: CustomRule<Value, null>; | ||
export default _default; |
@@ -6,21 +6,43 @@ "use strict"; | ||
exports.default = rule_1.CustomRule.create({ | ||
name: 'name', | ||
defaultValue: null, | ||
name: 'async-attr-in-script', | ||
defaultLevel: 'warning', | ||
defaultValue: 'always', | ||
defaultOptions: null, | ||
async verify(document, locale) { | ||
const reports = []; | ||
const message = await messages_1.default(locale, 'error'); | ||
await document.walkOn('Node', async (node) => { | ||
await document.walkOn('Element', async (node) => { | ||
if (!node.rule) { | ||
return; | ||
} | ||
if (true) { | ||
// reports.push({ | ||
// level: node.rule.level, | ||
// message, | ||
// line: node.line, | ||
// col: node.col, | ||
// raw: node.raw, | ||
// }); | ||
if (!node.hasAttribute('src')) { | ||
return; | ||
} | ||
const hasAsyncAttr = !node.hasAttribute('async'); | ||
let bad = false; | ||
let necessary; | ||
switch (node.rule.value) { | ||
case 'always': { | ||
necessary = 'Required {0}'; | ||
bad = hasAsyncAttr; | ||
break; | ||
} | ||
case 'never': { | ||
necessary = 'Not required {0}'; | ||
bad = !hasAsyncAttr; | ||
break; | ||
} | ||
default: { | ||
return; | ||
} | ||
} | ||
if (bad) { | ||
const message = await messages_1.default(locale, necessary, '{$} attribute'); | ||
reports.push({ | ||
level: node.rule.level, | ||
message: message.replace('{$}', 'async'), | ||
line: node.line, | ||
col: node.col, | ||
raw: node.raw, | ||
}); | ||
} | ||
}); | ||
@@ -27,0 +49,0 @@ return reports; |
@@ -1,3 +0,75 @@ | ||
# markuplint-rule-async-attr-in-script | ||
# scriptタグのasync属性 (`async-attr-in-script`) | ||
WIP | ||
scriptタグの**async属性**の設定・非設定を警告します。 | ||
> Scripts without async or defer attributes, as well as inline scripts, are fetched and executed immediately, before the browser continues to parse the page. | ||
> [cite: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Script#Notes] | ||
> | ||
> async 属性または defer 属性を持たない script はインラインスクリプト同様に、ブラウザーがページの解析を続けるより先に、ただちに読み込みおよび実行されます。 | ||
> [引用: https://developer.mozilla.org/ja/docs/Web/HTML/Element/Script#Notes] | ||
## ルールの詳細 | ||
👎 間違ったコード例 | ||
`{ "async-attr-in-script": "always" }` | ||
```html | ||
<script src="path/to"></script> | ||
``` | ||
`{ "async-attr-in-script": "naver" }` | ||
```html | ||
<script async src="path/to"></script> | ||
``` | ||
👍 正しいコード例 | ||
`{ "async-attr-in-script": "always" }` | ||
```html | ||
<script async src="path/to"></script> | ||
``` | ||
`{ "async-attr-in-script": "naver" }` | ||
```html | ||
<script src="path/to"></script> | ||
``` | ||
### オプション | ||
設定値|デフォルト|解説 | ||
---|---|--- | ||
`"always"`|✓|async属性がないと警告します。 | ||
`"never"`||async属性があると警告します。 | ||
### デフォルトの警告レベル | ||
`warning` | ||
## 設定例 | ||
外部ライブラリを利用する場合、定義順の関係で`async`属性を指定すると問題が起こる場合があります。その場合は、`nodeRules`経由でフィルタリングするとことができます。次の例は、jQueryライブラリのタグの警告をさけるために`nodeRules`にセレクタ`script[src*="jquery" i]`で絞込み、`"never"`を再設定(上書き)しています。 | ||
```html | ||
<script src="lib/jquery.min.js"></script> | ||
<script async src="main.js"></script> | ||
``` | ||
```json | ||
{ | ||
"rules": { | ||
"async-attr-in-script": "always", | ||
}, | ||
"nodeRules": [ | ||
{ | ||
"selector": "script[src*=\"jquery\"]", | ||
"rules": { | ||
"async-attr-in-script": "never" | ||
} | ||
} | ||
] | ||
} | ||
``` |
{ | ||
"$schema": "./$schema.json#", | ||
"keywords": { | ||
"tag": "タグ", | ||
"tag name": "タグ名", | ||
"attribute": "属性", | ||
"attributes": "属性", | ||
"attribute name": "属性名", | ||
"attribute value": "属性値", | ||
"attribute id value": "id属性の値", | ||
"element": "要素", | ||
"quote": "囲う", | ||
"double quotation mark": "ダブルクオーテーション", | ||
"single quotation mark": "シングルクォーテーション", | ||
"lowercase": "小文字", | ||
"uppercase": "大文字", | ||
"illegal characters": "不正な文字", | ||
"escape in character reference": "参照文字でエスケープ", | ||
"deprecated": "非推奨", | ||
"indentation": "インデント", | ||
"tab": "タブ", | ||
"space": "スペース" | ||
}, | ||
"{0} is {1}": "{0}は{1}です。", | ||
"Duplicate {0}": "{0}が重複しています。", | ||
"{0} is must {1} on {2}": "{0}は{2}で{1}べきです。", | ||
"{0} must {1}": "{0}は{1}するべきです。", | ||
"{0} should {1}": "{0}は{1}してください。", | ||
"{0} must be {1}": "{0}は{1}にするべきです。", | ||
"{0} should be {1}": "{0}は{1}にしてください。", | ||
"{0} of {1} must be {2}": "{1}の{0}は{2}にするべきです。", | ||
"{0} of {1} should be {2}": "{1}の{0}は{2}にしてください。", | ||
"Values allowed for {0} attributes are {$}": "{0}属性に許可される値は{$}です。", | ||
"{0} width spaces": "{0}幅スペース" | ||
"$schema": "./$schema.json#", | ||
"keywords": { | ||
"tag": "タグ", | ||
"tag name": "タグ名", | ||
"attribute": "属性", | ||
"attributes": "属性", | ||
"attribute name": "属性名", | ||
"attribute value": "属性値", | ||
"attribute id value": "id属性の値", | ||
"{$} attribute": "{$}属性", | ||
"element": "要素", | ||
"quote": "囲う", | ||
"double quotation mark": "ダブルクオーテーション", | ||
"single quotation mark": "シングルクォーテーション", | ||
"lowercase": "小文字", | ||
"uppercase": "大文字", | ||
"illegal characters": "不正な文字", | ||
"escape in character reference": "参照文字でエスケープ", | ||
"deprecated": "非推奨", | ||
"indentation": "インデント", | ||
"tab": "タブ", | ||
"space": "スペース" | ||
}, | ||
"{0} is {1}": "{0}は{1}です。", | ||
"Required {0}": "{0}が必要です", | ||
"Not required {0}": "{0}は不要です", | ||
"Duplicate {0}": "{0}が重複しています。", | ||
"{0} is must {1} on {2}": "{0}は{2}で{1}べきです。", | ||
"{0} must {1}": "{0}は{1}するべきです。", | ||
"{0} should {1}": "{0}は{1}してください。", | ||
"{0} must be {1}": "{0}は{1}にするべきです。", | ||
"{0} should be {1}": "{0}は{1}にしてください。", | ||
"{0} of {1} must be {2}": "{1}の{0}は{2}にするべきです。", | ||
"{0} of {1} should be {2}": "{1}の{0}は{2}にしてください。", | ||
"Values allowed for {0} attributes are {$}": "{0}属性に許可される値は{$}です。", | ||
"{0} width spaces": "{0}幅スペース" | ||
} |
@@ -51,3 +51,2 @@ # Rules | ||
- [class-naming](./markuplint-rule-class-naming/README.ja.md) クラス名 (🚧 WIP) | ||
- [required-class-elements](./markuplint-rule-required-class-elements/README.ja.md) クラスの有無 (🚧 WIP) | ||
- bem/markuplint-rule-bem-rule-nesting BEMの入れ子関係 (🚧 WIP) | ||
@@ -54,0 +53,0 @@ - bem/markuplint-rule-bem-rule-block BEMのBlockの要素名/クラス名/属性 (🚧 WIP) |
@@ -51,3 +51,2 @@ # Rules | ||
- [🚧 WIP] [class-naming](./markuplint-rule-class-naming/README.md) | ||
- [🚧 WIP] [required-class-elements](./markuplint-rule-required-class-elements/README.md) | ||
- [🚧 WIP] bem/markuplint-rule-bem-rule-nesting | ||
@@ -54,0 +53,0 @@ - [🚧 WIP] bem/markuplint-rule-bem-rule-block |
{ | ||
"name": "markuplint", | ||
"version": "0.16.2", | ||
"version": "0.17.0", | ||
"description": "HTML linter for legacy/modern HTML, Web Components, SVG, MathML, AMP HTML and more.", | ||
@@ -32,2 +32,3 @@ "main": "lib/index.js", | ||
"find-node-modules": "^1.0.4", | ||
"get-stdin": "^5.0.1", | ||
"meow": "^4.0.0", | ||
@@ -48,3 +49,3 @@ "os-locale": "^2.1.0", | ||
"del": "^3.0.0", | ||
"eslint": "^4.15.0", | ||
"eslint": "^4.16.0", | ||
"gulp": "^4.0.0", | ||
@@ -51,0 +52,0 @@ "gulp-typescript": "^4.0.0-alpha.1", |
@@ -25,13 +25,17 @@ ![markuplint](media/logo-v.svg) | ||
Usage | ||
$ markuplint <HTML file> | ||
$ <stdout> | markuplint | ||
Usage | ||
$ markuplint <HTML file> | ||
$ <stdout> | markuplint | ||
Options | ||
--ruleset, -r Ruleset file path | ||
--no-color, -c output no color | ||
Options | ||
--ruleset, -r Ruleset file path. | ||
--no-color, -c Output no color. | ||
--format, -f FORMAT Output format. Support "JSON" only. Default "JSON". | ||
Examples | ||
$ markuplint verifyee.html --ruleset path/to/.markuplintrc | ||
$ cat verifyee.html | markuplint | ||
--help, -h Show help. | ||
--version, -v Show version. | ||
Examples | ||
$ markuplint verifyee.html --ruleset path/to/.markuplintrc | ||
$ cat verifyee.html | markuplint | ||
``` | ||
@@ -38,0 +42,0 @@ |
390235
331
10165
97
10
+ Addedget-stdin@^5.0.1
+ Addedget-stdin@5.0.1(transitive)