UNPKG

3.15 kBJavaScriptView Raw
1"use strict";
2
3const
4 ToloframeworkPermissiveJson = require( "toloframework-permissive-json" ),
5 Preprocessor = require( "./boilerplate.preprocessor" ),
6 Fatal = require( "./fatal" ),
7 View = require( "./boilerplate.view" ),
8 Global = require( "./boilerplate.global" );
9
10
11const codeGenerators = { View, Global };
12
13
14exports.registerCodeGenerator = function ( name, generator ) {
15 codeGenerators[ name ] = generator;
16};
17
18
19exports.generateCodeFrom = function ( src ) {
20 const xjs = src.clone( "xjs" );
21 if ( xjs.exists() === false ) return src.read();
22
23 try {
24 const
25 rawDef = parseXJS( xjs ),
26 def = Preprocessor( rawDef ),
27 boilerplate = codeGenerators[ def[ 0 ] ];
28
29 if ( !boilerplate ) {
30 throw Error( `Unknown code generator "${def[0]}"!\n` +
31 `Available generators are: ${Object.keys(codeGenerators).join(", ")}.` );
32 }
33 return boilerplate.generateCodeFrom( def, src.read(), src.name() );
34 } catch ( ex ) {
35 Fatal.fire(
36 `Fatal error in ${xjs.getAbsoluteFilePath()}!\n${ex}`,
37 src.name(),
38 xjs.getAbsoluteFilePath()
39 );
40 }
41 return null;
42};
43
44/**
45 * @param {Source} xjs - Source of the XJS file.
46 * @returns {undefined}
47 */
48function parseXJS( xjs ) {
49 const xjsFileContent = xjs.read();
50 try {
51 return ToloframeworkPermissiveJson.parse( xjsFileContent );
52 } catch ( ex ) {
53 const code = getFewLinesOfCode( xjsFileContent, ex.index, 3 );
54 throw Error( `Invalid permissive JSON syntax:${ex.message}\n\n${code}` );
55 }
56}
57
58
59function getFewLinesOfCode( code, issuePosition, linesToDisplay ) {
60 if ( typeof linesToDisplay === 'undefined' ) linesToDisplay = 3;
61 var lineCount = 1;
62 var currentIndex = 0;
63 var previousIndex = 0;
64 var lines = [];
65 issuePosition = Math.min( issuePosition, code.length - 1 );
66 while ( currentIndex < code.length ) {
67 if ( code.charAt( currentIndex ) === '\n' ) {
68 lines.push( { line: lineCount, begin: previousIndex, end: currentIndex } );
69 if ( lines.length > linesToDisplay )
70 lines.shift();
71 previousIndex = currentIndex + 1;
72 lineCount++;
73 if ( currentIndex >= issuePosition ) break;
74 }
75 currentIndex++;
76 }
77
78 debugger;
79 var columnsSeparator = ": ";
80 var lineNumbersLengths = lines.map( x => ( "" + x.line ).length );
81 var spaceForLineNumbers = lineNumbersLengths.reduce( ( a, v ) => Math.max( a, v ), 0 );
82 var output = lines.map(
83 x => padStart( x.line, spaceForLineNumbers ) +
84 columnsSeparator + code.substring( x.begin, x.end ) ).join( "\n" );
85 var lastLineBegin = lines.pop().begin;
86 output += "\n" + padStart( "^",
87 spaceForLineNumbers + columnsSeparator.length + issuePosition - lastLineBegin - 1 );
88 return output;
89}
90
91function padStart( text, targetLength, padString ) {
92 if ( typeof padString === 'undefined' ) padString = ' ';
93 text = "" + text;
94 while ( text.length < targetLength )
95 text = padString + text;
96 return text;
97}
\No newline at end of file