Skip to content

Commit

Permalink
feat: resolve remark plugin with prefix remark- automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
JounQin committed Aug 22, 2019
1 parent 3b16406 commit 5284395
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 58 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@
"strong": "*"
},
"plugins": [
"remark-preset-lint-recommended",
"remark-preset-lint-markdown-style-guide"
"preset-lint-recommended",
"preset-lint-markdown-style-guide"
]
},
"renovate": {
Expand Down
74 changes: 74 additions & 0 deletions packages/eslint-plugin-mdx/src/rules/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import remarkStringify from 'remark-stringify'
import unified, { Processor } from 'unified'
import remarkMdx from 'remark-mdx'
import remarkParse from 'remark-parse'

import { RemarkConfig } from './types'

import cosmiconfig, { Explorer, CosmiconfigResult } from 'cosmiconfig'

export const requirePkg = (plugin: string, prefix: string) => {
prefix = prefix.endsWith('-') ? prefix : prefix + '-'
const packages = [
plugin,
plugin.startsWith('@')
? plugin.replace('/', '/' + prefix)
: prefix + plugin,
]
let error: Error
for (const pkg of packages) {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
return require(pkg)
} catch (err) {
if (!error) {
error = err
}
}
}
throw error
}

let remarkConfig: Explorer
let remarkProcessor: Processor

export const getRemarkProcessor = (searchFrom: string) => {
if (!remarkConfig) {
remarkConfig = cosmiconfig('remark', {
packageProp: 'remarkConfig',
})
}

if (!remarkProcessor) {
remarkProcessor = unified()
.use(remarkParse)
.freeze()
}

/* istanbul ignore next */
const { plugins = [], settings }: Partial<RemarkConfig> =
(remarkConfig.searchSync(searchFrom) || ({} as CosmiconfigResult)).config ||
{}

// disable this rule automatically since we already have a parser option `extensions`
plugins.push(['lint-file-extension', false])

return plugins
.reduce(
(remarkProcessor, pluginWithSettings) => {
const [plugin, ...pluginSettings] = Array.isArray(pluginWithSettings)
? pluginWithSettings
: [pluginWithSettings]
return remarkProcessor.use(
/* istanbul ignore next */
typeof plugin === 'string' ? requirePkg(plugin, 'remark') : plugin,
...pluginSettings,
)
},
remarkProcessor()
.use({ settings })
.use(remarkStringify)
.use(remarkMdx),
)
.freeze()
}
1 change: 1 addition & 0 deletions packages/eslint-plugin-mdx/src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { noUnescapedEntities } from './no-unescaped-entities'
import { noUnusedExpressions } from './no-unused-expressions'
import { remark } from './remark'

export * from './helper'
export * from './types'

export { noJsxHtmlComments, noUnescapedEntities, noUnusedExpressions, remark }
Expand Down
59 changes: 3 additions & 56 deletions packages/eslint-plugin-mdx/src/rules/remark.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,12 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../../typings.d.ts" />

import path from 'path'

import remarkStringify from 'remark-stringify'
import unified, { Processor } from 'unified'
import remarkMdx from 'remark-mdx'
import remarkParse from 'remark-parse'
import vfile from 'vfile'
import { DEFAULT_EXTENSIONS } from 'eslint-mdx'
import vfile from 'vfile'

import { RemarkConfig } from './types'
import { getRemarkProcessor } from './helper'

import cosmiconfig, { Explorer, CosmiconfigResult } from 'cosmiconfig'
import { Rule } from 'eslint'

let remarkConfig: Explorer
let remarkProcessor: Processor

const getRemarkProcessor = (searchFrom: string, extname: string) => {
if (!remarkConfig) {
remarkConfig = cosmiconfig('remark', {
packageProp: 'remarkConfig',
})
}

if (!remarkProcessor) {
remarkProcessor = unified()
.use(remarkParse)
.freeze()
}

/* istanbul ignore next */
const { plugins = [], settings }: Partial<RemarkConfig> =
(remarkConfig.searchSync(searchFrom) || ({} as CosmiconfigResult)).config ||
{}

// disable this rule automatically since we have a parser option `extensions`
plugins.push(['remark-lint-file-extension', extname.slice(1)])

return plugins
.reduce(
(remarkProcessor, pluginWithSettings) => {
const [plugin, ...pluginSettings] = Array.isArray(pluginWithSettings)
? pluginWithSettings
: [pluginWithSettings]
return remarkProcessor.use(
/* istanbul ignore next */
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
typeof plugin === 'string' ? require(plugin) : plugin,
...pluginSettings,
)
},
remarkProcessor()
.use({ settings })
.use(remarkStringify)
.use(remarkMdx),
)
.freeze()
}

export const remark: Rule.RuleModule = {
meta: {
type: 'layout',
Expand Down Expand Up @@ -88,7 +35,7 @@ export const remark: Rule.RuleModule = {
return
}
const sourceText = sourceCode.getText(node)
const remarkProcessor = getRemarkProcessor(filename, extname)
const remarkProcessor = getRemarkProcessor(filename)
const file = remarkProcessor.processSync(
vfile({
path: filename,
Expand Down
12 changes: 12 additions & 0 deletions test/helper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { requirePkg } from 'eslint-plugin-mdx'

describe('Helpers', () => {
it('should resolve package correctly', () => {
expect(requirePkg('@1stg/config', 'husky')).toBeDefined()
expect(requirePkg('lint', 'remark')).toBeDefined()
expect(requirePkg('remark-parse', 'non existed')).toBeDefined()
})

it('should throw on non existed package', () =>
expect(() => requirePkg('@1stg/config', 'unexpected-')).toThrow())
})

0 comments on commit 5284395

Please sign in to comment.