@@ -4,6 +4,7 @@ import selectorParser = require('postcss-selector-parser');
4
4
import atImport = require( "postcss-import" )
5
5
import path = require( 'node:path' ) ;
6
6
const html = require ( './html' )
7
+ const key = require ( './key' )
7
8
8
9
declare module 'postcss-selector-parser' {
9
10
// For some reasons these aren't avaiblable in this module types
@@ -18,6 +19,7 @@ type Parsed = Record<
18
19
string ,
19
20
{
20
21
tag : string
22
+ rootAttribute : string
21
23
attributes : Record < string , Set < string > >
22
24
booleanAttributes : Set < string >
23
25
properties : Set < string >
@@ -29,7 +31,7 @@ function render(parsed: Parsed): string {
29
31
const jsxElements : Record < string , string [ ] > = { }
30
32
31
33
Object . entries ( parsed ) . forEach (
32
- ( [ key , { tag, attributes, booleanAttributes, properties } ] ) => {
34
+ ( [ key , { tag, rootAttribute , attributes, booleanAttributes, properties } ] ) => {
33
35
const interfaceName = `Mist_${ key } `
34
36
35
37
const attributeEntries = Object . entries ( attributes )
@@ -45,7 +47,9 @@ function render(parsed: Parsed): string {
45
47
const valueType = Array . from ( values )
46
48
. map ( ( v ) => `'${ v } '` )
47
49
. join ( ' | ' )
48
- interfaceDefinition += ` '${ attr } '?: ${ valueType } \n`
50
+ // Root attribute is used to narrow type and therefore is the only attribute
51
+ // that shouldn't be optional (i.e. attr: ... and not attr?: ...)
52
+ interfaceDefinition += ` '${ attr } '${ rootAttribute === attr ? '' : '?' } : ${ valueType } \n`
49
53
} )
50
54
51
55
booleanAttributes . forEach ( ( attr ) => {
@@ -82,23 +86,10 @@ function render(parsed: Parsed): string {
82
86
return interfaceDefinitions + jsxDeclaration
83
87
}
84
88
85
- // Turn button[data-component='foo'] into a key that will be used for the interface name
86
- function key ( selector : selectorParser . Node ) : string {
87
- let key = ''
88
- if ( selector . type === 'tag' ) {
89
- key += selector . toString ( ) . toLowerCase ( )
90
- }
91
- const next = selector . next ( )
92
- if ( next ?. type === 'attribute' ) {
93
- const { attribute, value } = next as selectorParser . Attribute
94
- key += `_${ attribute } _${ value } `
95
- }
96
- return key . replace ( / [ ^ a - z A - Z 0 - 9 _ ] / g, '_' )
97
- }
98
-
99
89
function initialParsedValue ( ) : Parsed [ keyof Parsed ] {
100
90
return {
101
91
tag : '' ,
92
+ rootAttribute : '' ,
102
93
attributes : { } ,
103
94
booleanAttributes : new Set ( ) ,
104
95
properties : new Set ( ) ,
@@ -121,6 +112,11 @@ const _mistcss: PluginCreator<{}> = (_opts = {}) => {
121
112
if ( selector . type === 'tag' ) {
122
113
current = parsed [ key ( selector ) ] = initialParsedValue ( )
123
114
current . tag = selector . toString ( ) . toLowerCase ( )
115
+ const next = selector . next ( )
116
+ if ( next ?. type === 'attribute' ) {
117
+ const { attribute, value } = next as selectorParser . Attribute
118
+ if ( value ) current . rootAttribute = attribute
119
+ }
124
120
}
125
121
126
122
if ( selector . type === 'attribute' ) {
@@ -152,7 +148,7 @@ const _mistcss: PluginCreator<{}> = (_opts = {}) => {
152
148
153
149
_mistcss . postcss = true
154
150
155
- export const mistcss : PluginCreator < { } > = ( _opts = { } ) => {
151
+ const mistcss : PluginCreator < { } > = ( _opts = { } ) => {
156
152
return {
157
153
postcssPlugin : 'mistcss' ,
158
154
plugins : [ atImport ( ) , _mistcss ( ) ]
@@ -161,5 +157,4 @@ export const mistcss: PluginCreator<{}> = (_opts = {}) => {
161
157
162
158
mistcss . postcss = true
163
159
164
- // Needed to make PostCSS happy
165
160
module . exports = mistcss
0 commit comments