This commit is contained in:
		
							parent
							
								
									e04c03007b
								
							
						
					
					
						commit
						21b72f7854
					
				
					 3 changed files with 209 additions and 2 deletions
				
			
		|  | @ -11,7 +11,191 @@ module.exports = { | |||
| 		return { | ||||
| 			type: 'code', | ||||
| 			content: code, | ||||
| 			code: code.substr(3, code.length - 6).trim() | ||||
| 			code: code.substr(3, code.length - 6).trim(), | ||||
| 			codeHtml: genHtml(code.substr(3, code.length - 6).trim()) | ||||
| 		}; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| function escape(text) { | ||||
| 	return text | ||||
| 		.replace(/>/g, '>') | ||||
| 		.replace(/</g, '<'); | ||||
| } | ||||
| 
 | ||||
| // 文字数が多い順にソートします
 | ||||
| // そうしないと、「function」という文字列が与えられたときに「func」が先にマッチしてしまう可能性があるためです
 | ||||
| const keywords = [ | ||||
| 	'true', | ||||
| 	'false', | ||||
| 	'null', | ||||
| 	'nil', | ||||
| 	'undefined', | ||||
| 	'var', | ||||
| 	'const', | ||||
| 	'let', | ||||
| 	'mut', | ||||
| 	'if', | ||||
| 	'then', | ||||
| 	'else', | ||||
| 	'switch', | ||||
| 	'case', | ||||
| 	'for', | ||||
| 	'each', | ||||
| 	'in', | ||||
| 	'while', | ||||
| 	'loop', | ||||
| 	'continue', | ||||
| 	'break', | ||||
| 	'do', | ||||
| 	'goto', | ||||
| 	'end', | ||||
| 	'function', | ||||
| 	'func', | ||||
| 	'fn', | ||||
| 	'return', | ||||
| 	'async', | ||||
| 	'await', | ||||
| 	'require', | ||||
| 	'import', | ||||
| 	'export', | ||||
| 	'new', | ||||
| 	'this', | ||||
| 	'class', | ||||
| 	'constructor' | ||||
| ].sort((a, b) => b.length - a.length); | ||||
| 
 | ||||
| const symbols = [ | ||||
| 	'=', | ||||
| 	'+', | ||||
| 	'-', | ||||
| 	'*', | ||||
| 	'/', | ||||
| 	'%', | ||||
| 	'^', | ||||
| 	'&', | ||||
| 	'|', | ||||
| 	'>', | ||||
| 	'<', | ||||
| 	'~' | ||||
| ]; | ||||
| 
 | ||||
| const elements = [ | ||||
| 	// comment
 | ||||
| 	code => { | ||||
| 		if (code.substr(0, 2) != '//') return null; | ||||
| 		const comment = code.match(/^\/\/(.+?)\n/)[0]; | ||||
| 		return { | ||||
| 			html: `<span class="comment">${escape(comment)}</span>`, | ||||
| 			next: comment.length | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	// string
 | ||||
| 	code => { | ||||
| 		if (!/^['"`]/.test(code)) return null; | ||||
| 		const begin = code[0]; | ||||
| 		let str = begin; | ||||
| 		let thisIsNotAString = false; | ||||
| 		for (i = 1; i < code.length; i++) { | ||||
| 			const char = code[i]; | ||||
| 			if (char == '\\') { | ||||
| 				i++; | ||||
| 				continue; | ||||
| 			} else if (char == begin) { | ||||
| 				str += char; | ||||
| 				break; | ||||
| 			} else if (char == '\n' || i == (code.length - 1)) { | ||||
| 				thisIsNotAString = true; | ||||
| 				break; | ||||
| 			} else { | ||||
| 				str += char; | ||||
| 			} | ||||
| 		} | ||||
| 		if (thisIsNotAString) { | ||||
| 			return null; | ||||
| 		} else { | ||||
| 			return { | ||||
| 				html: `<span class="string">${escape(str)}</span>`, | ||||
| 				next: str.length | ||||
| 			}; | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	// number
 | ||||
| 	(code, i, source) => { | ||||
| 		const prev = source[i - 1]; | ||||
| 		if (prev && /[a-zA-Z]/.test(prev)) return null; | ||||
| 		if (!/^[0-9]+/.test(code)) return null; | ||||
| 		const match = code.match(/^[0-9]+/)[0]; | ||||
| 		if (match) { | ||||
| 			return { | ||||
| 				html: `<span class="number">${match}</span>`, | ||||
| 				next: match.length | ||||
| 			}; | ||||
| 		} else { | ||||
| 			return null; | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	// keyword
 | ||||
| 	code => { | ||||
| 		const match = keywords.filter(k => code.substr(0, k.length) == k)[0]; | ||||
| 		if (match) { | ||||
| 			if (/^[a-zA-Z]/.test(code.substr(match.length))) return null; | ||||
| 			return { | ||||
| 				html: `<span class="keyword ${match}">${match}</span>`, | ||||
| 				next: match.length | ||||
| 			}; | ||||
| 		} else { | ||||
| 			return null; | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	// symbol
 | ||||
| 	code => { | ||||
| 		const match = symbols.filter(s => code[0] == s)[0]; | ||||
| 		if (match) { | ||||
| 			return { | ||||
| 				html: `<span class="symbol">${match}</span>`, | ||||
| 				next: 1 | ||||
| 			}; | ||||
| 		} else { | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
| ]; | ||||
| 
 | ||||
| // specify lang is todo
 | ||||
| function genHtml(source, lang) { | ||||
| 	let code = source; | ||||
| 	let html = ''; | ||||
| 
 | ||||
| 	function push(token) { | ||||
| 		html += token.html; | ||||
| 		code = code.substr(token.next); | ||||
| 	} | ||||
| 
 | ||||
| 	let i = 0; | ||||
| 
 | ||||
| 	while (code != '') { | ||||
| 		const parsed = elements.some(el => { | ||||
| 			const e = el(code, i, source); | ||||
| 			if (e) { | ||||
| 				push(e); | ||||
| 				return true; | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		if (!parsed) { | ||||
| 			push({ | ||||
| 				html: escape(code[0]), | ||||
| 				next: 1 | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		i++; | ||||
| 	} | ||||
| 
 | ||||
| 	return html; | ||||
| } | ||||
|  |  | |||
|  | @ -107,6 +107,29 @@ a | |||
| 	* | ||||
| 		cursor pointer | ||||
| 
 | ||||
| pre > code | ||||
| 	.comment | ||||
| 		opacity 0.5 | ||||
| 
 | ||||
| 	.string | ||||
| 		color #e96900 | ||||
| 
 | ||||
| 	.keyword | ||||
| 		color #2973b7 | ||||
| 
 | ||||
| 		&.true | ||||
| 		&.false | ||||
| 		&.null | ||||
| 		&.nil | ||||
| 		&.undefined | ||||
| 			color #ae81ff | ||||
| 
 | ||||
| 	.symbol | ||||
| 		color #42b983 | ||||
| 
 | ||||
| 	.number | ||||
| 		color #ae81ff | ||||
| 
 | ||||
| mk-locker | ||||
| 	display block | ||||
| 	position fixed | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ module.exports = function(tokens, shouldBreak, shouldEscape) { | |||
| 			case 'hashtag': // TODO
 | ||||
| 				return '<a>' + escape(token.content) + '</a>'; | ||||
| 			case 'code': | ||||
| 				return '<pre><code>' + escape(token.code) + '</code></pre>'; | ||||
| 				return '<pre><code>' + token.codeHtml + '</code></pre>'; | ||||
| 		} | ||||
| 	}).join(''); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue