Process short links.
diff --git a/dokka.iml b/dokka.iml
index 509dfa7..b0393b7 100644
--- a/dokka.iml
+++ b/dokka.iml
@@ -13,6 +13,6 @@
     <orderEntry type="library" name="kotlin" level="project" />
     <orderEntry type="library" name="kotlin-compiler" level="project" />
     <orderEntry type="library" name="junit:junit:4.11" level="project" />
-    <orderEntry type="library" name="idea-markdown" level="project" />
+    <orderEntry type="library" name="markdown" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt
index 8079fb4..462e886 100644
--- a/src/Kotlin/ContentBuilder.kt
+++ b/src/Kotlin/ContentBuilder.kt
@@ -5,17 +5,16 @@
 import org.jetbrains.jet.lang.resolve.*
 import org.jetbrains.jet.lang.resolve.scopes.*
 import org.jetbrains.jet.lang.resolve.name.*
-import net.nicoulaj.idea.markdown.lang.*
+import org.intellij.markdown.*
 
 public fun DocumentationBuilder.buildContent(tree: MarkdownNode, descriptor: DeclarationDescriptor): Content {
+//    println(tree.toTestString())
     val nodeStack = ArrayDeque<ContentNode>()
     nodeStack.push(Content())
 
     tree.visit {(node, processChildren) ->
         val parent = nodeStack.peek()!!
-        val nodeType = node.type
-        val nodeText = tree.text
-        when (nodeType) {
+        when (node.type) {
             MarkdownElementTypes.UNORDERED_LIST -> {
                 nodeStack.push(ContentList())
                 processChildren()
@@ -46,33 +45,40 @@
                 processChildren()
                 parent.append(nodeStack.pop())
             }
-        /*            MarkdownElementTypes.ANONYMOUS_SECTION -> {
-                        nodeStack.push(ContentSection(""))
-                        processChildren()
-                        parent.append(nodeStack.pop())
-                    }
-                    MarkdownElementTypes.DIRECTIVE -> {
-                        val name = tree.findChildByType(node, MarkdownElementTypes.DIRECTIVE_NAME)?.let { tree.getNodeText(it) } ?: ""
-                        val params = tree.findChildByType(node, MarkdownElementTypes.DIRECTIVE_PARAMS)?.let { tree.getNodeText(it) } ?: ""
-                        when (name) {
-                            "code" -> parent.append(functionBody(descriptor, params))
-                        }
-                    }
-                    MarkdownElementTypes.NAMED_SECTION -> {
-                        val label = tree.findChildByType(node, MarkdownElementTypes.SECTION_NAME)?.let { tree.getNodeText(it) } ?: ""
-                        nodeStack.push(ContentSection(label))
-                        processChildren()
-                        parent.append(nodeStack.pop())
-                    }*/
-            MarkdownElementTypes.INLINE_LINK -> {
-                val target = node.child(MarkdownElementTypes.LINK_TITLE)?.let { it.text } ?: ""
-                val href = node.child(MarkdownElementTypes.LINK_DESTINATION)?.let { it.text }
-                val link = if (href != null) ContentExternalLink(href) else ContentExternalLink(target)
-                link.append(ContentText(target))
-                parent.append(link)
+/*
+            MarkdownElementTypes.DIRECTIVE -> {
+                val name = tree.findChildByType(node, MarkdownElementTypes.DIRECTIVE_NAME)?.let { tree.getNodeText(it) } ?: ""
+                val params = tree.findChildByType(node, MarkdownElementTypes.DIRECTIVE_PARAMS)?.let { tree.getNodeText(it) } ?: ""
+                when (name) {
+                    "code" -> parent.append(functionBody(descriptor, params))
+                }
+            }
+*/
+            MarkdownElementTypes.SECTION -> {
+                val label = node.child(MarkdownTokenTypes.SECTION_ID)?.let { it.text.trimLeading("$").trim("{","}") } ?: ""
+                nodeStack.push(ContentSection(label))
+                processChildren()
+                parent.append(nodeStack.pop())
+            }
+            MarkdownElementTypes.SHORT_REFERENCE_LINK -> {
+                val label = node.child(MarkdownElementTypes.LINK_LABEL)
+                val target = label?.child(MarkdownTokenTypes.TEXT)
+                if (target != null) {
+                    val link = ContentExternalLink(target.text)
+                    link.append(ContentText(target.text))
+                    parent.append(link)
+                }
+            }
+            MarkdownTokenTypes.WHITE_SPACE,
+            MarkdownTokenTypes.EOL -> {
+                if (nodeStack.peek() is ContentParagraph && node.parent?.children?.last() != node) {
+                    nodeStack.push(ContentText(node.text))
+                    processChildren()
+                    parent.append(nodeStack.pop())
+                }
             }
             MarkdownTokenTypes.TEXT -> {
-                nodeStack.push(ContentText(nodeText))
+                nodeStack.push(ContentText(node.text))
                 processChildren()
                 parent.append(nodeStack.pop())
             }
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt
index d8be9d5..c2d2831 100644
--- a/src/Kotlin/DocumentationBuilder.kt
+++ b/src/Kotlin/DocumentationBuilder.kt
@@ -4,7 +4,6 @@
 import org.jetbrains.dokka.DocumentationNode.*
 import org.jetbrains.jet.lang.types.*
 import org.jetbrains.jet.lang.types.lang.*
-import org.jetbrains.jet.lang.resolve.scopes.*
 import org.jetbrains.jet.lang.resolve.name.*
 import org.jetbrains.jet.lang.resolve.lazy.*
 
@@ -218,6 +217,7 @@
     fun ValueParameterDescriptor.build(): DocumentationNode {
         val node = DocumentationNode(this, Kind.Parameter)
         node.appendType(getType())
+        register(this, node)
         return node
     }
 
@@ -301,9 +301,9 @@
         }
     }
 
-    fun getResolutionScope(node: DocumentationNode): JetScope {
+    fun getResolutionScope(node: DocumentationNode): DeclarationDescriptor {
         val descriptor = nodeToDescriptor[node] ?: throw IllegalArgumentException("Node is not known to this context")
-        return getResolutionScope(descriptor)
+        return descriptor
     }
 
     fun resolveContentLinks(node: DocumentationNode, content: ContentNode) {
@@ -311,26 +311,38 @@
         for (child in snapshot) {
             if (child is ContentExternalLink) {
                 val referenceText = child.href
-                if (Name.isValidIdentifier(referenceText)) {
-                    val scope = getResolutionScope(node)
-                    val symbolName = Name.guess(referenceText)
-                    val symbol = scope.getLocalVariable(symbolName) ?:
-                            scope.getProperties(symbolName).firstOrNull() ?:
-                            scope.getFunctions(symbolName).firstOrNull() ?:
-                            scope.getClassifier(symbolName)
+                val symbol = resolveReference(getResolutionScope(node), referenceText)
+                if (symbol != null) {
+                    val targetNode = descriptorToNode[symbol]
+                    val contentLink = if (targetNode != null) ContentNodeLink(targetNode) else ContentExternalLink("#")
 
-                    if (symbol != null) {
-                        val targetNode = descriptorToNode[symbol]
-                        val contentLink = if (targetNode != null) ContentNodeLink(targetNode) else ContentExternalLink("#")
-
-                        val index = content.children.indexOf(child)
-                        content.children.remove(index)
-                        contentLink.children.addAll(child.children)
-                        content.children.add(index, contentLink)
-                    }
+                    val index = content.children.indexOf(child)
+                    content.children.remove(index)
+                    contentLink.children.addAll(child.children)
+                    content.children.add(index, contentLink)
                 }
+
             }
             resolveContentLinks(node, child)
         }
     }
+
+    private fun resolveReference(context: DeclarationDescriptor, reference: String): DeclarationDescriptor? {
+        if (Name.isValidIdentifier(reference)) {
+            val scope = getResolutionScope(context)
+            val symbolName = Name.guess(reference)
+            return scope.getLocalVariable(symbolName) ?:
+                    scope.getProperties(symbolName).firstOrNull() ?:
+                    scope.getFunctions(symbolName).firstOrNull() ?:
+                    scope.getClassifier(symbolName)
+
+        }
+
+        val names = reference.split('.')
+        val result = names.fold<String, DeclarationDescriptor?>(context) {(nextContext, name) ->
+            nextContext?.let { resolveReference(it, name) }
+        }
+
+        return result
+    }
 }
\ No newline at end of file
diff --git a/src/Markdown/MarkdownProcessor.kt b/src/Markdown/MarkdownProcessor.kt
index b5e18f9..05c4a7e 100644
--- a/src/Markdown/MarkdownProcessor.kt
+++ b/src/Markdown/MarkdownProcessor.kt
@@ -1,17 +1,19 @@
 package org.jetbrains.dokka
 
-import net.nicoulaj.idea.markdown.lang.ast.*
-import net.nicoulaj.idea.markdown.lang.parser.dialects.commonmark.*
-import net.nicoulaj.idea.markdown.lang.parser.*
-import net.nicoulaj.idea.markdown.lang.*
+import org.intellij.markdown.*
+import org.intellij.markdown.ast.*
+import org.intellij.markdown.parser.*
+import org.intellij.markdown.parser.dialects.KDocMarkerProcessor
 
-class MarkdownNode(val node: ASTNode, val markdown: String) {
-    val children: List<MarkdownNode> get() = node.children.map { MarkdownNode(it, markdown) }
+class MarkdownNode(val node: ASTNode, val parent: MarkdownNode?, val markdown: String) {
+    val children: List<MarkdownNode> = node.children.map { MarkdownNode(it, this, markdown) }
     val endOffset: Int get() = node.endOffset
     val startOffset: Int get() = node.startOffset
     val type: IElementType get() = node.type
     val text: String get() = markdown.substring(startOffset, endOffset)
     fun child(type: IElementType): MarkdownNode? = children.firstOrNull { it.type == type }
+
+    override fun toString(): String = present()
 }
 
 fun MarkdownNode.visit(action: (MarkdownNode, () -> Unit) -> Unit) {
@@ -27,9 +29,7 @@
     var level = 0
     visit {(node, visitChildren) ->
         sb.append(" ".repeat(level * 2))
-        sb.append(node.type.toString())
-        sb.append(":" + node.text.replace("\n", "\u23CE"))
-        sb.appendln()
+        node.presentTo(sb)
         level++
         visitChildren()
         level--
@@ -37,6 +37,13 @@
     return sb.toString()
 }
 
+private fun MarkdownNode.present() = StringBuilder { presentTo(this) }.toString()
+private fun MarkdownNode.presentTo(sb: StringBuilder) {
+    sb.append(type.toString())
+    sb.append(":" + text.replace("\n", "\u23CE"))
+    sb.appendln()
+}
+
 public fun MarkdownNode.toHtml(): String {
     val sb = StringBuilder()
     visit {(node, processChildren) ->
@@ -126,14 +133,14 @@
 
 fun parseMarkdown(markdown: String): MarkdownNode {
     if (markdown.isEmpty())
-        return MarkdownNode(LeafASTNode(MarkdownElementTypes.MARKDOWN_FILE, 0, 0), markdown)
-    return MarkdownNode(MarkdownParser(CommonMarkMarkerProcessor()).buildMarkdownTreeFromString(markdown), markdown)
+        return MarkdownNode(LeafASTNode(MarkdownElementTypes.MARKDOWN_FILE, 0, 0), null, markdown)
+    return MarkdownNode(MarkdownParser(KDocMarkerProcessor.Factory()).buildMarkdownTreeFromString(markdown), null, markdown)
 }
 
 fun markdownToHtml(markdown: String): String {
 
-    val tree = MarkdownParser(CommonMarkMarkerProcessor()).buildMarkdownTreeFromString(markdown)
-    val markdownTree = MarkdownNode(tree, markdown)
+    val tree = MarkdownParser(KDocMarkerProcessor.Factory()).buildMarkdownTreeFromString(markdown)
+    val markdownTree = MarkdownNode(tree, null, markdown)
     val ast = markdownTree.toTestString()
     return markdownTree.toHtml()
 }
diff --git a/test/data/functions/functionWithParams.kt b/test/data/functions/functionWithParams.kt
index 52cd074..85c4936 100644
--- a/test/data/functions/functionWithParams.kt
+++ b/test/data/functions/functionWithParams.kt
@@ -1,5 +1,6 @@
 /**
  * Multiline
+ *
  * Function
  * Documentation
  */
diff --git a/test/data/links/linkToJDK.kt b/test/data/links/linkToJDK.kt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/data/links/linkToJDK.kt
diff --git a/test/data/links/linkToMember.kt b/test/data/links/linkToMember.kt
new file mode 100644
index 0000000..b60eaed
--- /dev/null
+++ b/test/data/links/linkToMember.kt
@@ -0,0 +1,6 @@
+/**
+ * This is link to [member]
+ */
+class Foo {
+    fun member() {}
+}
\ No newline at end of file
diff --git a/test/data/links/linkToParam.kt b/test/data/links/linkToParam.kt
new file mode 100644
index 0000000..ca42a74
--- /dev/null
+++ b/test/data/links/linkToParam.kt
@@ -0,0 +1,5 @@
+/**
+ * This is link to [param]
+ */
+fun Foo(param: String) {
+}
\ No newline at end of file
diff --git a/test/data/links/linkToQualifiedMember.kt b/test/data/links/linkToQualifiedMember.kt
new file mode 100644
index 0000000..22c154f
--- /dev/null
+++ b/test/data/links/linkToQualifiedMember.kt
@@ -0,0 +1,6 @@
+/**
+ * This is link to [Foo.member]
+ */
+class Foo {
+    fun member() {}
+}
\ No newline at end of file
diff --git a/test/data/links/linkToSelf.kt b/test/data/links/linkToSelf.kt
new file mode 100644
index 0000000..74395f0
--- /dev/null
+++ b/test/data/links/linkToSelf.kt
@@ -0,0 +1,6 @@
+/**
+ * This is link to [Foo]
+ */
+class Foo {
+
+}
\ No newline at end of file
diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt
index ccef891..5a4b986 100644
--- a/test/src/TestAPI.kt
+++ b/test/src/TestAPI.kt
@@ -63,6 +63,13 @@
             append(node.text)
         }
         is ContentEmphasis -> append("*").appendChildren(node).append("*")
+        is ContentNodeLink -> {
+            append("[")
+            appendChildren(node)
+            append(" -> ")
+            append(node.node.toString())
+            append("]")
+        }
         else -> {
             appendChildren(node)
         }
diff --git a/test/src/markdown/ParserTest.kt b/test/src/markdown/ParserTest.kt
index 16892f2..80ee733 100644
--- a/test/src/markdown/ParserTest.kt
+++ b/test/src/markdown/ParserTest.kt
@@ -5,12 +5,18 @@
 import org.jetbrains.dokka.toTestString
 import org.jetbrains.dokka.toHtml
 import org.jetbrains.dokka.parseMarkdown
+import org.junit.Ignore
 
-public class ParserTest {
+Ignore public class ParserTest {
     fun runTestFor(text : String) {
+        println("MD: ---")
+        println(text)
         val markdownTree = parseMarkdown(text)
+        println("AST: ---")
         println(markdownTree.toTestString())
+        println("HTML: ---")
         println(markdownTree.toHtml())
+        println()
     }
 
     Test fun text() {
@@ -89,20 +95,20 @@
     }
 
     Test fun emphAndEmptySection() {
-        runTestFor("*text* \$sec:")
+        runTestFor("*text*\n\$sec:\n")
     }
 
     Test fun emphAndSection() {
-        runTestFor("*text* \$sec: some text")
+        runTestFor("*text*\n\$sec: some text\n")
     }
 
     Test fun emphAndBracedSection() {
-        runTestFor("Text *bold* text \${sec}: some text")
+        runTestFor("Text *bold* text \n\${sec}: some text")
     }
 
     Test fun section() {
         runTestFor(
-                "Plain text \$one: Summary \${two}: Description with *emphasis* \${An example of a section}: Example")
+                "Plain text \n\$one: Summary \n\${two}: Description with *emphasis* \n\${An example of a section}: Example")
     }
 
     Test fun anonymousSection() {
@@ -111,12 +117,12 @@
 
     Test fun specialSection() {
         runTestFor(
-                "Plain text \$\$summary: Summary \${\$description}: Description \${\$An example of a section}: Example")
+                "Plain text \n\$\$summary: Summary \n\${\$description}: Description \n\${\$An example of a section}: Example")
     }
 
     Test fun emptySection() {
         runTestFor(
-                "Plain text \$summary:")
+                "Plain text \n\$summary:")
     }
 
     val b = "$"
diff --git a/test/src/model/CommentTest.kt b/test/src/model/CommentTest.kt
index b2ad0ac..5fc9572 100644
--- a/test/src/model/CommentTest.kt
+++ b/test/src/model/CommentTest.kt
@@ -25,7 +25,7 @@
         verifyModel("test/data/comments/multilineDoc.kt") { model ->
             with(model.members.single().members.single()) {
                 assertEquals("doc1", content.summary.toTestString())
-                assertEquals("doc2\ndoc3\n", content.description.toTestString())
+                assertEquals("doc2\ndoc3", content.description.toTestString())
             }
         }
     }
diff --git a/test/src/model/FunctionTest.kt b/test/src/model/FunctionTest.kt
index c6ad93c..2a4ad0a 100644
--- a/test/src/model/FunctionTest.kt
+++ b/test/src/model/FunctionTest.kt
@@ -24,12 +24,10 @@
                 assertEquals("fn", name)
                 assertEquals(DocumentationNode.Kind.Function, kind)
                 assertEquals("Function with receiver", content.summary.toTestString())
-                assertEquals("Unit", details.elementAt(0).name)
-
                 assertEquals(4, details.count())
+                assertEquals("internal", details.elementAt(0).name)
                 assertEquals("final", details.elementAt(1).name)
-                assertEquals("internal", details.elementAt(2).name)
-                with(details.elementAt(3)) {
+                with(details.elementAt(2)) {
                     assertEquals("<this>", name)
                     assertEquals(DocumentationNode.Kind.Receiver, kind)
                     assertEquals(Content.Empty, content)
@@ -37,6 +35,7 @@
                     assertTrue(members.none())
                     assertTrue(links.none())
                 }
+                assertEquals("Unit", details.elementAt(3).name)
                 assertTrue(members.none())
                 assertTrue(links.none())
             }
@@ -51,10 +50,9 @@
                 assertEquals("generic function", content.summary.toTestString())
 
                 assertEquals(4, details.count())
-                assertEquals("Unit", details.elementAt(0).name)
+                assertEquals("private", details.elementAt(0).name)
                 assertEquals("final", details.elementAt(1).name)
-                assertEquals("private", details.elementAt(2).name)
-                with(details.elementAt(3)) {
+                with(details.elementAt(2)) {
                     assertEquals("T", name)
                     assertEquals(DocumentationNode.Kind.TypeParameter, kind)
                     assertEquals(Content.Empty, content)
@@ -62,6 +60,7 @@
                     assertTrue(members.none())
                     assertTrue(links.none())
                 }
+                assertEquals("Unit", details.elementAt(3).name)
 
                 assertTrue(members.none())
                 assertTrue(links.none())
@@ -76,15 +75,16 @@
                 assertEquals("generic function", content.summary.toTestString())
 
                 assertEquals(5, details.count())
-                assertEquals("Unit", details.elementAt(0).name)
+                assertEquals("public", details.elementAt(0).name)
                 assertEquals("final", details.elementAt(1).name)
-                assertEquals("public", details.elementAt(2).name)
-                with(details.elementAt(3)) {
+                with(details.elementAt(2)) {
                     assertEquals("T", name)
                     assertEquals(DocumentationNode.Kind.TypeParameter, kind)
                     assertEquals(Content.Empty, content)
                     with(details.single()) {
                         assertEquals("R", name)
+                        assertEquals("R", name)
+                        assertEquals("R", name)
                         assertEquals(DocumentationNode.Kind.UpperBound, kind)
                         assertEquals(Content.Empty, content)
                         assertTrue(details.none())
@@ -94,13 +94,14 @@
                     assertTrue(members.none())
                     assertTrue(links.none())
                 }
-                with(details.elementAt(4)) {
+                with(details.elementAt(3)) {
                     assertEquals("R", name)
                     assertEquals(DocumentationNode.Kind.TypeParameter, kind)
                     assertEquals(Content.Empty, content)
                     assertTrue(members.none())
                     assertTrue(links.none())
                 }
+                assertEquals("Unit", details.elementAt(4).name)
 
                 assertTrue(members.none())
                 assertTrue(links.none())
@@ -118,10 +119,9 @@
 Documentation""", content.description.toTestString())
 
                 assertEquals(4, details.count())
-                assertEquals("Unit", details.elementAt(0).name)
+                assertEquals("internal", details.elementAt(0).name)
                 assertEquals("final", details.elementAt(1).name)
-                assertEquals("internal", details.elementAt(2).name)
-                with(details.elementAt(3)) {
+                with(details.elementAt(2)) {
                     assertEquals("x", name)
                     assertEquals(DocumentationNode.Kind.Parameter, kind)
                     assertEquals("parameter", content.summary.toTestString())
@@ -129,7 +129,7 @@
                     assertTrue(members.none())
                     assertTrue(links.none())
                 }
-
+                assertEquals("Unit", details.elementAt(3).name)
                 assertTrue(members.none())
                 assertTrue(links.none())
             }
diff --git a/test/src/model/LinkTest.kt b/test/src/model/LinkTest.kt
new file mode 100644
index 0000000..151d269
--- /dev/null
+++ b/test/src/model/LinkTest.kt
@@ -0,0 +1,48 @@
+package org.jetbrains.dokka.tests
+
+import org.junit.Test
+import kotlin.test.*
+import org.jetbrains.dokka.*
+
+public class LinkTest {
+    Test fun linkToSelf() {
+        verifyModel("test/data/links/linkToSelf.kt") { model ->
+            with(model.members.single().members.single()) {
+                assertEquals("Foo", name)
+                assertEquals(DocumentationNode.Kind.Class, kind)
+                assertEquals("This is link to [Foo -> Class:Foo]", content.summary.toTestString())
+            }
+        }
+    }
+
+    Test fun linkToMember() {
+        verifyModel("test/data/links/linkToMember.kt") { model ->
+            with(model.members.single().members.single()) {
+                assertEquals("Foo", name)
+                assertEquals(DocumentationNode.Kind.Class, kind)
+                assertEquals("This is link to [member -> Function:member]", content.summary.toTestString())
+            }
+        }
+    }
+
+    Test fun linkToQualifiedMember() {
+        verifyModel("test/data/links/linkToQualifiedMember.kt") { model ->
+            with(model.members.single().members.single()) {
+                assertEquals("Foo", name)
+                assertEquals(DocumentationNode.Kind.Class, kind)
+                assertEquals("This is link to [Foo.member -> Function:member]", content.summary.toTestString())
+            }
+        }
+    }
+
+    Test fun linkToParam() {
+        verifyModel("test/data/links/linkToParam.kt") { model ->
+            with(model.members.single().members.single()) {
+                assertEquals("Foo", name)
+                assertEquals(DocumentationNode.Kind.Function, kind)
+                assertEquals("This is link to [param -> Parameter:param]", content.summary.toTestString())
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/test/src/model/PropertyTest.kt b/test/src/model/PropertyTest.kt
index 93d8176..7cd287a 100644
--- a/test/src/model/PropertyTest.kt
+++ b/test/src/model/PropertyTest.kt
@@ -40,7 +40,7 @@
                 assertEquals("String", detail(DocumentationNode.Kind.Type).name)
                 assertTrue(links.none())
                 with(members.single()) {
-                    assertEquals("<get-property>", name)
+                    assertEquals("<get>", name)
                     assertEquals(DocumentationNode.Kind.Function, kind)
                     assertEquals(Content.Empty, content)
                     assertEquals("String", detail(DocumentationNode.Kind.Type).name)
@@ -66,7 +66,7 @@
 
                 assertEquals(2, members.count())
                 with(members.elementAt(0)) {
-                    assertEquals("<get-property>", name)
+                    assertEquals("<get>", name)
                     assertEquals(DocumentationNode.Kind.Function, kind)
                     assertEquals(Content.Empty, content)
                     val get_modifiers = details(DocumentationNode.Kind.Modifier).map { it.name }