js - Parse markdown string (bold and italic only)

2019-07-26 19:46发布

问题:

Trying to parse a string in javascript that contains bold annotations, marked as *multi word bold* (asterisk), and italic annotations, marked as _multi word italic_ (underline).
I'd like the parser function to support multi words annotations, italic within bold, bold within italic and mixed (see examples).

Here are some inputs with required outputs examples:

const simpleInput = "The *quick brown fox* jumps _over the lazy dog_";
const simpleOutput =[
    {text: 'The '},
    {text: 'quick brown fox', bold: true},
    {text: ' jumps '},
    {text: 'over the lazy dog', italic: true}
];

const italicWithinBoldInput = "The *quick brown _fox jumps_ over the* lazy dog";
const italicWithinBoldOutput =[
    {text: 'The '},
    {text: 'quick brown ', bold: true},
    {text: 'fox jumps', bold: true, italic: true},
    {text: ' over the', bold: true},
    {text: ' lazy dog'}
];

const mixedInput = "The *quick brown _fox jumps* over the_ lazy dog";
const mixedOutput =[
    {text: 'The '},
    {text: 'quick brown ', bold: true},
    {text: 'fox jumps', bold: true, italic: true},
    {text: ' over the', italic: true},
    {text: ' lazy dog'}
];

I tried some parsers on npm but everything was a bit of an overkill, nothing was quite what I needed..

回答1:

You can do it in the following way

function getObject(str){
    let bold = false, italics = false;
    let output = [];
    let text = str.split('').reduce((a, b) => {
        if(b == '*'){
            if(bold){
                if(a != ''){
                    if(italics)
                        output.push({text: a, bold: true, italics:true});
                    else
                      output.push({text: a, bold: true});
                }
                bold = false;
            }
            else{
                if(italics)
                    output.push({text: a, italics: true})
                else
                    output.push({text: a})
                bold = true;
            }
            return '';
        }
        else if(b == '_'){
            if(italics){
                if(a != ''){
                    if(bold)
                        output.push({text: a, bold: true, italics:true});
                    else
                      output.push({text: a, italics: true});
                }
                italics = false;
            }
            else{
                if(bold)
                    output.push({text: a, bold: true})
                else
                    output.push({text: a})
                italics = true;
            }
            return '';
        }
        else{
            return a+b;
        }
    }, '');
    if(text != '')
        output.push({text : text});
    console.log(output);
    return output;
}


const simpleInput = "The *quick brown fox* jumps _over the lazy dog_";

getObject(simpleInput);

const italicWithinBoldInput = "The *quick brown _fox jumps_ over the* lazy dog";

getObject(italicWithinBoldInput);

const mixedInput = "The *quick brown _fox jumps* over the_ lazy dog";

getObject(mixedInput);