[from now] 2014/08/01 20:47:25

diff --git a/src/main/groovy/gaiden/BindingBuilder.groovy b/src/main/groovy/gaiden/BindingBuilder.groovy
index 40264b3..8e7f3a3 100644
--- a/src/main/groovy/gaiden/BindingBuilder.groovy
+++ b/src/main/groovy/gaiden/BindingBuilder.groovy
@@ -22,6 +22,8 @@ import groovy.transform.CompileStatic
 import java.nio.file.Path
 import java.nio.file.Paths

+import static org.apache.commons.lang3.StringEscapeUtils.*
+
 /**
  * Builder for binding to be passed to a template engine.
  *
@@ -35,6 +37,8 @@ class BindingBuilder {
     private String title
     private Path tocOutputFilePath

+    private Path outputDirectory
+
     private String content
     private Path sourcePath
     private Path outputPath
@@ -43,8 +47,9 @@ class BindingBuilder {

     private PageReferenceFactory pageReferenceFactory

-    BindingBuilder(String title, Path tocOutputFilePath, PageReferenceFactory pageReferenceFactory) {
+    BindingBuilder(String title, Path outputDirectory, Path tocOutputFilePath, PageReferenceFactory pageReferenceFactory) {
         this.title = title
+        this.outputDirectory = outputDirectory
         this.tocOutputFilePath = tocOutputFilePath
         this.pageReferenceFactory = pageReferenceFactory
     }
@@ -102,21 +107,20 @@ class BindingBuilder {
             return EMPTY_STRING
         }

-        def previousTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath))?.previous
+        def previousTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath, null))?.previous
         if (!previousTocNode) {
             return EMPTY_STRING
         }

         if (!previousTocNode.pageSource) {
-            return "<< $previousTocNode.title".encodeAsHtml()
+            return escapeHtml4("<< $previousTocNode.title")
         }

-
         def relativePath = outputPath.relativize(previousTocNode.pageSource.outputPath)

         def sb = new StringBuilder()
-        sb << "<a href='${relativePath + previousTocNode.pageReference.hash}' class='prev'>"
-        sb << "<< $previousTocNode.title".encodeAsHtml()
+        sb << "<a href='${relativePath.toString() + previousTocNode.pageReference.hash}' class='prev'>"
+        sb << escapeHtml4("<< $previousTocNode.title")
         sb << "</a>"
         return sb.toString()
     }
@@ -126,20 +130,20 @@ class BindingBuilder {
             return EMPTY_STRING
         }

-        def nextTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath))?.next
+        def nextTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath, null))?.next
         if (!nextTocNode) {
             return EMPTY_STRING
         }

         if (!nextTocNode.pageSource) {
-            return "$nextTocNode.title >>".encodeAsHtml()
+            return escapeHtml4("$nextTocNode.title >>")
         }

         def relativePath = outputPath.relativize(nextTocNode.pageSource.outputPath)

         def sb = new StringBuilder()
-        sb << "<a href='${relativePath + nextTocNode.pageReference.hash}' class='next'>"
-        sb << "$nextTocNode.title >>".encodeAsHtml()
+        sb << "<a href='${relativePath.toString() + nextTocNode.pageReference.hash}' class='next'>"
+        sb << escapeHtml4("$nextTocNode.title >>")
         sb << "</a>"
         return sb.toString()
     }
@@ -150,11 +154,15 @@ class BindingBuilder {
             if (!resourceFile.absolute) {
                 return resourceFilePath
             }
-            outputPath.relativize(resourceFile).toString()
+
+            def src = outputDirectory.resolve(outputPath)
+            def dest = outputDirectory.resolve(resourceFile.toString().substring(1))
+
+            return src.parent.relativize(dest).toString()
         }
     }

     private String getTocPath() {
-        outputPath.relativize(tocOutputFilePath).toString()
+        outputPath.parent.relativize(tocOutputFilePath).toString()
     }
 }
diff --git a/src/main/groovy/gaiden/DocumentSource.groovy b/src/main/groovy/gaiden/DocumentSource.groovy
index 7ad35ef..355c717 100644
--- a/src/main/groovy/gaiden/DocumentSource.groovy
+++ b/src/main/groovy/gaiden/DocumentSource.groovy
@@ -35,6 +35,8 @@ class DocumentSource {
      * @return the page source
      */
     PageSource findPageSource(PageReference pageReference) {
-        pageSources.find { it.matches(pageReference) }
+        pageSources.find {
+            it.path == pageReference.path
+        }
     }
 }
diff --git a/src/main/groovy/gaiden/DocumentWriter.groovy b/src/main/groovy/gaiden/DocumentWriter.groovy
index 9184fee..ef1c399 100644
--- a/src/main/groovy/gaiden/DocumentWriter.groovy
+++ b/src/main/groovy/gaiden/DocumentWriter.groovy
@@ -24,7 +24,6 @@ import org.springframework.stereotype.Component
 import java.nio.file.Files
 import java.nio.file.Path

-
 /**
  * A document writer writes a {@link Document} to files.
  *
@@ -73,8 +72,7 @@ class DocumentWriter {
         if (Files.notExists(path.parent)) {
             Files.createDirectories(path.parent)
         }
-
-        path.write(content, gaidenConfig.outputEncoding)
+        Files.write(path, content.getBytes(gaidenConfig.outputEncoding))
     }

     private void copyStaticFiles() {
diff --git a/src/main/groovy/gaiden/GaidenConfig.groovy b/src/main/groovy/gaiden/GaidenConfig.groovy
index 7d0d9fe..bacad5c 100644
--- a/src/main/groovy/gaiden/GaidenConfig.groovy
+++ b/src/main/groovy/gaiden/GaidenConfig.groovy
@@ -119,7 +119,7 @@ class GaidenConfig {
     }

     Path getTocOutputFile() {
-        Paths.get(tocOutputFilePath)
+        outputDirectory.resolve(tocOutputFilePath)
     }

     Path getGaidenConfigFile() {
diff --git a/src/main/groovy/gaiden/PageBuilder.groovy b/src/main/groovy/gaiden/PageBuilder.groovy
index 4aba7e7..d4d366e 100644
--- a/src/main/groovy/gaiden/PageBuilder.groovy
+++ b/src/main/groovy/gaiden/PageBuilder.groovy
@@ -61,7 +61,7 @@ class PageBuilder {
     private String buildPage(PageBuildContext context, PageSource pageSource) {
         def content = markdownProcessor.markdownToHtml(context, pageSource)

-        def binding = new BindingBuilder(gaidenConfig.title, gaidenConfig.tocOutputFile, pageReferenceFactory)
+        def binding = new BindingBuilder(gaidenConfig.title, gaidenConfig.outputDirectory, gaidenConfig.tocOutputFile, pageReferenceFactory)
             .setContent(content)
             .setPageBuildContext(context)
             .setOutputPath(pageSource.outputPath)
diff --git a/src/main/groovy/gaiden/PageReferenceFactory.groovy b/src/main/groovy/gaiden/PageReferenceFactory.groovy
index 75706ed..f99acd6 100644
--- a/src/main/groovy/gaiden/PageReferenceFactory.groovy
+++ b/src/main/groovy/gaiden/PageReferenceFactory.groovy
@@ -15,7 +15,7 @@ class PageReferenceFactory {
     @Autowired
     GaidenConfig gaidenConfig

-    PageReference get(Path path, PageSource basePageSource = null) {
+    PageReference get(Path path, PageSource basePageSource) {
         return new PageReference(
             path: getPath(path, basePageSource),
             hash: getHash(path),
@@ -23,18 +23,19 @@ class PageReferenceFactory {
     }

     private Path getPath(Path original, PageSource basePageSource) {
-        def basePath = getBasePath(original)
+        def path = removeHash(original)

-        if (basePath.absolute) {
-            return getCanonicalPath(gaidenConfig.pagesDirectory.resolve(basePath))
+        if (path.absolute) {
+            return getCanonicalPath(gaidenConfig.pagesDirectory.resolve(path.toString().substring(1)))
         }

         if (!basePageSource) {
             // TODO warning log
-            return basePath
+            // TOCの場合
+            return getCanonicalPath(gaidenConfig.pagesDirectory.resolve(path))
         }

-        return getCanonicalPath(basePageSource.path.resolve(basePath).toAbsolutePath())
+        return getCanonicalPath(basePageSource.path.resolve(path).toAbsolutePath())
     }

     private static Path getCanonicalPath(Path path) {
@@ -43,7 +44,6 @@ class PageReferenceFactory {
         }

         def found = SourceCollector.PAGE_SOURCE_EXTENSIONS.collect { String extension ->
-
             Paths.get("${path.toString()}.${extension}")
         }.find { Path pathWithExtension ->
             Files.exists(pathWithExtension)
@@ -65,7 +65,7 @@ class PageReferenceFactory {
         filename.substring(hashIndex)
     }

-    private static Path getBasePath(Path path) {
+    private static Path removeHash(Path path) {
         def filename = path.fileName.toString()
         def hashIndex = filename.lastIndexOf("#")

diff --git a/src/main/groovy/gaiden/SourceCollector.groovy b/src/main/groovy/gaiden/SourceCollector.groovy
index bafa8bc..1200d5f 100644
--- a/src/main/groovy/gaiden/SourceCollector.groovy
+++ b/src/main/groovy/gaiden/SourceCollector.groovy
@@ -16,6 +16,7 @@

 package gaiden

+import gaiden.util.PathUtils
 import groovy.transform.CompileStatic
 import org.apache.commons.io.FilenameUtils
 import org.springframework.beans.factory.annotation.Autowired
@@ -63,7 +64,7 @@ class SourceCollector {

     private PageSource createPageSource(Path path) {
         def relativePath = gaidenConfig.pagesDirectory.relativize(path)
-        def outputPath = gaidenConfig.outputDirectory.resolve(relativePath)
+        def outputPath = gaidenConfig.outputDirectory.resolve(PathUtils.replaceExtension(relativePath, "html"))
         new PageSource(
             path: path,
             outputPath: outputPath,
diff --git a/src/main/groovy/gaiden/Toc.groovy b/src/main/groovy/gaiden/Toc.groovy
index c1dd0e3..52b768c 100644
--- a/src/main/groovy/gaiden/Toc.groovy
+++ b/src/main/groovy/gaiden/Toc.groovy
@@ -48,7 +48,6 @@ class Toc {
      * @return TOC node found
      */
     TocNode findTocNode(PageReference pageReference) {
-        tocNodes.find { it.pageSource?.matches(pageReference) }
+        tocNodes.find { it.pageSource?.path == pageReference.path }
     }
-
 }
diff --git a/src/main/groovy/gaiden/TocBuilder.groovy b/src/main/groovy/gaiden/TocBuilder.groovy
index 3bc0697..e78f0ca 100644
--- a/src/main/groovy/gaiden/TocBuilder.groovy
+++ b/src/main/groovy/gaiden/TocBuilder.groovy
@@ -18,12 +18,17 @@ package gaiden

 import gaiden.context.BuildContext
 import gaiden.message.MessageSource
+import gaiden.util.PathUtils
 import groovy.transform.CompileStatic
 import groovy.transform.TypeCheckingMode
 import groovy.xml.MarkupBuilder
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Component

+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+
 /**
  * A builder of TOC.
  *
@@ -45,6 +50,9 @@ class TocBuilder {
     @Autowired
     MessageSource messageSource

+    @Autowired
+    PageReferenceFactory pageReferenceFactory
+
     private List<TocNode> tocNodes = []

     /**
@@ -53,7 +61,7 @@ class TocBuilder {
      * @return {@link Toc}'s instance
      */
     Toc build(BuildContext context) {
-        if (!gaidenConfig.tocFile.exists()) {
+        if (Files.notExists(gaidenConfig.tocFile)) {
             return null
         }

@@ -61,13 +69,13 @@ class TocBuilder {
         def tocNode = toTocNodes(context, tocSourceNode.children())
         def tocContent = buildContent(context, tocNode)

-        def binding = new BindingBuilder(gaidenConfig.title, gaidenConfig.tocOutputFilePath)
+        def binding = new BindingBuilder(gaidenConfig.title, gaidenConfig.outputDirectory, gaidenConfig.tocOutputFile, pageReferenceFactory)
             .setContent(tocContent)
-            .setOutputPath(gaidenConfig.tocOutputFilePath)
+            .setOutputPath(gaidenConfig.tocOutputFile)
             .build()

         def content = templateEngine.make(binding)
-        new Toc(path: gaidenConfig.tocOutputFilePath, content: content, tocNodes: tocNodes)
+        new Toc(path: gaidenConfig.tocOutputFile, content: content, tocNodes: tocNodes)
     }

     @CompileStatic(TypeCheckingMode.SKIP)
@@ -120,9 +128,10 @@ class TocBuilder {
         writer.toString()
     }

-    private String resolveOutputPath(BuildContext context, String path) {
-        def pageReference = new PageReference(path)
-        if (pageReference.extension != null && pageReference.extension != "md") {
+    private String resolveOutputPath(BuildContext context, Path path) {
+        def pageReference = pageReferenceFactory.get(path, null)
+        def extension = PathUtils.getExtension(pageReference.path)
+        if (!(extension in SourceCollector.PAGE_SOURCE_EXTENSIONS)) {
             return path
         }

@@ -131,15 +140,16 @@ class TocBuilder {
             System.err.println("WARNING: " + messageSource.getMessage("toc.page.reference.not.exists.message", [path]))
             return null
         }
-        return pageSource.outputPath + pageReference.fragment
+
+        return gaidenConfig.tocOutputFile.parent.relativize(pageSource.outputPath).toString() + pageReference.hash
     }

     private List<TocNode> toTocNodes(BuildContext context, List<Node> nodes) {
         nodes.collect { Node node ->
             def tocNode = new TocNode()
-            tocNode.path = node.name()
+            tocNode.path = Paths.get(node.name() as String)
             tocNode.title = node.attributes().title
-            tocNode.pageSource = context.documentSource.findPageSource(new PageReference(tocNode.path))
+            tocNode.pageSource = context.documentSource.findPageSource(pageReferenceFactory.get(tocNode.path, null))

             if (!tocNodes.empty) {
                 def previous = tocNodes.last()
diff --git a/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy b/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
index 0919bfd..e0a982b 100644
--- a/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
+++ b/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
@@ -29,6 +29,7 @@ import org.pegdown.ast.ExpLinkNode
 import org.pegdown.ast.RefLinkNode

 import java.nio.file.Path
+import java.nio.file.Paths

 import static org.pegdown.FastEncoder.*

@@ -70,7 +71,7 @@ class GaidenLinkRenderer extends LinkRenderer {
             return createRendering(url, title, text)
         }

-        def pageReference = pageReferenceFactory.get(url, pageSource)
+        def pageReference = pageReferenceFactory.get(Paths.get(url), pageSource)

         def targetPageSource = context.documentSource.findPageSource(pageReference)
         if (!targetPageSource) {
diff --git a/src/main/groovy/gaiden/util/PathUtils.groovy b/src/main/groovy/gaiden/util/PathUtils.groovy
index 0c54209..8e386f6 100644
--- a/src/main/groovy/gaiden/util/PathUtils.groovy
+++ b/src/main/groovy/gaiden/util/PathUtils.groovy
@@ -18,6 +18,10 @@ import static java.nio.file.StandardCopyOption.*
 @CompileStatic
 class PathUtils {

+    static String getExtension(Path path) {
+        FilenameUtils.getExtension(path.toString())
+    }
+
     /**
      * Replaces the extension of filename.
      *
@@ -40,8 +44,12 @@ class PathUtils {
     }

     static void copyFiles(Path src, Path dest) {
-        src.eachFileRecurse(FileType.FILES) { Path file ->
-            Files.copy(file, dest.resolve(src.relativize(file)), REPLACE_EXISTING)
+        src.eachFileRecurse(FileType.FILES) { Path srcFile ->
+            def destFile = dest.resolve(src.relativize(srcFile))
+            if (Files.notExists(destFile.parent)) {
+                Files.createDirectories(destFile.parent)
+            }
+            Files.copy(srcFile, destFile, REPLACE_EXISTING)
         }
     }
 }
[from now] 2014/08/01 20:48:57

diff --git a/src/main/groovy/gaiden/BindingBuilder.groovy b/src/main/groovy/gaiden/BindingBuilder.groovy
index 8e7f3a3..75ecf33 100644
--- a/src/main/groovy/gaiden/BindingBuilder.groovy
+++ b/src/main/groovy/gaiden/BindingBuilder.groovy
@@ -107,7 +107,7 @@ class BindingBuilder {
             return EMPTY_STRING
         }

-        def previousTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath, null))?.previous
+        def previousTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath))?.previous
         if (!previousTocNode) {
             return EMPTY_STRING
         }
@@ -130,7 +130,7 @@ class BindingBuilder {
             return EMPTY_STRING
         }

-        def nextTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath, null))?.next
+        def nextTocNode = pageBuildContext.toc.findTocNode(pageReferenceFactory.get(sourcePath))?.next
         if (!nextTocNode) {
             return EMPTY_STRING
         }
diff --git a/src/main/groovy/gaiden/PageReferenceFactory.groovy b/src/main/groovy/gaiden/PageReferenceFactory.groovy
index f99acd6..392a6d6 100644
--- a/src/main/groovy/gaiden/PageReferenceFactory.groovy
+++ b/src/main/groovy/gaiden/PageReferenceFactory.groovy
@@ -15,7 +15,7 @@ class PageReferenceFactory {
     @Autowired
     GaidenConfig gaidenConfig

-    PageReference get(Path path, PageSource basePageSource) {
+    PageReference get(Path path, PageSource basePageSource = null) {
         return new PageReference(
             path: getPath(path, basePageSource),
             hash: getHash(path),
diff --git a/src/main/groovy/gaiden/TocBuilder.groovy b/src/main/groovy/gaiden/TocBuilder.groovy
index e78f0ca..e5322aa 100644
--- a/src/main/groovy/gaiden/TocBuilder.groovy
+++ b/src/main/groovy/gaiden/TocBuilder.groovy
@@ -149,7 +149,7 @@ class TocBuilder {
             def tocNode = new TocNode()
             tocNode.path = Paths.get(node.name() as String)
             tocNode.title = node.attributes().title
-            tocNode.pageSource = context.documentSource.findPageSource(pageReferenceFactory.get(tocNode.path, null))
+            tocNode.pageSource = context.documentSource.findPageSource(pageReferenceFactory.get(tocNode.path))

             if (!tocNodes.empty) {
                 def previous = tocNodes.last()
[from now] 2014/08/01 20:57:32

diff --git a/src/main/groovy/gaiden/PageReferenceFactory.groovy b/src/main/groovy/gaiden/PageReferenceFactory.groovy
index 392a6d6..f8ec667 100644
--- a/src/main/groovy/gaiden/PageReferenceFactory.groovy
+++ b/src/main/groovy/gaiden/PageReferenceFactory.groovy
@@ -30,8 +30,6 @@ class PageReferenceFactory {
         }

         if (!basePageSource) {
-            // TODO warning log
-            // TOCの場合
             return getCanonicalPath(gaidenConfig.pagesDirectory.resolve(path))
         }

@@ -72,6 +70,6 @@ class PageReferenceFactory {
         if (hashIndex == -1) {
             return path
         }
-        path.parent.resolveSibling(filename.substring(0, hashIndex))
+        return path.resolveSibling(filename.substring(0, hashIndex))
     }
 }