@@ -4,8 +4,6 @@ import path from 'node:path'
44import { pathToFileURL } from 'node:url'
55
66import type { Token , TokenType , tokTypes as _tokTypes } from 'acorn'
7- import { cosmiconfig } from 'cosmiconfig'
8- import type { CosmiconfigResult } from 'cosmiconfig/dist/types'
97import type { AST } from 'eslint'
108import type { EsprimaToken } from 'espree/lib/token-translator'
119import type {
@@ -26,27 +24,22 @@ import type {
2624import type { Options } from 'micromark-extension-mdx-expression'
2725import type { Root } from 'remark-mdx'
2826import { extractProperties , runAsWorker } from 'synckit'
29- import type { FrozenProcessor , Plugin } from 'unified'
27+ import type { FrozenProcessor } from 'unified'
28+ import type { Config , Configuration } from 'unified-engine/lib/configuration'
3029import type { Node } from 'unist'
3130import { ok as assert } from 'uvu/assert'
3231import type { VFileMessage } from 'vfile-message'
3332
3433import {
35- arrayify ,
3634 loadEsmModule ,
3735 nextCharOffsetFactory ,
3836 normalizePosition ,
3937 prevCharOffsetFactory ,
40- requirePkg ,
4138} from './helpers'
4239import { restoreTokens } from './tokens'
43- import type {
44- NormalPosition ,
45- RemarkConfig ,
46- RemarkPlugin ,
47- WorkerOptions ,
48- WorkerResult ,
49- } from './types'
40+ import type { NormalPosition , WorkerOptions , WorkerResult } from './types'
41+
42+ let config : Configuration
5043
5144let acorn : typeof import ( 'acorn' )
5245let acornJsx : {
@@ -60,12 +53,29 @@ let tt: Record<string, TokenType> & typeof _tokTypes
6053
6154let TokenTranslator : typeof import ( 'espree/lib/token-translator' ) [ 'default' ]
6255
63- const explorer = cosmiconfig ( 'remark' , {
64- packageProp : 'remarkConfig' ,
65- } )
66-
6756export const processorCache = new Map < string , FrozenProcessor > ( )
6857
58+ const getRemarkConfig = async ( searchFrom : string ) => {
59+ if ( ! config ) {
60+ const { Configuration } = await loadEsmModule <
61+ typeof import ( 'unified-engine/lib/configuration' )
62+ > ( 'unified-engine/lib/configuration.js' )
63+ config = new Configuration ( {
64+ cwd : process . cwd ( ) ,
65+ packageField : 'remarkConfig' ,
66+ pluginPrefix : 'remark' ,
67+ rcName : '.remarkrc' ,
68+ detectConfig : true ,
69+ } )
70+ }
71+
72+ return new Promise < Config > ( ( resolve , reject ) =>
73+ config . load ( searchFrom , ( error , result ) =>
74+ error ? reject ( error ) : resolve ( result ) ,
75+ ) ,
76+ )
77+ }
78+
6979const getRemarkMdxOptions = ( tokens : Token [ ] ) : Options => ( {
7080 acorn : acornParser ,
7181 acornOptions : {
@@ -83,7 +93,6 @@ export const getRemarkProcessor = async (
8393 searchFrom : string ,
8494 isMdx : boolean ,
8595 ignoreRemarkConfig ?: boolean ,
86- // eslint-disable-next-line sonarjs/cognitive-complexity
8796) => {
8897 const initCacheKey = `${ String ( isMdx ) } -${ searchFrom } `
8998
@@ -93,12 +102,10 @@ export const getRemarkProcessor = async (
93102 return cachedProcessor
94103 }
95104
96- const result : CosmiconfigResult = ignoreRemarkConfig
97- ? null
98- : await explorer . search ( searchFrom )
105+ const result = ignoreRemarkConfig ? null : await getRemarkConfig ( searchFrom )
99106
100- const cacheKey = result
101- ? `${ String ( isMdx ) } -${ result . filepath } `
107+ const cacheKey = result ?. filePath
108+ ? `${ String ( isMdx ) } -${ result . filePath } `
102109 : String ( isMdx )
103110
104111 cachedProcessor = processorCache . get ( cacheKey )
@@ -120,19 +127,23 @@ export const getRemarkProcessor = async (
120127
121128 const remarkProcessor = unified ( ) . use ( remarkParse ) . freeze ( )
122129
123- if ( result ) {
124- /* istanbul ignore next */
125- const { plugins = [ ] , settings } =
126- // type-coverage:ignore-next-line -- cosmiconfig's typings issue
127- ( result . config || { } ) as Partial < RemarkConfig >
130+ if ( result ?. filePath ) {
131+ const { plugins, settings } = result
128132
129133 // disable this rule automatically since we already have a parser option `extensions`
130134 // only disable this plugin if there are at least one plugin enabled
131135 // otherwise it is redundant
132136 /* istanbul ignore else */
133137 if ( plugins . length > 0 ) {
134138 try {
135- plugins . push ( [ await requirePkg ( 'lint-file-extension' , 'remark' ) , false ] )
139+ plugins . push ( [
140+ (
141+ await loadEsmModule < typeof import ( 'remark-lint-file-extension' ) > (
142+ 'remark-lint-file-extension' ,
143+ )
144+ ) . default ,
145+ false ,
146+ ] )
136147 } catch {
137148 // just ignore if the package does not exist
138149 }
@@ -146,21 +157,9 @@ export const getRemarkProcessor = async (
146157 initProcessor . use ( remarkMdx , getRemarkMdxOptions ( sharedTokens ) )
147158 }
148159
149- cachedProcessor = (
150- await plugins . reduce ( async ( processor , pluginWithSettings ) => {
151- const [ plugin , ...pluginSettings ] = arrayify ( pluginWithSettings ) as [
152- RemarkPlugin ,
153- ...unknown [ ] ,
154- ]
155- return ( await processor ) . use (
156- /* istanbul ignore next */
157- typeof plugin === 'string'
158- ? await requirePkg < Plugin > ( plugin , 'remark' , result . filepath )
159- : plugin ,
160- ...pluginSettings ,
161- )
162- } , Promise . resolve ( initProcessor ) )
163- ) . freeze ( )
160+ cachedProcessor = plugins
161+ . reduce ( ( processor , plugin ) => processor . use ( ...plugin ) , initProcessor )
162+ . freeze ( )
164163 } else {
165164 const initProcessor = remarkProcessor ( ) . use ( remarkStringify )
166165
0 commit comments