[from now] 2014/08/03 23:22:31

diff --git a/src/main/groovy/gaiden/PageReferenceFactory.groovy b/src/main/groovy/gaiden/PageReferenceFactory.groovy
index 3a61b9f..e3f7941 100644
--- a/src/main/groovy/gaiden/PageReferenceFactory.groovy
+++ b/src/main/groovy/gaiden/PageReferenceFactory.groovy
@@ -6,6 +6,7 @@
 import org.springframework.stereotype.Component

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

@@ -43,7 +44,7 @@ private Path getPath(Path original, PageSource basePageSource) {

     private static Path getCanonicalPath(Path path) {
         if (Files.exists(path)) {
-            return path.toRealPath()
+            return path.toRealPath(LinkOption.NOFOLLOW_LINKS)
         }

         def found = SourceCollector.PAGE_SOURCE_EXTENSIONS.collect { String extension ->
@@ -52,7 +53,7 @@ private static Path getCanonicalPath(Path path) {
             Files.exists(pathWithExtension)
         }
         if (found) {
-            return found.toRealPath()
+            return found.toRealPath(LinkOption.NOFOLLOW_LINKS)
         }
         return path
     }
diff --git a/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy b/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
index 1f1ed3c..1c17c6c 100644
--- a/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
+++ b/src/main/groovy/gaiden/markdown/GaidenLinkRenderer.groovy
@@ -74,7 +74,7 @@
         def pageReference = pageReferenceFactory.get(Paths.get(url), pageSource)
         def targetPageSource = context.documentSource.findPageSource(pageReference)
         if (!targetPageSource) {
-            if (isPageSourceExtension(url)) {
+            if (isPageSourceExtension(pageReference.path.toString())) {
                 System.err.println("WARNING: " + messageSource.getMessage("output.page.reference.not.exists.message", [url, pageSource.path]))
             }

diff --git a/src/main/groovy/gaiden/markdown/ImageRenderer.groovy b/src/main/groovy/gaiden/markdown/ImageRenderer.groovy
index fa1e253..3879ed3 100644
--- a/src/main/groovy/gaiden/markdown/ImageRenderer.groovy
+++ b/src/main/groovy/gaiden/markdown/ImageRenderer.groovy
@@ -22,6 +22,7 @@
 import groovy.transform.CompileStatic

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

@@ -83,7 +84,7 @@ private String getRelativeImagePath(String imagePath) {
             return imagePath
         }

-        pageSource.outputPath.parent.relativize(outputDirectory.resolve(staticDirectory.toRealPath().relativize(imageFile.toRealPath()))).toString()
+        pageSource.outputPath.parent.relativize(outputDirectory.resolve(staticDirectory.relativize(imageFile.toRealPath(LinkOption.NOFOLLOW_LINKS)))).toString()
     }

     private Path getImageFile(String imagePath) {
@@ -94,11 +95,4 @@ private Path getImageFile(String imagePath) {
             return staticDirectory.resolve(outputDirectory.relativize(pageSource.outputPath.parent).resolve(imagePath))
         }
     }
-
-    private void checkFileExists(Path imageFile, String imagePath) {
-        if (Files.notExists(imageFile)) {
-            // It is required to normalize path such as '/path/to/../images/sample.png'.
-            System.err.println("WARNING: " + messageSource.getMessage("image.reference.not.exists.message", [imagePath, pageSource.path]))
-        }
-    }
 }
diff --git a/src/test/groovy/gaiden/markdown/GaidenLinkRendererSpec.groovy b/src/test/groovy/gaiden/markdown/GaidenLinkRendererSpec.groovy
index edd7368..178e2a8 100644
--- a/src/test/groovy/gaiden/markdown/GaidenLinkRendererSpec.groovy
+++ b/src/test/groovy/gaiden/markdown/GaidenLinkRendererSpec.groovy
@@ -18,8 +18,7 @@

 import gaiden.DocumentSource
 import gaiden.GaidenSpec
-import gaiden.PageSource
-import gaiden.SourceCollector
+import gaiden.PageReferenceFactory
 import gaiden.context.PageBuildContext

 class GaidenLinkRendererSpec extends GaidenSpec {
@@ -27,13 +26,14 @@
     def "'render' should return a rendering object which has replaced link url"() {
         setup:
             def documentSource = new DocumentSource(pageSources: [
-                new PageSource(path: "first.md"),
-                new PageSource(path: "path/second.md"),
+                createPageSource("first.md"),
+                createPageSource("path/second.md")
             ])
             createFiles("first.md", "path/second.md", pageSourcePath)
             def context = new PageBuildContext(documentSource: documentSource)
-            def pageSource = new PageSource(path: pageSourcePath)
-            def linkRenderer = new GaidenLinkRenderer(context, pageSource, pagesDirectory, messageSource)
+            def pageSource = createPageSource(pageSourcePath)
+            def pageReferenceFactory = new PageReferenceFactory(gaidenConfig: gaidenConfig)
+            def linkRenderer = new GaidenLinkRenderer(context, pageSource, gaidenConfig.pagesDirectory, messageSource, pageReferenceFactory)

         when:
             def rendering = linkRenderer.render(path, "Test Title", "Test Text")
@@ -62,8 +62,9 @@
     def "'render' should not replace path if not found a page source"() {
         setup:
             def context = new PageBuildContext(documentSource: new DocumentSource(pageSources: []))
-            def pageSource = new PageSource(path: pageSourcePath)
-            def linkRenderer = new GaidenLinkRenderer(context, pageSource, pagesDirectory, messageSource)
+            def pageSource = createPageSource(pageSourcePath)
+            def pageReferenceFactory = new PageReferenceFactory(gaidenConfig: gaidenConfig)
+            def linkRenderer = new GaidenLinkRenderer(context, pageSource, gaidenConfig.pagesDirectory, messageSource, pageReferenceFactory)
             createFile(pageSourcePath)

         and:
@@ -78,7 +79,7 @@
             rendering.text == "Test Text"

         and:
-            (1..SourceCollector.PAGE_SOURCE_EXTENSIONS.size()) * printStream.println("WARNING: '$path' in $pageSourcePath refers to non-existent page")
+            1 * printStream.println("WARNING: '${path}' in ${pageSource.path.toString()} refers to non-existent page")

         where:
             pageSourcePath | path
@@ -100,9 +101,10 @@

     def "'render' should not output a warning message when a path is not Markdown"() {
         setup:
-            def context = new PageBuildContext(documentSource: new DocumentSource())
-            def pageSource = new PageSource(path: "test.md")
-            def linkRenderer = new GaidenLinkRenderer(context, pageSource, pagesDirectory, messageSource)
+            def context = new PageBuildContext(documentSource: new DocumentSource(pageSources: []))
+            def pageSource = createPageSource("test.md")
+            def pageReferenceFactory = new PageReferenceFactory(gaidenConfig: gaidenConfig)
+            def linkRenderer = new GaidenLinkRenderer(context, pageSource, gaidenConfig.pagesDirectory, messageSource, pageReferenceFactory)

         and:
             def printStream = Mock(PrintStream)
@@ -137,9 +139,10 @@

     def "'render' should not output a warning message when a path is URL"() {
         setup:
-            def context = new PageBuildContext(documentSource: new DocumentSource())
-            def pageSource = new PageSource(path: "test.md")
-            def linkRenderer = new GaidenLinkRenderer(context, pageSource, pagesDirectory, messageSource)
+            def context = new PageBuildContext(documentSource: new DocumentSource(pageSources: []))
+            def pageSource = createPageSource("test.md")
+            def pageReferenceFactory = new PageReferenceFactory(gaidenConfig: gaidenConfig)
+            def linkRenderer = new GaidenLinkRenderer(context, pageSource, gaidenConfig.pagesDirectory, messageSource, pageReferenceFactory)

         and:
             def printStream = Mock(PrintStream)
[from now] 2014/08/03 23:49:49

diff --git a/src/main/groovy/gaiden/PageReference.groovy b/src/main/groovy/gaiden/PageReference.groovy
index e4f279a..ead8785 100644
--- a/src/main/groovy/gaiden/PageReference.groovy
+++ b/src/main/groovy/gaiden/PageReference.groovy
@@ -30,85 +30,4 @@

     Path path
     String hash
-
-//    /**
-//     * The relative path from the pages directory.
-//     * <p>
-//     * The path doesn't contain a fragment(#).
-//     */
-//    String path
-//
-//    /** The fragment of path */
-//    String fragment
-//
-//    @CompileStatic(TypeCheckingMode.SKIP)
-//    PageReference(String url) {
-//        (path, fragment) = url.split("#") as List
-//        fragment = fragment ? "#${fragment}" : ""
-//    }
-//
-//    /**
-//     * Returns the abstract relative path from the pages directory.
-//     * <p>
-//     * The pass doesn't contain a file extension.
-//     *
-//     * @return the abstract relative path
-//     */
-//    String getAbstractPath() {
-//        FileUtils.removeExtension(path)
-//    }
-//
-//    /**
-//     * Returns the extension of filename.
-//     *
-//     * @return the extension of filename
-//     */
-//    String getExtension() {
-//        FileUtils.getExtension(new File(path).name)
-//    }
-//
-//    /**
-//     * Checks the path is URL.
-//     *
-//     * @return {@code true} if the path is URL
-//     */
-//    boolean isUrl() {
-//        try {
-//            new URL(path)
-//        } catch (MalformedURLException e) {
-//            return false
-//        }
-//        true
-//    }
-//
-//    /**
-//     * Checks the path is an absolute path.
-//     *
-//     * @return {@code true} if the path is an absolute path
-//     */
-//    boolean isAbsolutePath() {
-//        !path.startsWith("/")
-//    }
-//
-//    /**
-//     * Checks the extension of filename is a page source extension.
-//     *
-//     * @return {@code true} if the extension of filename is a page source extension
-//     * @see SourceCollector#PAGE_SOURCE_EXTENSIONS
-//     */
-//    boolean isPageSourceExtension() {
-//        !extension || extension in SourceCollector.PAGE_SOURCE_EXTENSIONS
-//    }
-//
-//    /**
-//     * Converts this page reference into a page reference which has a full path.
-//     *
-//     * @param rootDirectory the root directory of page sources
-//     * @param baseDirectory the directory of base
-//     * @return the page reference which has a full path
-//     */
-//    PageReference toFullPathPageReference(File rootDirectory, File baseDirectory) {
-//        assert isAbsolutePath()
-//        new PageReference(FileUtils.getRelativePathForDirectoryToFile(rootDirectory, new File(baseDirectory, path)) + fragment)
-//    }
 }
diff --git a/src/test/groovy/gaiden/DocumentBuilderSpec.groovy b/src/test/groovy/gaiden/DocumentBuilderSpec.groovy
index 40ae3a7..ef75a6a 100644
--- a/src/test/groovy/gaiden/DocumentBuilderSpec.groovy
+++ b/src/test/groovy/gaiden/DocumentBuilderSpec.groovy
@@ -18,16 +18,15 @@

 import gaiden.context.BuildContext
 import gaiden.context.PageBuildContext
-import spock.lang.Specification

-class DocumentBuilderSpec extends Specification {
+class DocumentBuilderSpec extends GaidenSpec {

     def "'build' should builds document"() {
         setup:
             def documentSource = new DocumentSource()
             documentSource.pageSources = [
-                new PageSource(path: "source1.md", content: "# markdown1"),
-                new PageSource(path: "source2.md", content: "# markdown2"),
+                createPageSource("source1.md"),
+                createPageSource("source2.md"),
             ]
             def context = new BuildContext(documentSource: documentSource)

@@ -50,5 +49,4 @@
         and:
             document
     }
-
 }
diff --git a/src/test/groovy/gaiden/DocumentWriterSpec.groovy b/src/test/groovy/gaiden/DocumentWriterSpec.groovy
index eabbb5f..e848dc2 100644
--- a/src/test/groovy/gaiden/DocumentWriterSpec.groovy
+++ b/src/test/groovy/gaiden/DocumentWriterSpec.groovy
@@ -16,22 +16,16 @@

 package gaiden

-import gaiden.util.FileUtils
+import gaiden.util.PathUtils
 import groovy.io.FileType
-import spock.lang.Specification

-class DocumentWriterSpec extends Specification {
+import java.nio.file.Path
+import java.nio.file.Paths

-    def outputDirectory = new File("build/gaiden-test-doc")
-
-    GaidenConfig gaidenConfig
+class DocumentWriterSpec extends GaidenSpec {

     def setup() {
-        outputDirectory.deleteDir()
-
-        gaidenConfig = new GaidenConfig()
-        gaidenConfig.outputDirectoryPath = outputDirectory.path
-        gaidenConfig.staticDirectoryPath = "src/test/resources/static-files"
+        PathUtils.copyFiles(Paths.get("src/test/resources/static-files"), gaidenConfig.staticDirectory)
     }

     def "'write' should write a document to files"() {
@@ -41,7 +35,7 @@ def setup() {
             def page3 = createPage("sub/document3.md")

         and:
-            def toc = new Toc(path: "toc.html", content: "<h1>table of contents</h1>")
+            def toc = new Toc(path: gaidenConfig.tocOutputFile, content: "<h1>table of contents</h1>")

         and:
             def document = new Document(pages: [page1, page2, page3], toc: toc)
@@ -49,7 +43,6 @@ def setup() {
             documentWriter.gaidenConfig = gaidenConfig

         and:
-            def saved = System.out
             def printStream = Mock(PrintStream)
             System.out = printStream

@@ -57,7 +50,7 @@ def setup() {
             documentWriter.write(document)

         then:
-            getFiles(outputDirectory) == [
+            getFiles(gaidenConfig.outputDirectory) == [
                 "document1.html",
                 "document2.html",
                 "sub/document3.html",
@@ -68,24 +61,21 @@ def setup() {
             ] as Set

         and:
-            new File("build/gaiden-test-doc/document1.html").text == page1.content
-            new File("build/gaiden-test-doc/document2.html").text == page2.content
-            new File("build/gaiden-test-doc/sub/document3.html").text == page3.content
+            gaidenConfig.outputDirectory.resolve("document1.html").text == page1.content
+            gaidenConfig.outputDirectory.resolve("document2.html").text == page2.content
+            gaidenConfig.outputDirectory.resolve("sub/document3.html").text == page3.content

         and:
-            new File("build/gaiden-test-doc/toc.html").text == toc.content
+            gaidenConfig.outputDirectory.resolve("toc.html").text == toc.content

         and:
-            1 * printStream.println("Built document at ${outputDirectory.canonicalPath}")
-
-        cleanup:
-            System.out = saved
+            1 * printStream.println("Built document at ${gaidenConfig.outputDirectory}")
     }

     def "'write' should overwrite when file already exists"() {
         setup:
             def page = createPage("document1.md")
-            def toc = new Toc(path: "toc.html", content: "<h1>table of contents</h1>")
+            def toc = new Toc(path: gaidenConfig.tocOutputFile, content: "<h1>table of contents</h1>")
             def document = new Document(pages: [page], toc: toc)

         and:
@@ -97,8 +87,8 @@ def setup() {
             documentWriter.write(document)

         then:
-            new File("build/gaiden-test-doc/document1.html").text == page.content
-            new File("build/gaiden-test-doc/toc.html").text == toc.content
+            gaidenConfig.outputDirectory.resolve("document1.html").text == page.content
+            gaidenConfig.outputDirectory.resolve("toc.html").text == toc.content
     }

     def "'write' should write a specified encoding"() {
@@ -106,7 +96,7 @@ def setup() {
             def page = createPage("document.md", "これはShift_JISのドキュメントです。")

         and:
-            def toc = new Toc(path: "toc.html", content: "<h1>これはShift_JISのTOCです</h1>")
+            def toc = new Toc(path: gaidenConfig.tocOutputFile, content: "<h1>これはShift_JISのTOCです</h1>")

         and:
             def document = new Document(pages: [page], toc: toc)
@@ -118,7 +108,7 @@ def setup() {
             documentWriter.write(document)

         then:
-            getFiles(outputDirectory) == [
+            getFiles(gaidenConfig.outputDirectory) == [
                 "document.html",
                 "images/dummy.png",
                 "css/main.css",
@@ -127,10 +117,8 @@ def setup() {
             ] as Set

         and:
-            new File("build/gaiden-test-doc/document.html").getText("Shift_JIS") == page.content
-
-        and:
-            new File("build/gaiden-test-doc/toc.html").getText("Shift_JIS") == toc.content
+            gaidenConfig.outputDirectory.resolve("document.html").getText("Shift_JIS") == page.content
+            gaidenConfig.outputDirectory.resolve("toc.html").getText("Shift_JIS") == toc.content
     }

     def "'write' should not write anything if toc file doesn't exist"() {
@@ -143,7 +131,7 @@ def setup() {
             documentWriter.write(document)

         then:
-            getFiles(outputDirectory) == [
+            getFiles(gaidenConfig.outputDirectory) == [
                 "images/dummy.png",
                 "css/main.css",
                 "js/test.js",
@@ -151,16 +139,15 @@ def setup() {
     }

     private Page createPage(String path, String content = null) {
-        def source = new PageSource(path: path)
+        def source = createPageSource(path)
         new Page(source: source, content: content ?: "<title>Document</title><p>${source.outputPath} content</p>")
     }

-    private Set getFiles(File directory) {
+    private Set getFiles(Path directory) {
         def files = []
-        directory.eachFileRecurse(FileType.FILES) {
-            files << FileUtils.getRelativePathForDirectoryToFile(directory, it)
+        directory.eachFileRecurse(FileType.FILES) { Path file ->
+            files << directory.relativize(file).toString()
         }
-        files
+        files as Set
     }
-
 }
diff --git a/src/test/groovy/gaiden/command/CreateProjectCommandSpec.groovy b/src/test/groovy/gaiden/command/CreateProjectCommandSpec.groovy
index deebde4..72fc08d 100644
--- a/src/test/groovy/gaiden/command/CreateProjectCommandSpec.groovy
+++ b/src/test/groovy/gaiden/command/CreateProjectCommandSpec.groovy
@@ -81,7 +81,7 @@ def cleanup() {
             e.code == "command.create.project.name.required.error"
     }

-    private Set collectFilePathRecurse(File directory) {
+    private static Set collectFilePathRecurse(File directory) {
         def fileset = []
         directory.eachFileRecurse {
             fileset << it.path.replaceFirst(directory.path, "")
[from now] 2014/08/03 23:55:34

diff --git a/src/test/groovy/gaiden/GaidenSpec.groovy b/src/test/groovy/gaiden/GaidenSpec.groovy
index 514af79..2e4c957 100644
--- a/src/test/groovy/gaiden/GaidenSpec.groovy
+++ b/src/test/groovy/gaiden/GaidenSpec.groovy
@@ -51,7 +51,7 @@ BuildContext createBuildContext(List<Map> pageSourceMaps) {
         new BuildContext(documentSource: documentSource)
     }

-    PageSource createPageSource(String path) {
+    PageSource createPageSource(String path, String content = null) {
         def pageSource = new PageSource()

         pageSource.path = gaidenConfig.pagesDirectory.resolve(path)
@@ -60,6 +60,9 @@ PageSource createPageSource(String path) {

         }
         Files.createFile(pageSource.path)
+        if (content) {
+            pageSource.path.write(content)
+        }

         pageSource.outputPath = gaidenConfig.outputDirectory.resolve(FilenameUtils.removeExtension(path) + ".html")

diff --git a/src/test/groovy/gaiden/PageBuilderSpec.groovy b/src/test/groovy/gaiden/PageBuilderSpec.groovy
index 9b0ffbd..51f2cf7 100644
--- a/src/test/groovy/gaiden/PageBuilderSpec.groovy
+++ b/src/test/groovy/gaiden/PageBuilderSpec.groovy
@@ -20,18 +20,17 @@
 import gaiden.markdown.GaidenMarkdownProcessor

 import java.nio.file.Files
-import java.nio.file.Path

 class PageBuilderSpec extends GaidenSpec {

-    Path templateFile
-
-    GaidenConfig gaidenConfig
     TemplateEngine templateEngine
     GaidenMarkdownProcessor gaidenMarkdownProcessor

     def setup() {
-        templateFile = Files.createTempFile("layout", "html")
+        def templateFile = gaidenConfig.templateFile
+        if (Files.notExists(templateFile.parent)) {
+            Files.createDirectories(templateFile.parent)
+        }
         templateFile << '''
             |<html>
             |<head>
@@ -43,8 +42,6 @@ def setup() {
             |</html>
             '''.stripMargin()

-        gaidenConfig = new GaidenConfig()
-        gaidenConfig.templateFilePath = templateFile
         gaidenConfig.title = "Test Title"

         templateEngine = new TemplateEngine()
@@ -55,13 +52,9 @@ def setup() {
         gaidenMarkdownProcessor.messageSource = messageSource
     }

-    def cleanup() {
-        Files.delete(templateFile)
-    }
-
     def "'build' should build a page"() {
         setup:
-            def pageSource = new PageSource(path: "test.md", content: "# Test")
+            def pageSource = createPageSource("test.md", "# Test")
             def documentSource = new DocumentSource(pageSources: [pageSource])
             def context = new PageBuildContext(documentSource: documentSource, toc: new Toc(tocNodes: []))

@@ -73,7 +66,7 @@ def cleanup() {
             def page = pageBuilder.build(context, pageSource)

         then:
-            page.path == "test.html"
+            page.path == gaidenConfig.outputDirectory.resolve("test.html")
             page.content == '''
             |<html>
             |<head>
@@ -85,5 +78,4 @@ def cleanup() {
             |</html>
             '''.stripMargin()
     }
-
 }