The selectCode
function is an asynchronous function that detects the language of a file, parses it using ANTLR, transforms the parsed output into HTML, selects specific DOM elements, and returns the result as a string.
The selectCode
function is an asynchronous function that performs language detection, ANTLR parsing, and HTML transformation on a given file. It catches any errors that occur during the parsing process and returns the result as a string, along with an error message if an error occurs.
npm run import -- "select antlr tree"
import fs from 'fs'
//import path from 'path'
import antlr from 'antlr4'
const {selectDom} = importer.import("select tree")
//TODO: fix this with own transpiler because no one is going to share their hard work on StringTemplate4 code
/*
function toString(ctx, subctx) {
var ast = (subctx || ctx)
if(typeof ast.ownerDocument !== 'undefined') {
ast = htmlToTree(ast)
}
//escodegen.attachComments(ast, ast.comments, ast.tokens, ast.whitespace)
return escodegen.generate(ast, {
comment: true,
tokens: true,
whitespace: true,
format: {indent: {style: ' '}, quotes: 'single'}
})
}
*/
let extToLang
let treeToHtml
let getParser
async function selectCode(descriptor, code, language) {
if(!extToLang)
extToLang = await importer.import("ext to lang")
if(!treeToHtml)
treeToHtml = (await importer.import("antlr to html")).treeToHtml
if(!getParser)
getParser = await importer.import("get antlr tool")
if(typeof code === 'function') {
code = code.toString()
}
if(typeof code === 'string') {
if(fs.existsSync(code)) {
if(typeof language === 'undefined') {
// TODO: use language file extension from media-server code module gheshi support
language = await extToLang(code)
}
code = fs.readFileSync(code).toString('utf8')
}
var {lexer, parser} = await getParser(language)
try {
const chars = new antlr.InputStream(code);
const lexerStream = new lexer(chars);
const tokens = new antlr.CommonTokenStream(lexerStream);
const parserStream = new parser(tokens);
parserStream.input = code
const tree = parserStream[parserStream.ruleNames[0]]();
code = selectDom(['//' + parserStream.ruleNames[0]], treeToHtml(tree))[0]
} catch(e) {
console.log(e)
throw new Error('Could not parse \n' + code)
}
}
return selectDom(descriptor, code)
}
export default selectCode
import fs from 'fs';
import antlr from 'antlr4';
import { importer } from './importer';
const { selectDom } = importer.import('select tree');
const { extToLang, treeToHtml, getParser } = await loadModules();
async function loadModules() {
const extToLang = await importer.import('ext to lang');
const treeToHtml = (await importer.import('antlr to html')).treeToHtml;
const getParser = await importer.import('get antlr tool');
return { extToLang, treeToHtml, getParser };
}
/**
* Selects code from a given descriptor and returns the selected code as HTML.
* @param {string[]} descriptor - The descriptor to select the code from.
* @param {string|Function} code - The code to select, either a string or a function.
* @param {string} [language] - The language of the code, automatically detected if not provided.
* @returns {Promise<string>} The selected code as HTML.
*/
async function selectCode(descriptor, code, language) {
if (typeof code === 'function') {
code = code.toString();
}
if (typeof code ==='string' && fs.existsSync(code)) {
language = await getLanguageFromExtension(code);
code = await readFile(code, 'utf8');
}
const lexer = await getLexer(language);
const parser = await getParser(language);
try {
const antlrStream = new antlr.InputStream(code);
const lexerStream = new lexer(antlrStream);
const tokens = new antlr.CommonTokenStream(lexerStream);
const parserStream = new parser(tokens);
parserStream.input = code;
const tree = parserStream[parserStream.ruleNames[0]]();
const codeHtml = await getHtmlFromTree(tree);
return selectDom(descriptor, codeHtml);
} catch (e) {
console.log(e);
throw new Error(`Could not parse \n${code}`);
}
}
async function getLanguageFromExtension(file) {
const extToLang = await importer.import('ext to lang');
return extToLang(file);
}
async function getLexer(language) {
const getParser = await importer.import('get antlr tool');
return getParser(language).lexer;
}
async function getParser(language) {
const getParser = await importer.import('get antlr tool');
return getParser(language);
}
async function getHtmlFromTree(tree) {
const treeToHtml = (await importer.import('antlr to html')).treeToHtml;
return treeToHtml(tree);
}
async function readFile(file, encoding) {
return fs.readFileSync(file, encoding);
}
export default selectCode;
Code Breakdown
The code starts by importing various modules:
fs
from the fs
module (File System) for file system operations.antlr
from the antlr4
module (ANTLR v4) for ANTLR parsing.importer
and selectDom
functions from an external module ( likely a custom module).The code defines several variables:
extToLang
: an object that maps file extensions to languages.treeToHtml
: a function that converts an ANTLR tree to HTML.getParser
: a function that returns a parser for a given language.selectCode
FunctionThe selectCode
function takes three parameters: descriptor
, code
, and language
. It is an asynchronous function that performs the following tasks:
code
parameter is a string and a file exists at the specified path, it tries to detect the language from the file extension using the extToLang
object. If the language is not specified, it uses this detected language.getParser
function to get a lexer and parser for the detected language. It then reads the file contents and creates an ANTLR input stream.treeToHtml
function to convert the AST to HTML.selectDom
function to select specific DOM elements from the HTML output.The code catches any errors that occur during the parsing process and logs the error message. If an error occurs, it throws a new error with the parsed code and the error message.