@@ -12,40 +12,69 @@ import { RuleHelper } from "textlint-rule-helper";
12
12
export function checkPair ( context , { left, right } ) {
13
13
assert ( left ) ;
14
14
assert ( right ) ;
15
- let { Syntax, RuleError, report, getSource } = context ;
16
- let helper = new RuleHelper ( context ) ;
15
+ const { Syntax, RuleError, report, getSource } = context ;
16
+ const helper = new RuleHelper ( context ) ;
17
17
let isInParagraph = false ;
18
18
let currentStrInParagraph = [ ] ;
19
19
/**
20
20
* `Str` nodeの配列を受け取り、pairが見つからないnodeを返す
21
21
* @param {Object } currentStrInParagraph
22
22
* @returns {{node, index}[] }
23
23
*/
24
+ const findAllSymbolLocations = ( symbol , text ) => {
25
+ let index = 0 ;
26
+ const symbolLocations = [ ] ;
27
+ while ( index < text . length ) {
28
+ index = text . indexOf ( symbol , index ) ;
29
+ if ( index < 0 ) break ;
30
+ symbolLocations . push ( {
31
+ index,
32
+ symbol
33
+ } ) ;
34
+ index += 1 ;
35
+ }
36
+ return symbolLocations ;
37
+ } ;
24
38
const foundMissingPairNodes = ( currentStrInParagraph ) => {
25
- let foundLeft = false ;
26
- let matchParentheses = [ ] ;
27
- currentStrInParagraph . forEach ( ( node ) => {
28
- const text = getSource ( node ) ;
29
- // left を探す
30
- let leftIndex = - 1 ;
31
- if ( ! foundLeft ) {
32
- leftIndex = text . indexOf ( left ) ;
33
- if ( leftIndex !== - 1 ) {
34
- matchParentheses . push ( {
35
- node,
36
- index : leftIndex
37
- } ) ;
38
- foundLeft = true ;
39
- }
39
+ let matchParentheses = currentStrInParagraph
40
+ . map ( ( node ) => {
41
+ let text = getSource ( node ) ;
42
+ const leftSymbolLocations = findAllSymbolLocations ( left , text ) ;
43
+ const rightSymbolLocations = left !== right ? findAllSymbolLocations ( right , text ) : [ ] ;
44
+ const allSymbolLocations = [ ...leftSymbolLocations , ...rightSymbolLocations ] . sort (
45
+ ( a , b ) => a . index - b . index
46
+ ) ;
47
+ return allSymbolLocations . map ( ( loc ) => ( { ...loc , ...{ node } } ) ) ;
48
+ } )
49
+ . flat ( ) ;
50
+ if ( left === right ) {
51
+ const isCompletedParentheses = matchParentheses . length % 2 == 0 ;
52
+ if ( isCompletedParentheses ) {
53
+ return [ ] ;
54
+ } else {
55
+ return [ matchParentheses [ matchParentheses . length - 1 ] ] ;
40
56
}
41
- // right を探す
42
- let pairIndex = text . indexOf ( right , leftIndex + 1 ) ;
43
- if ( pairIndex !== - 1 ) {
44
- matchParentheses . pop ( ) ;
45
- foundLeft = false ;
57
+ } else {
58
+ const lastUnmatchParences = [ ] ;
59
+ while ( matchParentheses . length > 0 ) {
60
+ const item = matchParentheses . shift ( ) ;
61
+ if ( item . symbol == left ) {
62
+ lastUnmatchParences . push ( item ) ;
63
+ } else {
64
+ // right
65
+ const last = lastUnmatchParences . pop ( ) ;
66
+ if ( last ) {
67
+ if ( last . symbol == right ) {
68
+ lastUnmatchParences . push ( last ) ;
69
+ lastUnmatchParences . push ( item ) ;
70
+ }
71
+ } else {
72
+ lastUnmatchParences . push ( item ) ;
73
+ }
74
+ }
46
75
}
47
- } ) ;
48
- return matchParentheses ;
76
+ return lastUnmatchParences ;
77
+ }
49
78
} ;
50
79
return {
51
80
[ Syntax . Paragraph ] ( node ) {
@@ -69,13 +98,12 @@ export function checkPair(context, { left, right }) {
69
98
if ( missingPairList . length === 0 ) {
70
99
return ;
71
100
}
72
- missingPairList . forEach ( ( { node, index } ) => {
73
- report (
74
- node ,
75
- new RuleError ( `${ left } の対となる${ right } が見つかりません。${ left } ${ right } ` , {
76
- index
77
- } )
78
- ) ;
101
+ missingPairList . forEach ( ( { index, node, symbol } ) => {
102
+ let message =
103
+ symbol === left
104
+ ? `${ left } の対となる${ right } が見つかりません。${ left } ${ right } `
105
+ : `${ right } の対となる${ left } が見つかりません。${ left } ${ right } ` ;
106
+ report ( node , new RuleError ( message , { index } ) ) ;
79
107
} ) ;
80
108
}
81
109
} ;
0 commit comments