Last active
December 16, 2017 14:13
-
-
Save bz0/fdebc5f1857b4a9a1b055963ec38546e to your computer and use it in GitHub Desktop.
typescriptで書くpukiwikiパーサ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Inline { | |
private match = { | |
strong: /^''([\s\S]+?)''(?!')/, | |
em: /^'''((?:[^_]|__)+?)'''(?!')/, | |
br: /^~(?:\n|$)|^(&br;)/, | |
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/ | |
} | |
private out: string; | |
private renderer: Renderer; | |
constructor(){ | |
this.renderer = new Renderer(); | |
this.out = ""; | |
} | |
public strong(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.strong.exec(src)){ | |
src = src.substring(cap[0].length); | |
this.out += this.renderer.strong(src); | |
} | |
return src; | |
} | |
public em(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.em.exec(src)){ | |
src = src.substring(cap[0].length); | |
this.out += this.renderer.em(src); | |
} | |
return src; | |
} | |
public text(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.text.exec(src)){ | |
this.out += src; | |
src = src.substring(cap[0].length); | |
} | |
return src; | |
} | |
public output(src: string): string { | |
while(src){ | |
src = this.strong(src); | |
src = this.em(src); | |
src = this.text(src); | |
} | |
return this.out; | |
} | |
} | |
class Block { | |
private match = { | |
newline: /^\n+/, | |
heading: /^(\*{1,4})(.*?)(?:\n+|$)/, | |
text: /^[^\n]+/ | |
} | |
private tokens: {type:string, depth: number, text: string}[]; | |
constructor(){ | |
this.tokens = []; | |
} | |
public newline(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.newline.exec(src)){ | |
src = src.substring(cap[0].length); | |
this.tokens.push({ | |
type: 'newline', | |
text: cap[1], | |
depth: 0 | |
}); | |
} | |
return src; | |
} | |
public heading(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.heading.exec(src)){ | |
src = src.substring(cap[0].length); | |
console.log(this.tokens); | |
this.tokens.push({ | |
type: 'heading', | |
text: cap[2], | |
depth: cap[1].length | |
}); | |
} | |
return src; | |
} | |
public text(src: string): string { | |
var cap: Array<string>; | |
if (cap = this.match.text.exec(src)){ | |
src = src.substring(cap[0].length); | |
this.tokens.push({ | |
type: 'text', | |
text: cap[0], | |
depth: 0 | |
}); | |
} | |
return src; | |
} | |
public output(src: string): {type:string, depth: number, text: string}[] { | |
while(src){ | |
src = this.newline(src); | |
src = this.heading(src); | |
src = this.text(src); | |
} | |
return this.tokens; | |
} | |
} | |
class Renderer { | |
public heading(text: string, depth: number): string{ | |
return '<h' + depth + '>' + text + '<h' + depth + '>'; | |
} | |
public strong(text: string): string { | |
return '<b>' + text + '</b>'; | |
} | |
public em(text: string): string { | |
return '<em>' + text + '</em>'; | |
} | |
public output(token: {type:string, depth: number, text: string}): string{ | |
var src = ""; | |
if (token.type==="heading"){ | |
src = this.heading(token.text, token.depth); | |
} | |
return src; | |
} | |
} | |
class Parser{ | |
private block:Block; | |
private inline:Inline; | |
private render:Renderer; | |
constructor(){ | |
this.block = new Block(); | |
this.inline = new Inline(); | |
this.render = new Renderer(); | |
} | |
public exec(input: string): string{ | |
var tokens = this.block.output(input); | |
var output = ""; | |
for(var i=0; i<tokens.length; i++){ | |
tokens[i].text = this.inline.output(tokens[i].text); | |
output += this.render.output(tokens[i]); | |
} | |
return output; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment