Deciphering the transpiled code and tracing it back to its original markup script

Is there an easy solution to convert custom markup into different formats, even with nested markings? Examples include...

  • for \k[hello], the output is <b>hello</b>
  • for \i[world], the output is <em>world</em>
  • for hello \k[dear \i[world]], the output is
    hello <b>dear <em>world</em></b>
  • for \b[some text](url), the output is
    <a href=”url”>some text</a>
  • for \r[some text](url), the output will be
    <img alt=”some text” src=”url” />

Converting the above to javascript, while considering nesting, is surprisingly simple if the markup grammar remains consistent.

//
// Define the syntax and translation to javascript.
//
const grammar = {

  syntax: {
    k:      {markUp: `\k[`, javascript: `"+grammar.oneArg("k","`,  pre: `<b>`,  post: `</b>`},
    i:      {markUp: `\i[`, javascript: `"+grammar.oneArg("i","`,  pre: `<em>`, post: `</em>`},
    b:      {markUp: `\b[`, javascript: `"+grammar.twoArgs("b","`, pattern: `<a href="$2">$1</a>`},
    r:      {markUp: `\r[`, javascript: `"+grammar.twoArgs("r","`, pattern: `<img alt="$1" src="$2"/>`},
    close0: {markUp: `](`,   javascript: `","`},
    close1: {markUp: `)`,    javascript: `")+"`},
    close2: {markUp: `]`,    javascript: `")+"`}
  },

  oneArg: function( command, arg1 ) {
    return grammar.syntax[ command ].pre + arg1 + grammar.syntax[ command ].post;
  },

  twoArgs: function( command, arg1, arg2 ) {
    return grammar.syntax[ command ].pattern.split( `$1` ).join( arg1 ).split( `$2` ).join( arg2 );
  }
}


function transpileAndExecute( markUpString ) {
  // Convert the markUp to javascript.
  for ( command in grammar.syntax ) {
    markUpString = markUpString.split( grammar.syntax[ command ].markUp ).join( grammar.syntax[ command ].javascript );
  }

  // With the markUp now converted to javascript, let's execute it!
  return new Function( `return "${markUpString}"` )();
}

var markUpTest = `Hello \k[dear \i[world!]] \b[\i[Search:] \k[Engine 1]](http://www.google.com) \r[\i[Search:] \k[Engine 2]](http://www.yahoo.com)`;

console.log( transpileAndExecute( markUpTest ) );

It's important to address preprocessing issues like handling tokens within normal text. Using '\]' as a representation of ']' before transpiling and replacing occurrences afterward solves this issue easily.

Transpiling large amounts of markup using the defined grammar faces challenges when dealing with syntax errors. Capturing error details from the dynamically compiled javascript function can help identify line numbers and character positions, but mapping these errors back to the original markup poses a challenge.

If extra characters like ']' are misplaced, like after "Goodbye"...

Hello World! \b[\i[Goodbye]]] \k[World!]]

This results in the transpiled version...

"Hello World! "+grammar.twoArgs("b",""+grammar.oneArg("i","Goodbye")+"")+"")+" "+grammar.oneArg("k","World!")+"")+""
                                                                           ^

The goal is to map syntax errors back to the original markup efficiently. Any suggestions on making this process simpler would be appreciated. Thank you.

Answer №1

To ensure proper syntax in your text, I recommend creating a syntax checker similar to jsonlint or jslint. This checker will verify that all elements are properly closed before compiling the text for readability.

By implementing this functionality, you can easily debug any issues and prevent malformed code from causing chaos. Additionally, you can provide an error-highlighted document editor to assist users in editing their text.

Below is a proof of concept that focuses on checking if brackets are correctly closed:

var grammarLint = function(text) {
  var nestingCounter = 0;
  var isCommand = char => char == '\\';
  var isOpen = char => char == '[';
  var isClose = char => char == ']';
  var lines = text.split('\n');
  for(var i = 0; i < lines.length; i++) {
    text = lines[i];
    for(var c = 0; c < text.length; c++) {
     var char = text.charAt(c);
     if(isCommand(char) && isOpen(text.charAt(c+2))) {
        c += 2;
        nestingCounter++;
        continue;
     }
     if(isClose(char)) {
        nestingCounter--;
        if(nestingCounter < 0) {
            throw new Error('Command closed but not opened at on line '+(i+1)+' char '+(c+1));
        }
      }
    }
  }
  if(nestingCounter > 0) {
     throw new Error(nestingCounter + ' Unclosed command brackets found');
  }
}
text = 'Hello World! \\b[\\i[Goodbye]]] \\k[World!]]';
try {
   grammarLint(text);
}
catch(e) {
   console.error(e.message);
}
text = 'Hello World! \\b[\\i[Goodbye \\k[World!]]';
try {
   grammarLint(text);
}
catch(e) {
   console.error(e.message);
}

Answer №2

Explored the use of the javascript compiler to catch syntax errors in the transpiled code and link them back to the original markup by incorporating comments in the transpiled code. This method allows for pinpointing the markup error with more accuracy, even though the error messages are primarily transpiler syntax errors rather than direct markup errors.

This approach also incorporates CertainPerformance's technique ( Find details of SyntaxError thrown by javascript new Function() constructor ) of employing setTimeout to capture syntax errors in the transpiled code, along with a javascript Promise for smoother execution flow.

"use strict";

//
// Define the syntax and translation to javascript.
//
class Transpiler {
  // Code implementation
}

Included below are sample scenarios with flawed markup along with their respective console outputs. In one instance, there is an extra ] in the markup...

let markUp = `Hello World \k[Goodbye]] World`;
new Transpiler().transpileAndExecute( markUp ).then(result => console.log( result )).catch( err => console.log( err ));

The resultant transpiled code displays embedded comments pointing back to the character positions in the original markup. Upon encountering a javascript compiler error, it gets caught by transpilerSyntaxChecker, which uses these comments to identify the location in the markup, presenting the error on the console accordingly...

In another run, missing a closing ] results in...

let markUp = `\i[Hello World] \k[\i[Goodbye] World`;
new Transpiler().transpileAndExecute( markUp ).then(result => console.log( result )).catch(err => console.log( err ));

The ensuing error highlights the missing parenthesis in the transpiled code, pinpointing the range within the markup script as well. While not a perfect solution, this approach provides a workaround that facilitates error detection and troubleshooting process.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to set multiple headers and change the content type when needed?

I am struggling with a function that cannot be overridden: getHtml:function(aURL,aPostData,aHeaders,aMethod){ this.xhr = new XMLHttpRequest(); var tmp=this; this.xhr.onreadystatechange=function(){ tmp.onStateChange(); }; if(aPo ...

Incorporating Styled Components in an NPM Package

I'm facing a dilemma and I'm not sure if it's my own issue, a problem with the library, or simply not possible in general (although it should be). Here's what I'm trying to accomplish: I've utilized Material UI to create a "L ...

What is the best way to traverse through a nested JSON file with d3.js?

Greetings. I am currently facing a challenge in navigating through a nested JSON file. Below is the JSON data that I need assistance with: {"Id":466,"Name":"korea", "Occurrences": ...

Securing Email and Password Data in Cypress Tests

Greetings! I trust everyone is in good spirits. My dilemma lies in the fact that I am hesitant to include email and passwords in version control. I am considering using environment variables in my cypress tests and utilizing secrets for runtime value pro ...

Having trouble with Semantic UI Modal onShow / onVisible functionality?

Seeking assistance with resizing an embedded google map in a Semantic UI modal after it is shown. After numerous attempts, I have narrowed down the issue to receiving callbacks when the modal becomes visible. Unfortunately, the onShow or onVisible functio ...

What is the procedure for incorporating JavaScript into my tic-tac-toe game's HTML and CSS?

I have created a simple Tic Tac Toe game using HTML and CSS. Although there is no embedded Javascript, I do reference a Javascript file for functionality. Can anyone provide me with the most straightforward Javascript code that will display an 'X&apos ...

What steps are involved in forming a JavaScript promise that resolves into a thenable object?

When using the faye browser client with promises, I encountered an issue with a function that creates a faye client after performing an asynchronous operation: function fayeClient() { return doSomethingAsychronous().then(function() { var faye_client ...

Does the presence of all angular2 bundles in index.html result in imports retrieving data from memory rather than making another request to the server?

Transitioning from angular 1 to angular 2, I initially faced some challenges with performance using a node backend. The page took 40 seconds to fully load in Firefox and made over 500 requests. This made me consider reverting back to angular 1 until the re ...

Steps to open and configure a Mobile-Angular modal from another controller

Is it possible to use a modal in Angular JS for mobile devices without compromising the layout? I'm having trouble setting up the controller for my modal inside my main controller and passing parameters. Should I consider using ui-bootstrap for this p ...

React component triggering dynamic redirection based on URL query changes

I've been struggling to implement a redirect with a query from a form in React. Despite trying different methods, I haven't been able to make it work. As a newbie in front-end development, what might seem simple to others is actually causing me s ...

What could be causing my canvas element to only display a blank black screen?

Setting up a 3d asset viewer in Three.js can be quite challenging, especially for someone who is new to JavaScript like myself. After following the advice to wrap my code within an 'init();' function, I encountered a new issue - a black screen in ...

What causes the other array to be affected when one is changed?

Take a look at this snippet of JavaScript code: var x = [1, 2, 3], y = x; y[1] = 3; x; // x === [1, 3, 3] Why does this happen? Why is the value of "x" changing when I update "y[1]"? I tried it in both Firefox and Chrome and got the same result. Th ...

Learn the best way to handle special characters like <, >, ", ', and & in Javascript, and successfully transfer escaped data from one text box to another

I am seeking a way to use JavaScript to escape special characters. I came across a code snippet on this URL: http://jsperf.com/encode-html-entities. It successfully handles <>&, but I have encountered an issue with double quotes ("). The JavaScri ...

Implementing a JavaScript function that uses the AJAX method to confirm and update

I am currently attempting to update a database using the JavaScript confirm() function in combination with AJAX. My goal is to have "accepted_order.php" run if the user clicks "OK," and "declined_order.php" run if the user clicks "Cancel," all without caus ...

The jQuery .accordion() feature is not functioning properly due to the failure to load jQuery into the HTML document

I have exhaustively researched online and visited numerous resources, including Stack Overflow. Despite making countless adjustments to my code, it still refuses to function properly. The frustration is mounting as I struggle with jQuery - a technology tha ...

Could anyone please provide advice on how to resolve the issue I encountered when trying to make Post and get Http method calls using protractor?

I am currently facing an issue while trying to make a GET API request using protractor. The challenge lies in using the bearer token generated from a previous POST response in the headers of the GET request. Although I have successfully executed the POST r ...

Tips for showcasing the output information in react framework

I'm currently developing a project that involves using rabbitMQ and react. After successfully connecting my rabbitMQ server to my react app, I was able to retrieve data from the server. Although I can output this data to the console using console.lo ...

Ways to capture the value of several images and add them to an array

When working on a multiple file upload task, I encountered the need to convert images into base64 encoded strings. My form consists of two fields, one for first name and another for image upload. The user can enter their name, upload multiple photos, and c ...

Find out whether the object is located behind another item

Is there a method to determine if elementA is "obscured" by another element, meaning it is not visible to the user? We could potentially achieve this using stacking context, but the challenge lies in identifying which elements to compare. This would requi ...

Pause until the array is populated before displaying the components

Currently, I am using firebase storage to fetch a list of directories. Once this fetching process is complete, I want to return a list of Project components that will be rendered with the retrieved directory names. How can I wait for the fetching to finish ...