15
15
* @import {Nodes, Paragraph} from 'mdast'
16
16
*/
17
17
18
+ import { ccount } from 'ccount'
18
19
import { ok as assert } from 'devlop'
19
20
import { parseEntities } from 'parse-entities'
20
21
import { stringifyEntitiesLight } from 'stringify-entities'
@@ -88,6 +89,16 @@ export function directiveFromMarkdown() {
88
89
*/
89
90
export function directiveToMarkdown ( options ) {
90
91
const settings = options || emptyOptions
92
+ if (
93
+ settings . quote !== '"' &&
94
+ settings . quote !== "'" &&
95
+ settings . quote !== null &&
96
+ settings . quote !== undefined
97
+ ) {
98
+ throw new Error (
99
+ 'Invalid quote `' + settings . quote + '`, expected `\'` or `"`'
100
+ )
101
+ }
91
102
92
103
handleDirective . peek = peekDirective
93
104
@@ -181,12 +192,6 @@ export function directiveToMarkdown(options) {
181
192
* @returns {string }
182
193
*/
183
194
function attributes ( node , state ) {
184
- // If the alternative is less common than `quote`, switch.
185
- const appliedQuote = settings . quote || state . options . quote || '"'
186
- const subset =
187
- node . type === 'textDirective'
188
- ? [ appliedQuote ]
189
- : [ appliedQuote , '\n' , '\r' ]
190
195
const attributes = node . attributes || { }
191
196
/** @type {Array<string> } */
192
197
const values = [ ]
@@ -208,7 +213,9 @@ export function directiveToMarkdown(options) {
208
213
const value = String ( attributes [ key ] )
209
214
210
215
if ( key === 'id' ) {
211
- id = shortcut . test ( value ) ? '#' + value : quoted ( 'id' , value )
216
+ id = shortcut . test ( value )
217
+ ? '#' + value
218
+ : quoted ( 'id' , value , node , state )
212
219
} else if ( key === 'class' ) {
213
220
const list = value . split ( / [ \t \n \r ] + / g)
214
221
/** @type {Array<string> } */
@@ -225,11 +232,11 @@ export function directiveToMarkdown(options) {
225
232
226
233
classesFull =
227
234
classesFullList . length > 0
228
- ? quoted ( 'class' , classesFullList . join ( ' ' ) )
235
+ ? quoted ( 'class' , classesFullList . join ( ' ' ) , node , state )
229
236
: ''
230
237
classes = classesList . length > 0 ? '.' + classesList . join ( '.' ) : ''
231
238
} else {
232
- values . push ( quoted ( key , value ) )
239
+ values . push ( quoted ( key , value , node , state ) )
233
240
}
234
241
}
235
242
}
@@ -247,23 +254,39 @@ export function directiveToMarkdown(options) {
247
254
}
248
255
249
256
return values . length > 0 ? '{' + values . join ( ' ' ) + '}' : ''
257
+ }
250
258
251
- /**
252
- * @param {string } key
253
- * @param {string } value
254
- * @returns {string }
255
- */
256
- function quoted ( key , value ) {
257
- return (
258
- key +
259
- ( value
260
- ? '=' +
261
- appliedQuote +
262
- stringifyEntitiesLight ( value , { subset} ) +
263
- appliedQuote
264
- : '' )
265
- )
266
- }
259
+ /**
260
+ * @param {string } key
261
+ * @param {string } value
262
+ * @param {Directives } node
263
+ * @param {State } state
264
+ * @returns {string }
265
+ */
266
+ function quoted ( key , value , node , state ) {
267
+ if ( ! value ) return key
268
+
269
+ // If the alternative is less common than `quote`, switch.
270
+ const preferred = settings . quote || state . options . quote || '"'
271
+ const alternative = preferred === '"' ? "'" : '"'
272
+ // If the alternative is less common than `quote`, switch.
273
+ const appliedQuote =
274
+ settings . quoteSmart &&
275
+ ccount ( value , preferred ) > ccount ( value , alternative )
276
+ ? alternative
277
+ : preferred
278
+ const subset =
279
+ node . type === 'textDirective'
280
+ ? [ appliedQuote ]
281
+ : [ appliedQuote , '\n' , '\r' ]
282
+
283
+ return (
284
+ key +
285
+ ( '=' +
286
+ appliedQuote +
287
+ stringifyEntitiesLight ( value , { subset} ) +
288
+ appliedQuote )
289
+ )
267
290
}
268
291
}
269
292
0 commit comments