1- import fs from "fs" ;
2- import readline from "readline" ;
31import parseArgs from "minimist" ;
2+ import { fromStdin , fromFile } from "./input" ;
43import { Resource as ResourceParser } from "../lib/parser" ;
5- import { Resource } from "../ast" ;
4+ import { Resource , NodeType , GroupComment } from "../ast" ;
65import { Bundle } from "../bundle" ;
76import { ErrorKind } from "../error" ;
7+ import { Value , StringValue , NumberValue } from "../value" ;
88
99const argv = parseArgs ( process . argv . slice ( 2 ) , {
10- boolean : [ "help" ] ,
10+ boolean : [ "help" , "group" ] ,
1111 alias : {
1212 help : "h" ,
13+ group : "g" ,
1314 } ,
1415} ) ;
1516
@@ -20,32 +21,41 @@ if (argv.help) {
2021const [ filePath ] = argv . _ ;
2122
2223if ( filePath === "-" ) {
23- parseStdin ( ) ;
24+ fromStdin ( print ) ;
2425} else if ( filePath ) {
25- parseFile ( filePath ) ;
26+ fromFile ( filePath , print ) ;
2627} else {
2728 exitHelp ( 1 ) ;
2829}
2930
3031function exitHelp ( exitCode : number ) {
3132 console . log ( `
32- Usage: node --experimental-modules parse.mjs [OPTIONS] <FILE>
33+ Usage: node format.js [OPTIONS] <FILE>
3334
3435 When FILE is "-", read text from stdin.
3536
3637 Examples:
3738
38- node --experimental-modules parse.mjs path/to/file.ftl
39- cat path/to/file.ftl | node --experimental-modules parse.mjs -
39+ node format.js path/to/file.ftl
40+ cat path/to/file.ftl | node format.js -
4041
4142 Options:
4243
4344 -h, --help Display help and quit.
45+ -g, --group Treat each group as a separate resource.
4446` ) ;
4547 process . exit ( exitCode ) ;
4648}
4749
48- function parseFluent ( source : string ) {
50+ function print ( source : string ) {
51+ if ( argv . group ) {
52+ printGroups ( source ) ;
53+ } else {
54+ printAll ( source ) ;
55+ }
56+ }
57+
58+ function parseString ( source : string ) {
4959 return ResourceParser . run ( source ) . fold (
5060 resource => resource ,
5161 err => {
@@ -54,15 +64,20 @@ function parseFluent(source: string) {
5464 ) ;
5565}
5666
57- function format ( resource : Resource ) {
67+ type Variables = Map < string , Value > ;
68+
69+ function formatResource ( resource : Resource , variables : Variables ) {
5870 let bundle = new Bundle ( ) ;
5971 bundle . addResource ( resource ) ;
6072
6173 let results = [ ] ;
6274 for ( let entry of resource . body ) {
75+ if ( entry . type !== NodeType . Message ) {
76+ continue ;
77+ }
6378 let message = bundle . getMessage ( entry . id . name ) ;
6479 if ( message ) {
65- let { value, errors} = bundle . formatValue ( message , new Map ( ) ) ;
80+ let { value, errors} = bundle . formatValue ( message , variables ) ;
6681 results . push ( {
6782 value,
6883 errors : errors . map ( error => ( {
@@ -72,36 +87,63 @@ function format(resource: Resource) {
7287 } ) ;
7388 }
7489 }
90+ return results ;
91+ }
7592
93+ function printAll ( source : string ) {
94+ let resource = parseString ( source ) ;
95+ let results = formatResource ( resource , new Map ( ) ) ;
7696 console . log ( JSON . stringify ( results , null , 4 ) ) ;
7797}
7898
79- function parseStdin ( ) {
80- const rl = readline . createInterface ( {
81- input : process . stdin ,
82- output : process . stdout ,
83- prompt : "fluent>" ,
84- } ) ;
85-
86- let lines : Array < string > = [ ] ;
87-
88- rl . on ( "line" , line => lines . push ( line ) ) ;
89- rl . on ( "close" , ( ) => parseFormat ( lines . join ( "\n" ) + "\n" ) ) ;
99+ interface Group {
100+ resource : Resource ;
101+ variables : Map < string , Value > ;
90102}
91103
92- function parseFile ( filePath : string ) {
93- fs . readFile ( filePath , "utf8" , ( err : NodeJS . ErrnoException | null , content : string | Buffer ) => {
94- if ( err ) {
95- throw err ;
104+ const RE_VARIABLE = / ^ \$ ( [ a - z A - Z ] * ) : ( s t r i n g | n u m b e r ) = ( .* ) $ / gm;
105+ function parseVariables ( comment : GroupComment ) {
106+ let variables = new Map ( ) ;
107+ let match ;
108+ while ( ( match = RE_VARIABLE . exec ( comment . content ) ) ) {
109+ let [ , name , type , value ] = match ;
110+ switch ( type ) {
111+ case "string" :
112+ variables . set ( name , new StringValue ( value ) ) ;
113+ break ;
114+ case "number" :
115+ variables . set ( name , new NumberValue ( parseFloat ( value ) ) ) ;
116+ break ;
96117 }
118+ }
119+ return variables ;
120+ }
121+
122+ function printGroups ( source : string ) {
123+ let resource = parseString ( source ) ;
97124
98- if ( typeof content === "string" ) {
99- parseFormat ( content ) ;
125+ let groups : Array < Group > = [ ] ;
126+ for ( let entry of resource . body ) {
127+ if ( entry . type === NodeType . GroupComment ) {
128+ groups . push ( {
129+ resource : {
130+ type : NodeType . Resource ,
131+ body : [ ] ,
132+ } ,
133+ variables : parseVariables ( entry ) ,
134+ } ) ;
135+ } else if ( groups . length > 0 ) {
136+ let currentGroup = groups [ groups . length - 1 ] ;
137+ currentGroup . resource . body . push ( entry ) ;
100138 }
101- } ) ;
102- }
139+ }
103140
104- function parseFormat ( source : string ) {
105- let resource = parseFluent ( source ) ;
106- format ( resource ) ;
141+ let results = [ ] ;
142+ for ( let group of groups ) {
143+ let groupResults = formatResource ( group . resource , group . variables ) ;
144+ let lastResult = groupResults . pop ( ) ;
145+ results . push ( lastResult ) ;
146+ }
147+
148+ console . log ( JSON . stringify ( results , null , 4 ) ) ;
107149}
0 commit comments