import * as R from 'ramda' ; export type MsaVariable = [ string , string , boolean ] ; export type MsaProperty = Record < string , string > | Record < `@isOptional` , boolean > ; export interface MSABase { properties : Record < string , MsaProperty > ; variables : Record < string , MsaVariable > ; } export interface ParserParams { defValue ? : string ; isOptional : boolean ; value : string ; } interface IsOptional { '@isOptional' : boolean ; } interface ParserValue { ( value ) : MsaProperty | false ; } interface ParseVariable { ( value ) : MsaVariable | false ; } interface ParseProperty { ( value ) : MsaProperty | false ; } const removeSpaces = R . compose ( R . trim , R . replace ( /\s\s+/g , ` ` ) ) ; const isMapped = R . both ( R . is ( String ) , R . includes ( `{` ) ) ; const parseMapped = ( initValue ) => R . pipe ( R . match ( /(?![\s])([\w-]+)[\s:]+([\w-]+)/g ) , R . map ( R . split ( `:` ) ) , R . reduce ( ( acc , [ property , css ] ) => R . assoc ( property , css . trim ( ) , acc ) , initValue ) ) ; const parseMappedValues = ( { value , isOptional } ) => ( isMapped ( value ) && parseMapped ( { '@isOptional' : isOptional } ) ( value ) ) ; const isMultiple = R . both ( R . is ( String ) , R . includes ( `|` ) ) ; const parseMultiple = ( initValue ) => R . pipe ( R . split ( `|` ) , R . reduce ( ( acc , next ) => R . assoc ( removeSpaces ( next ) , removeSpaces ( next ) , acc ) , initValue ) ) ; const parseMultipleValues = ( { value , isOptional } ) => ( isMultiple ( value ) && parseMultiple ( { '@isOptional' : isOptional } ) ( value ) ) ; const parseTernaryValue = ( { value , isOptional } ) => { if ( typeof value !== `string` ) return false ; const chunks = value . split ( /\?|:/ ) ; if ( ! chunks || chunks . length !== 3 ) return false ; const [ test , cssTrue , cssFalse ] = chunks . map ( removeSpaces ) ; return { [ test ] : cssTrue , '@default' : cssFalse , '@isOptional' : isOptional } ; } ; const parseConditionalValue = ( { value , isOptional } ) => { if ( typeof value !== `string` ) return false ; const result = removeSpaces ( value ) . split ( /\s/ ) ; if ( result . length !== 2 ) return false ; const [ test , cssTrue ] = result ; return { [ test ] : cssTrue , '@isOptional' : isOptional } ; } ; const parseSingleValue = ( { defValue , isOptional , value } ) => { if ( typeof value !== `string` ) return false ; const test = removeSpaces ( value ) ; if ( ! test ) return false ; return { [ test ] : defValue , '@isOptional' : isOptional } ; } ; const isVariable = R . both ( R . is ( String ) , R . includes ( `--` ) ) ; export const parseVariable = ( { value , isOptional } ) => { if ( ! isVariable ( value ) ) return false ; const reValue = /(.+)\s+(--[\w-]+)/ ; const [ all , defaultValue , variable ] = reValue . exec ( value ) || [ ] ; return all ? [ removeSpaces ( defaultValue ) , variable , isOptional ] : false ; } ; export const parseProperty = value => ( parseMappedValues ( value ) || parseMultipleValues ( value ) || parseTernaryValue ( value ) || parseConditionalValue ( value ) || parseSingleValue ( value ) ) ;