Permalink
Browse files

Fix Markdown headers in Codo comments.

If you have a `h3` Markdown header `###`, then the
converted block comment is illegal:

    # I'am a comment
    #
    # ### I'm a header
    #
    class TestClass

 will become

     ###
     I'am a comment

     ### I'm a header

     ###
     class TestClass

 and this isn't valid CoffeeScript. As fix I'm using the same
 technique as in Haml-Coffe: Prefixing valid `#` chars with
 an unicode character \u0091, so the resulting code will be:

      ###
      I'am a comment

       # # # I'm a header

      ###
      class TestClass

This is valid CoffeeScript and can be parsed. Prior to the
Markdown conversion, the \u0091 is removed again.

This fixes #55.
  • Loading branch information...
1 parent 317a453 commit b9df5db51493ea0ae95b28620108d182c6371acc @netzpirat netzpirat committed Aug 22, 2012
View
@@ -1,3 +1,7 @@
+# Master
+
+- [#55](https://github.com/netzpirat/codo/issues/55): Markdown Headings in Codo comments fixed.
+
# Version 1.2.1 - August 16, 2012
- [#39](https://github.com/netzpirat/codo/issues/39): Test alternative browsers.
View
@@ -12,9 +12,9 @@ group :codo do
end
# Generate codo doc
- guard :shell do
- watch(%r{src|theme}) { `./bin/codo` }
- end
+ #guard :shell do
+ # watch(%r{src|theme}) { `./bin/codo` }
+ #end
end
group :theme do
View
@@ -29,22 +29,31 @@ for filename in walkdir.sync './spec/templates'
})
filename = filename.substring process.cwd().length + 1
- tokens = parser.parseContent source, filename
- generated = JSON.stringify(parser.toJSON(), null, 2)
-
- report = "\n-------------------- CoffeeScript ----------------------\n"
- report += source
- report += "\n------------- Preprocessed CoffeeScript-----------------\n"
- report += parser.convertComments(source)
- report += "\n----------------------- Nodes --------------------------"
- report += tokens.toString()
- report += "\n-------------------- Parsed JSON ------------------------\n"
- report += generated
- report += "\n------------------- Expected JSON ---------------------\n"
- report += expected
- report += "\n-------------------------------------------------------\n"
-
- expect({
- generated: generated
- report: report.split('\n').join('\n ')
- }).toBeCompiledTo(expected)
+
+ try
+ tokens = parser.parseContent source, filename
+ generated = JSON.stringify(parser.toJSON(), null, 2)
+
+ report = "\n-------------------- CoffeeScript ----------------------\n"
+ report += source
+ report += "\n------------- Preprocessed CoffeeScript-----------------\n"
+ report += parser.convertComments(source)
+ report += "\n----------------------- Nodes --------------------------"
+ report += tokens.toString()
+ report += "\n-------------------- Parsed JSON ------------------------\n"
+ report += generated
+ report += "\n------------------- Expected JSON ---------------------\n"
+ report += expected
+ report += "\n-------------------------------------------------------\n"
+
+ expect({
+ generated: generated
+ report: report.split('\n').join('\n ')
+ }).toBeCompiledTo(expected)
+
+ catch e
+ expect({
+ generated: generated
+ report: "#{ filename }: #{ e.message }\n\n #{ source }"
+ }).toBeCompiledTo(expected)
+
@@ -0,0 +1,27 @@
+# Codo - the CoffeeScript API documentation generator
+#
+# # Header 1
+#
+# This is a paragraph.
+#
+# ## Header 2
+#
+# This is a paragraph.
+#
+# ### Header 3
+#
+# This is a paragraph.
+#
+# #### Header 4
+#
+# This is a paragraph.
+#
+# ##### Header 5
+#
+# This is a paragraph.
+#
+# ###### Header 6
+#
+# This is a paragraph.
+#
+class TestMarkdownDocumentation
@@ -0,0 +1,16 @@
+[
+ {
+ "file": "spec/templates/classes/class_description_markdown.coffee",
+ "doc": {
+ "comment": "<p>Codo - the CoffeeScript API documentation generator </p> <h1>Header 1</h1> <p>This is a paragraph. </p> <h2>Header 2</h2> <p>This is a paragraph. </p> <h3>Header 3</h3> <p>This is a paragraph. </p> <h4>Header 4</h4> <p>This is a paragraph. </p> <h5>Header 5</h5> <p>This is a paragraph. </p> <h6>Header 6</h6> <p>This is a paragraph. </p> ",
+ "summary": "Codo - the CoffeeScript API documentation generator"
+ },
+ "class": {
+ "className": "TestMarkdownDocumentation",
+ "name": "TestMarkdownDocumentation",
+ "namespace": ""
+ },
+ "methods": [],
+ "variables": []
+ }
+]
View
@@ -17,7 +17,7 @@ module.exports = class Doc extends Node
constructor: (@node, @options) ->
try
if @node
- @parseTags @leftTrimBlock(@node.comment.split('\n'))
+ @parseTags @leftTrimBlock(@node.comment.replace(/\u0091/gm, '').split('\n'))
catch error
console.warn('Create doc error:', @node, error) if @options.verbose
@@ -233,9 +233,12 @@ module.exports = class Doc extends Node
comment.push line
text = comment.join('\n')
- @summary = _.str.clean(/((?:.|\n)*?\.[\s$])/.exec(text)?[1] || text)
@comment = marked(text).replace /\n+/g, ' '
+ sentence = /((?:.|\n)*?[.#][\s$])/.exec(text)
+ sentence = sentence[1].replace(/\s*#\s*$/, '') if sentence
+ @summary = _.str.clean(sentence || text)
+
# Get a JSON representation of the object
#
# @return [Object] the JSON object
View
@@ -106,48 +106,53 @@ module.exports = class Parser
# @param [String] content the CoffeeScript file content
#
convertComments: (content) ->
- result = []
- comment = []
- inComment = false
- indentComment = 0
+ result = []
+ comment = []
+ inComment = false
+ inBlockComment = false
+ indentComment = 0
for line in content.split('\n')
- commentLine = /^(\s*#)\s?(\s*.*)/.exec(line)
- if commentLine and commentLine[2].substring(0, 2) isnt '##'
- show = true
-
- if inComment
- comment.push commentLine[2]
- else
- inComment = true
- indentComment = commentLine[1].length - 1
-
- comment.push whitespace(indentComment) + '###'
- comment.push commentLine[2]
+
+ blockComment = /^\s*#{3}/.exec(line)
+ if blockComment || inBlockComment
+ inBlockComment = !inBlockComment if blockComment
+ result.push line
else
- if inComment
- inComment = false
- comment.push whitespace(indentComment) + '###'
-
- # Push here comments only before certain lines
- if ///
- ( # Class
- class\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*
- | # Mixin or assignment
- ^\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff.]*\s+\=
- | # Function
- [$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*\s*:\s*(\(.*\)\s*)?[-=]>
- | # Function
- @[A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*\s*=\s*(\(.*\)\s*)?[-=]>
- | # Constant
- @[$A-Z_][A-Z_]*)
- ///.exec line
-
+ commentLine = /^(\s*#)\s?(\s*.*)/.exec(line)
+ if commentLine
+ if inComment
+ comment.push commentLine[2]?.replace /#/g, "\u0091#"
+ else
+ inComment = true
+ indentComment = commentLine[1].length - 1
+
+ comment.push whitespace(indentComment) + '###'
+ comment.push commentLine[2]?.replace /#/g, "\u0091#"
+ else
+ if inComment
+ inComment = false
+ comment.push whitespace(indentComment) + '###'
+
+ # Push here comments only before certain lines
+ if ///
+ ( # Class
+ class\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*
+ | # Mixin or assignment
+ ^\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff.]*\s+\=
+ | # Function
+ [$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*\s*:\s*(\(.*\)\s*)?[-=]>
+ | # Function
+ @[A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*\s*=\s*(\(.*\)\s*)?[-=]>
+ | # Constant
+ @[$A-Z_][A-Z_]*)
+ ///.exec line
+
result.push c for c in comment
-
- comment = []
-
- result.push line
+
+ comment = []
+
+ result.push line
result.join('\n')

0 comments on commit b9df5db

Please sign in to comment.