ometa WikiParser <: Parser { nl = '\n', createTextSpec = { var spec = { string: '', attributes: []}; spec.assemble = function() { var morph = new TextMorph(new Rectangle(0,0,10,10)); morph.applyStyle({fill: Color.white, borderWidth: 0, opacity: 0, fontSize: 16}); var text = new lively.Text.Text(spec.string); spec.attributes.forEach(function(ea) { text.emphasize(ea, ea.start, ea.stop) }); morph.setRichText(text); return morph; }; spec.add = function(str) { spec.string += str }; spec.addAttribute = function(attr) { spec.attributes.push(attr) }; spec.addAttributed = function(str, attribute) { attribute.start = spec.string.length; spec.add(str); attribute.stop = spec.string.length; spec.addAttribute(attribute); }; spec }, heading = '='+:start (~'\n' ~'=' char:c -> c)+:cs '='+:end ?(end.length == start.length) -> { var morph = new TextMorph(new Rectangle(0,0,10,10), cs.join('')); morph.applyStyle({fill: Color.white, borderWidth: 0, opacity: 0, fontSize: 40 - start.length * 6}); morph }, paragraph = createTextSpec:spec atomicText(spec)+ -> spec.assemble(), nestableText :spec = atomicText(spec) | list(spec), list :spec = '*'+:level spaces { spec.add(level.collect(function(ea) { return '\t'}).join('')); spec.add('• ')} (~'\n' (bold(spec) | italic(spec) | link(spec) | wordsNoNewline(spec)))+ ('\n' | end) {spec.add('\n')} list(spec)*, atomicText :spec = wordsNoParagraphEnd(spec) | bold(spec) | italic(spec) | link(spec) | list(spec) | trash(spec), trash :spec = ~'\n' ~end {spec.add('')} (char:c ?(c != '\n') {spec.add(c)})+ {spec.add('')}, character :spec = char:c -> spec.add(c), wordsNoParagraphEnd :spec = (~paragraphEnd char:c ?(c != '*' && c != '[' && c != '<' && c != '\'') {spec.add(c)})+, wordsNoNewline :spec = (char:c ?(c != '\n' && c != '*' && c != '[' && c != '<' && c != '\'') {spec.add(c)})+, bold :spec = ~space "'''" (~"'''" char:c ->c)+:cs "'''" -> { spec.addAttributed(cs.join(''), {style: 'bold'}) }, italic :spec = ~space "''" (~"''" char:c ->c)+:cs "''" -> { spec.addAttributed(cs.join(''), {style: 'italic'}) }, link :spec = '[' (~']' ~space char:c -> c)+:target (space+ (~']' char:c -> c)+ | empty -> []):name ']' -> { spec.addAttributed(name.join('') || target.join(''), {link: target.join(''), color: 'blue'}) }, paragraphEnd = '\n' ('\n'+ | '='), partEnd = '\n'+ | end, textParts = ((heading | paragraph):p partEnd -> p)+, log :msg = {console.log(msg)}, wikiTextDescription = textParts:parts end -> parts }