import * as messages from '@cucumber/messages' ; import IGherkinDocument = messages . GherkinDocument ; export default function compile ( gherkinDocument , uri , newId ) { const pickles = [ ] ; if ( gherkinDocument . feature == null ) { return pickles ; } const feature = gherkinDocument . feature ; const language = feature . language ; const featureTags = feature . tags ; let featureBackgroundSteps = [ ] ; feature . children . forEach ( ( stepsContainer ) => { if ( stepsContainer . background ) { featureBackgroundSteps = [ ] . concat ( stepsContainer . background . steps ) ; } else if ( stepsContainer . rule ) { compileRule ( featureTags , featureBackgroundSteps , stepsContainer . rule , language , pickles , uri , newId ) ; } else if ( stepsContainer . scenario . examples . length === 0 ) { compileScenario ( featureTags , featureBackgroundSteps , stepsContainer . scenario , language , pickles , uri , newId ) ; } else { compileScenarioOutline ( featureTags , featureBackgroundSteps , stepsContainer . scenario , language , pickles , uri , newId ) ; } } ) ; return pickles ; } function compileRule ( featureTags , featureBackgroundSteps , rule , language , pickles , uri , newId ) { let ruleBackgroundSteps = [ ] . concat ( featureBackgroundSteps ) ; const tags = [ ] . concat ( featureTags ) . concat ( rule . tags ) ; rule . children . forEach ( ( stepsContainer ) => { if ( stepsContainer . background ) { ruleBackgroundSteps = ruleBackgroundSteps . concat ( stepsContainer . background . steps ) ; } else if ( stepsContainer . scenario . examples . length === 0 ) { compileScenario ( tags , ruleBackgroundSteps , stepsContainer . scenario , language , pickles , uri , newId ) ; } else { compileScenarioOutline ( featureTags , ruleBackgroundSteps , stepsContainer . scenario , language , pickles , uri , newId ) ; } } ) ; } function compileScenario ( inheritedTags , backgroundSteps , scenario , language , pickles , uri , newId ) { const steps = scenario . steps . length === 0 ? [ ] : backgroundSteps . map ( ( step ) => pickleStep ( step , [ ] , null , newId ) ) ; const tags = [ ] . concat ( inheritedTags ) . concat ( scenario . tags ) ; scenario . steps . forEach ( ( step ) => steps . push ( pickleStep ( step , [ ] , null , newId ) ) ) ; const pickle = { id : newId ( ) , uri , astNodeIds : [ scenario . id ] , tags : pickleTags ( tags ) , name : scenario . name , language , steps , } ; pickles . push ( pickle ) ; } function compileScenarioOutline ( inheritedTags , backgroundSteps , scenario , language , pickles , uri , newId ) { scenario . examples . filter ( ( e ) => e . tableHeader ) . forEach ( ( examples ) => { const variableCells = examples . tableHeader . cells ; examples . tableBody . forEach ( ( valuesRow ) => { const steps = scenario . steps . length === 0 ? [ ] : backgroundSteps . map ( ( step ) => pickleStep ( step , [ ] , null , newId ) ) ; scenario . steps . forEach ( ( scenarioOutlineStep ) => { const step = pickleStep ( scenarioOutlineStep , variableCells , valuesRow , newId ) ; steps . push ( step ) ; } ) ; const id = newId ( ) ; const tags = pickleTags ( [ ] . concat ( inheritedTags ) . concat ( scenario . tags ) . concat ( examples . tags ) ) ; pickles . push ( { id , uri , astNodeIds : [ scenario . id , valuesRow . id ] , name : interpolate ( scenario . name , variableCells , valuesRow . cells ) , language , steps , tags , } ) ; } ) ; } ) ; } function createPickleArguments ( step , variableCells , valueCells ) { if ( step . dataTable ) { const argument = step . dataTable ; const table = { rows : argument . rows . map ( ( row ) => { return { cells : row . cells . map ( ( cell ) => { return { value : interpolate ( cell . value , variableCells , valueCells ) , } ; } ) , } ; } ) , } ; return { dataTable : table } ; } else if ( step . docString ) { const argument = step . docString ; const docString = { content : interpolate ( argument . content , variableCells , valueCells ) , } ; if ( argument . mediaType ) { docString . mediaType = interpolate ( argument . mediaType , variableCells , valueCells ) ; } return { docString } ; } } function interpolate ( name , variableCells , valueCells ) { variableCells . forEach ( ( variableCell , n ) => { const valueCell = valueCells [ n ] ; const valuePattern = '<' + variableCell . value + '>' ; const escapedPattern = valuePattern . replace ( /[-/\\^$*+?.()|[\]{}]/g , '\\$&' ) ; const regexp = new RegExp ( escapedPattern , 'g' ) ; const replacement = valueCell . value . replace ( new RegExp ( '\\$' , 'g' ) , '$$$$' ) ; name = name . replace ( regexp , replacement ) ; } ) ; return name ; } function pickleStep ( step , variableCells , valuesRow , newId ) { const astNodeIds = [ step . id ] ; if ( valuesRow ) { astNodeIds . push ( valuesRow . id ) ; } const valueCells = valuesRow ? valuesRow . cells : [ ] ; return { id : newId ( ) , text : interpolate ( step . text , variableCells , valueCells ) , argument : createPickleArguments ( step , variableCells , valueCells ) , astNodeIds : astNodeIds , } ; } function pickleTags ( tags ) { return tags . map ( pickleTag ) ; } function pickleTag ( tag ) { return { name : tag . name , astNodeId : tag . id , } ; }