Commits

firefly committed e5ee613

Translated `wykedown.coffee` to JavaScript.

  • Participants
  • Parent commits 12e9a90

Comments (0)

Files changed (2)

src/wykedown.coffee

-{markdown} = require '../deps/markdown'
-{Markdown} = markdown
-
-wykedown = Markdown.subclassDialect Markdown.dialects.Gruber
-
-#### Templates: {{Foo|bar|baz=qux}} #######################
-wykedown.inline['{{'] = (text) ->
-	res = @processInline text[2..]
-	for el,idx in res
-		if el.name == 'close_template'
-			content = res[0...idx]
-			rest    = res[idx+1..]
-			
-			# Process template arguments
-			args    = []
-			currArg = []
-			
-			for el in content
-				if typeof el == 'string'
-					[first, trailing ...] = el.split "|"
-					currArg.push first
-					
-					for part in trailing
-						args.push currArg
-						currArg = []
-						currArg.push part if part != ""
-				
-				else
-					currArg.push el
-			
-			args.push currArg if currArg.length
-			
-			name = args.shift()
-			if name.length != 1 or typeof name[0] != 'string'
-				throw new Error "Invalid template name. #{JSON.stringify name}"
-			
-			props = {
-				name : name[0]
-				args : args
-			}
-			
-			return [ text.length, ['template', props] ].concat rest
-	
-	# Shouldn't get here
-	console.log "Warn: Couldn't match template opening tag."
-	[ 2, '{{' ]	# Fall back gracefully to doing nothing...
-
-wykedown.inline['}}'] = (text) ->
-	[ 2, {
-		name: 'close_template'
-	} ]
-
-#### Wikilinks: [[foo]] or [[foo|bar]] ####################
-wykedown.inline['[['] = (text) ->
-	match = text.match ///
-		^\[\[				# start with literal [[
-		( [^ \| \] ]+ )		# non-]-or-| characters
-		(?:					# optionally,
-			\|				# literal |
-			( [^ \] ]* )	# followed by non-] characters
-		)?					# 
-		\]\]				# literal ]]
-		///
-	
-	if not match
-		throw new Error "Parse error: couldn't find end of wikilink starting with '#{text[0..30]}'."
-	
-	[wholeMatch, target, display] = match
-	display ?= target
-	
-	[ wholeMatch.length, [ 'wikilink', { target: target }, display ] ]
-
-#### Strikeout: ~foo~ #####################################
-wykedown.inline['~'] = (text) ->
-	index = text[1..].indexOf '~'
-
-	if not ~index
-		return null
-	
-	content = text[1..index]
-	
-	[ index + 2, ['del', content] ]
-
-#### Special symbols syntax ###############################
-wykedown.inline['---'] = -> [ 3, "—" ]	# em dash (from TeX)
-wykedown.inline['--']  = -> [ 2, "–" ]	# en dash (from TeX)
-wykedown.inline['->']  = -> [ 2, "→" ]	# rightwards arrow
-wykedown.inline['=>']  = -> [ 2, "⇒" ]	# rightwards double arrow
-wykedown.inline['<-']  = -> [ 2, "&#8592;" ]	# leftwards arrow
-wykedown.inline['<=']  = -> [ 2, "&#8656;" ]	# leftwards double arrow
-
-#### Allow HTML tags ######################################
-wykedown.inline['<'] = (text) ->
-	match = text.match /^<\/?([A-Za-z]+)(?: [^>]+)*>/
-	
-	return null if not match
-	
-	[ match[0].length, ['raw', match[0]] ]
-
-# Copy over all keys (to fix precedence)
-for key,val of Markdown.dialects.Gruber.block
-	wykedown.block[key] = val
-
-#### Fix paragraphs containing HTML #######################
-wykedown.block['para'] = (block, next) ->
-	# Everything's a para! Well, almost...
-	# count newlines & lines that are HTML-ish
-	lineCount     = block.split('\n').length
-#	htmlLineCount = block.match(/^\s*(?:<.*>\s*.*|)?$/gm)?.length
-	htmlLineCount = block.match(/^\s*<.*>\s*$/gm)?.length
-	
-	if lineCount == htmlLineCount
-		return [ ["raw", block.toString()] ]	# Don't mess with HTML!
-	
-	[ ["para"].concat @processInline block ]
-
-#### Other stuff ##########################################
-# TODO: Clean this portion up.
-Markdown.buildBlockOrder     wykedown.block
-Markdown.buildInlinePatterns wykedown.inline
-
-mapTree = (node, pred, callback) ->
-	if typeof node == 'string'
-		return node
-	
-	attrs = {}
-	[name, children] = node
-	
-	if children not instanceof Array
-		[_, attrs, children] = node
-	
-	shouldReplace = pred name, attrs, children
-	
-	if shouldReplace
-		callback name, attrs, children
-	else
-		newChildren = (mapTree ch, pred, callback for ch in children)
-		
-		if Object.keys(attrs).length > 0
-			[name, attrs, newChildren]
-		else
-			[name, newChildren]
-
-getFormatted = (name, args) ->
-	res = markdown.parse documents[name], wykedown
-	
-	newRes = mapTree res, ((name) -> name == "template"), (name, attrs, children) ->
-		if attrs["name"][0] == ':'
-			return [ "div" ].concat args[attrs["name"][1..]]
-		
-		[name, children] = getFormatted attrs["name"], attrs["args"]
-		children
-	
-	newRes
-
-exports.wykedown = wykedown
-exports.parse    = (source) -> markdown.parse  source, wykedown
-exports.toHTML   = (source) -> markdown.toHTML source, wykedown
-exports.utils    = {
-	mapTree : mapTree
-}
+var markdown = require('../deps/markdown').markdown
+var Markdown = markdown.Markdown
+
+var wykedown = Markdown.subclassDialect(Markdown.dialects.Gruber)
+
+//-- Templates: {{Foo|bar|baz=qux}} ---------------------------------
+wykedown.inline['{{'] = function(text) {
+	var res = this.processInline(text.slice(2))
+	for (idx = 0; idx < res.length; idx++) {
+		var el = res[idx]
+
+		if (el.name == 'close_template') {
+			var content = res.slice(0, idx)
+			  , rest    = res.slice(idx + 1)
+
+			// Process template arguments
+			var args    = []
+			  , currArg = []
+
+			for (var i=0; i < content.length; i++) {
+				var el = content[i]
+				if (typeof el == 'string') {
+					var splitted = el.split("|")
+					  , first    = splitted[0]
+					  , trailing = splitted.slice(1)
+
+					currArg.push(first)
+					trailing.forEach(function(part) {
+						args.push(currArg)
+						currArg = []
+
+						if (part != "") {
+							currArg.push(part)
+						}
+					})
+				} else {
+					currArg.push(el)
+				}
+			}
+
+			if (currArg.length) {
+				args.push(currArg)
+			}
+
+			var name = args.shift()
+			if (name.length != 1 || typeof name[0] != 'string') {
+				throw new Error("Invalid template name. " +
+						JSON.stringify(name))
+			}
+
+			var props = {
+				name : name[0],
+				args : args
+			}
+
+			return [ text.length, ['template', props] ].concat(rest)
+		}
+	}
+
+	// Shouldn't get here
+	console.warn("wykedown: Couldn't match template opening tag.")
+	return [ 2, '{{' ] // Fall back gracefully to doing nothing...
+}
+
+wykedown.inline['}}'] = function(text) {
+	return [ 2, {name: 'close_template'} ]
+}
+
+//-- Wikilinks: [[foo]] or [[foo|bar]] ------------------------------
+wykedown.inline['[['] = function(text) {
+	var match = text.match(/^\[\[([^\|\]]+)(?:\|([^\]]*))?\]\]/)
+
+	if (!match) {
+		throw new Error("Parse error: couldn't find end of wikilink starting with '" +
+				text.slice(0, 31) + "'.")
+	}
+
+	var wholeMatch = match[0]
+	  , target     = match[1]
+	  , display    = match[2]
+
+	display || (display = target)
+
+	return [ wholeMatch.length, ['wikilink', {target: target}, display] ]
+};
+
+//-- Strikeout: ~foo~ -----------------------------------------------
+wykedown.inline['~'] = function(text) {
+	var index = text.slice(1).indexOf('~')
+
+	if (index < 0) return null
+
+	var content = text.slice(1, index + 1)
+	return [ index + 2, ['del', content] ]
+};
+
+//-- Special symbols syntax -----------------------------------------
+wykedown.inline['---'] = function() { return [ 3, "&#8212;" ] } // em dash (from TeX)
+wykedown.inline['--']  = function() { return [ 2, "&#8211;" ] } // en dash (from TeX)
+wykedown.inline['->']  = function() { return [ 2, "&#8594;" ] } // rightwards arrow
+wykedown.inline['=>']  = function() { return [ 2, "&#8658;" ] } // rightwards double arrow
+wykedown.inline['<-']  = function() { return [ 2, "&#8592;" ] } // leftwards arrow
+wykedown.inline['<=']  = function() { return [ 2, "&#8656;" ] } // leftwards double arrow
+
+//-- Allow HTML tags ------------------------------------------------
+wykedown.inline['<'] = function(text) {
+	var match = text.match(/^<\/?([A-Za-z]+)(?: [^>]+)*>/)
+
+	if (!match) {
+		return null
+	} else {
+		return [ match[0].length, ['raw', match[0]] ]
+	}
+}
+
+// Copy over all keys (to fix precedence)
+var gruber = Markdown.dialects.Gruber
+for (var key in gruber.block) {
+	wykedown.block[key] = gruber.block[key]
+}
+
+//-- Fix paragraphs containing HTML ---------------------------------
+wykedown.block['para'] = function(block, next) {
+	// Everything's a para! Well, almost...
+	// count newlines & lines that are THML-ish
+	var lineCount     = block.split('\n').length
+	var match         = block.match(/^\s*<.*>\s*$/gm)
+	  , htmlLineCount = (match != null ? match.length : 0)
+
+	if (lineCount == htmlLineCount) {
+		return [ ["raw", block.toString()] ] // Don't mess with HTML!
+	} else {
+		return [ ["para"].concat(this.processInline(block)) ]
+	}
+}
+
+//-- Other stuff ----------------------------------------------------
+// TODO: Clean this portion up.
+Markdown.buildBlockOrder(wykedown.block)
+Markdown.buildInlinePatterns(wykedown.inline)
+
+function mapTree(node, pred, callback) {
+	if (typeof node == 'string') return node
+
+	var attrs    = {}
+	var name     = node[0]
+	  , children = node[1]
+
+	if (!(children instanceof Array)) {
+		var attrs    = node[1]
+		  , children = node[2]
+	}
+
+	var shouldReplace = pred(name, attrs, children)
+
+	if (shouldReplace) {
+		callback(name, attrs, children)
+	} else {
+		var newChildren = children.map(function(ch) {
+			return mapTree(ch, pred, callback)
+		})
+
+		if (Object.keys(attrs).length > 0) {
+			return [ name, attrs, newChildren ]
+		} else {
+			return [ name, newChildren ]
+		}
+	}
+}
+
+function getFormatted(name, args) {
+	var res = markdown.parse(documents[name], wykedown)
+
+	function mapper(name, attrs, children) {
+		if (attrs["name"][0] == ':') {
+			return [ "div" ].concat(args[attrs["name"].slice(1)])
+		}
+
+		var tuple    = getFormatted(attrs["name"], attrs["args"])
+		  , children = tuple[1]
+
+		return children
+	}
+	return mapTree(res, (function(name) { return name == "template" }), mapper)
+}
+
+exports.wykedown = wykedown
+exports.parse    = function(source) { return markdown.parse(source, wykedown) }
+exports.toHTML   = function(source) { return markdown.toHTML(source, wykedown) }
+exports.utils    = {
+	mapTree : mapTree
+}