Major refactoring and introduction of Task model.
This commit is contained in:
parent
107f394b82
commit
92c810870c
@ -8,6 +8,7 @@ import com.jessebrault.ssg.part.PartType
|
||||
import com.jessebrault.ssg.specialpage.GspSpecialPageRenderer
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageFileSpecialPagesProvider
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageType
|
||||
import com.jessebrault.ssg.task.TaskExecutorContext
|
||||
import com.jessebrault.ssg.template.GspTemplateRenderer
|
||||
import com.jessebrault.ssg.template.TemplateFileTemplatesProvider
|
||||
import com.jessebrault.ssg.template.TemplateType
|
||||
@ -80,16 +81,28 @@ abstract class AbstractBuildCommand extends AbstractSubCommand {
|
||||
// Do each build
|
||||
this.builds.each {
|
||||
def result = this.ssg.generate(it)
|
||||
if (result.v1.size() > 0) {
|
||||
if (result.hasDiagnostics()) {
|
||||
hadDiagnostics = true
|
||||
result.v1.each {
|
||||
result.diagnostics.each {
|
||||
logger.error(it.message)
|
||||
}
|
||||
} else {
|
||||
result.v2.each { Output output ->
|
||||
def target = new File(it.outDir, output.meta.targetPath)
|
||||
target.createParentDirectories()
|
||||
target.write(output.content)
|
||||
def tasks = result.get()
|
||||
Collection<Diagnostic> executionDiagnostics = []
|
||||
def context = new TaskExecutorContext(
|
||||
it,
|
||||
tasks,
|
||||
null,
|
||||
{ Collection<Diagnostic> diagnostics ->
|
||||
executionDiagnostics.addAll(diagnostics)
|
||||
}
|
||||
)
|
||||
result.get().each { it.execute(context) }
|
||||
if (!executionDiagnostics.isEmpty()) {
|
||||
hadDiagnostics = true
|
||||
executionDiagnostics.each {
|
||||
logger.error(it.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
lib/src/main/groovy/com/jessebrault/ssg/Result.groovy
Normal file
28
lib/src/main/groovy/com/jessebrault/ssg/Result.groovy
Normal file
@ -0,0 +1,28 @@
|
||||
package com.jessebrault.ssg
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false, includeFields = true)
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class Result<T> {
|
||||
|
||||
final Collection<Diagnostic> diagnostics
|
||||
private final T t
|
||||
|
||||
boolean hasDiagnostics() {
|
||||
!this.diagnostics.isEmpty()
|
||||
}
|
||||
|
||||
T get() {
|
||||
this.t
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"Result(diagnostics: ${ this.diagnostics }, t: ${ this.t })"
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +1,15 @@
|
||||
package com.jessebrault.ssg
|
||||
|
||||
import com.jessebrault.ssg.renderer.RenderContext
|
||||
import com.jessebrault.ssg.specialpage.SpecialPage
|
||||
import com.jessebrault.ssg.task.Output
|
||||
import com.jessebrault.ssg.task.OutputMeta
|
||||
import com.jessebrault.ssg.task.OutputMetaMap
|
||||
import com.jessebrault.ssg.text.FrontMatter
|
||||
import com.jessebrault.ssg.text.Text
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import com.jessebrault.ssg.task.SpecialPageToHtmlFileTaskFactory
|
||||
import com.jessebrault.ssg.task.TaskContainer
|
||||
import com.jessebrault.ssg.task.TextToHtmlFileTaskFactory
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.Marker
|
||||
import org.slf4j.MarkerFactory
|
||||
|
||||
import static com.jessebrault.ssg.util.ExtensionsUtil.stripExtension
|
||||
|
||||
@TupleConstructor(includeFields = true)
|
||||
@NullCheck
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
class SimpleStaticSiteGenerator implements StaticSiteGenerator {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SimpleStaticSiteGenerator)
|
||||
@ -27,128 +17,25 @@ class SimpleStaticSiteGenerator implements StaticSiteGenerator {
|
||||
private static final Marker exit = MarkerFactory.getMarker('EXIT')
|
||||
|
||||
@Override
|
||||
Tuple2<Collection<Diagnostic>, Collection<Output>> generate(Build build) {
|
||||
Result<TaskContainer> generate(Build build) {
|
||||
logger.trace(enter, 'build: {}', build)
|
||||
logger.info('processing build with name: {}', build.name)
|
||||
|
||||
def config = build.config
|
||||
def siteSpec = build.siteSpec
|
||||
def tasks = new TaskContainer()
|
||||
def diagnostics = []
|
||||
|
||||
// Get all texts, templates, parts, and specialPages
|
||||
def texts = config.textProviders.collectMany { it.provide() }
|
||||
def templates = config.templatesProviders.collectMany { it.provide() }
|
||||
def parts = config.partsProviders.collectMany { it.provide() }
|
||||
def specialPages = config.specialPagesProviders.collectMany { it.provide() }
|
||||
def textToHtmlFactory = new TextToHtmlFileTaskFactory()
|
||||
def textsResult = textToHtmlFactory.getTasks(build)
|
||||
tasks.addAll(textsResult.get())
|
||||
diagnostics.addAll(textsResult.diagnostics)
|
||||
|
||||
logger.debug('\n\ttexts: {}\n\ttemplates: {}\n\tparts: {}\n\tspecialPages: {}', texts, templates, parts, specialPages)
|
||||
def specialPageToHtmlFactory = new SpecialPageToHtmlFileTaskFactory()
|
||||
def specialPagesResult = specialPageToHtmlFactory.getTasks(build)
|
||||
tasks.addAll(specialPagesResult.get())
|
||||
diagnostics.addAll(specialPagesResult.diagnostics)
|
||||
|
||||
def globals = build.globals
|
||||
Collection<Diagnostic> diagnostics = []
|
||||
Collection<Output> generatedPages = []
|
||||
|
||||
Map<Text, OutputMeta> textOutputTasks = texts.collectEntries {
|
||||
[(it): new OutputMeta(it.path, stripExtension(it.path) + '.html')]
|
||||
}
|
||||
Map<SpecialPage, OutputMeta> specialPageOutputTasks = specialPages.collectEntries {
|
||||
[(it): new OutputMeta(it.path, stripExtension(it.path) + '.html')]
|
||||
}
|
||||
|
||||
def textOutputMetas = textOutputTasks.values() as ArrayList
|
||||
def specialPageOutputMetas = specialPageOutputTasks.values() as ArrayList
|
||||
def outputMetaMap = new OutputMetaMap([*textOutputMetas, *specialPageOutputMetas])
|
||||
|
||||
// Generate pages from each text, but only those that have a 'template' frontMatter field with a valid value
|
||||
textOutputTasks.each { text, outputMeta ->
|
||||
logger.trace(enter, 'text: {}, outputMeta: {}', text, outputMeta)
|
||||
logger.info('processing text: {}', text.path)
|
||||
|
||||
// Extract frontMatter from text
|
||||
def frontMatterResult = text.type.frontMatterGetter.get(text)
|
||||
FrontMatter frontMatter
|
||||
if (frontMatterResult.v1.size() > 0) {
|
||||
logger.debug('diagnostics for getting frontMatter for {}: {}', text.path, frontMatterResult.v1)
|
||||
diagnostics.addAll(frontMatterResult.v1)
|
||||
logger.trace(exit, '')
|
||||
return
|
||||
} else {
|
||||
frontMatter = frontMatterResult.v2
|
||||
logger.debug('frontMatter: {}', frontMatter)
|
||||
}
|
||||
|
||||
// Find the appropriate template from the frontMatter
|
||||
def desiredTemplate = frontMatter.find('template')
|
||||
if (desiredTemplate.isEmpty()) {
|
||||
logger.info('{} has no \'template\' key in its frontMatter; skipping generation', text)
|
||||
return
|
||||
}
|
||||
def template = templates.find { it.path == desiredTemplate.get() }
|
||||
if (template == null) {
|
||||
diagnostics << new Diagnostic('in textFile' + text.path + ' frontMatter.template references an unknown template: ' + desiredTemplate, null)
|
||||
logger.trace(exit, '')
|
||||
return
|
||||
}
|
||||
logger.debug('found template: {}', template)
|
||||
|
||||
// Render the template using the result of rendering the text earlier
|
||||
def templateRenderResult = template.type.renderer.render(
|
||||
template,
|
||||
text,
|
||||
new RenderContext(
|
||||
config,
|
||||
siteSpec,
|
||||
globals,
|
||||
texts,
|
||||
parts,
|
||||
outputMeta.sourcePath,
|
||||
outputMeta.targetPath
|
||||
)
|
||||
)
|
||||
String renderedTemplate
|
||||
if (templateRenderResult.v1.size() > 0) {
|
||||
diagnostics.addAll(templateRenderResult.v1)
|
||||
logger.trace(exit, '')
|
||||
return
|
||||
} else {
|
||||
renderedTemplate = templateRenderResult.v2
|
||||
}
|
||||
|
||||
// Create a GeneratedPage
|
||||
generatedPages << new Output(outputMeta, renderedTemplate)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate special pages
|
||||
specialPageOutputTasks.each { specialPage, outputMeta ->
|
||||
logger.info('processing specialPage: {}', specialPage.path)
|
||||
|
||||
def specialPageRenderResult = specialPage.type.renderer.render(
|
||||
specialPage,
|
||||
new RenderContext(
|
||||
config,
|
||||
siteSpec,
|
||||
globals,
|
||||
texts,
|
||||
parts,
|
||||
outputMeta.sourcePath,
|
||||
outputMeta.targetPath
|
||||
)
|
||||
)
|
||||
String renderedSpecialPage
|
||||
if (specialPageRenderResult.v1.size() > 0) {
|
||||
diagnostics.addAll(specialPageRenderResult.v1)
|
||||
logger.trace(exit, '')
|
||||
return
|
||||
} else {
|
||||
renderedSpecialPage = specialPageRenderResult.v2
|
||||
}
|
||||
|
||||
// Create a GeneratedPage
|
||||
generatedPages << new Output(outputMeta, renderedSpecialPage)
|
||||
return
|
||||
}
|
||||
|
||||
logger.trace(exit, '\n\tdiagnostics: {}\n\tgeneratedPages: {}', diagnostics, generatedPages)
|
||||
new Tuple2<>(diagnostics, generatedPages)
|
||||
logger.trace(exit, '\n\tdiagnostics: {}\n\ttasks: {}', diagnostics, tasks)
|
||||
new Result<>(diagnostics, tasks)
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.jessebrault.ssg
|
||||
|
||||
import com.jessebrault.ssg.task.Output
|
||||
import com.jessebrault.ssg.task.TaskContainer
|
||||
|
||||
interface StaticSiteGenerator {
|
||||
Tuple2<Collection<Diagnostic>, Collection<Output>> generate(Build build)
|
||||
Result<TaskContainer> generate(Build build)
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ final class StandardDslMap {
|
||||
it.siteSpec = context.siteSpec
|
||||
it.sourcePath = context.sourcePath
|
||||
it.targetPath = context.targetPath
|
||||
it.tasks = context.tasks
|
||||
it.text = b.text ? new EmbeddableText(
|
||||
b.text,
|
||||
context.globals,
|
||||
|
@ -3,6 +3,8 @@ package com.jessebrault.ssg.renderer
|
||||
import com.jessebrault.ssg.Config
|
||||
import com.jessebrault.ssg.SiteSpec
|
||||
import com.jessebrault.ssg.part.Part
|
||||
import com.jessebrault.ssg.task.Task
|
||||
import com.jessebrault.ssg.task.TaskContainer
|
||||
import com.jessebrault.ssg.text.Text
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
@ -19,4 +21,6 @@ final class RenderContext {
|
||||
final Collection<Part> parts
|
||||
final String sourcePath
|
||||
final String targetPath
|
||||
final TaskContainer tasks
|
||||
final Set<Class<? extends Task>> taskTypes
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
package com.jessebrault.ssg.specialpage
|
||||
|
||||
import com.jessebrault.ssg.task.Input
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
class SpecialPage implements Input {
|
||||
final class SpecialPage {
|
||||
|
||||
String text
|
||||
String path
|
||||
SpecialPageType type
|
||||
final String text
|
||||
final String path
|
||||
final SpecialPageType type
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
|
||||
@NullCheck
|
||||
@EqualsAndHashCode
|
||||
abstract class AbstractTask<T extends Task> implements Task {
|
||||
|
||||
final TaskType<T> type
|
||||
final String name
|
||||
|
||||
AbstractTask(TaskType<T> type, String name) {
|
||||
this.type = type
|
||||
this.name = name
|
||||
}
|
||||
|
||||
protected abstract T getThis()
|
||||
|
||||
@Override
|
||||
void execute(TaskExecutorContext context) {
|
||||
// I am guessing that if we put this.getThis(), it will think the runtime type is AbstractTask? Not sure.
|
||||
this.type.executor.execute(getThis(), context)
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"AbstractTask(name: ${ this.name }, type: ${ this.type })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface FileInput extends Input {
|
||||
File getFile()
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface FileOutput extends Output {
|
||||
File getFile()
|
||||
String getContent()
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false, includeFields = true)
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class HtmlFileOutput {
|
||||
|
||||
final File file
|
||||
final String htmlPath
|
||||
|
||||
private final Closure<String> contentClosure
|
||||
|
||||
String getContent(TaskContainer tasks, TaskTypeContainer taskTypes, Closure onDiagnostics) {
|
||||
this.contentClosure(tasks, taskTypes, onDiagnostics)
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"HtmlFileOutput(file: ${ this.file }, htmlPath: ${ this.htmlPath })"
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface Input {
|
||||
String getPath()
|
||||
String getName()
|
||||
}
|
@ -1,20 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck
|
||||
@EqualsAndHashCode
|
||||
final class Output {
|
||||
|
||||
final OutputMeta meta
|
||||
final String content
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"Output(meta: ${ this.meta })"
|
||||
}
|
||||
|
||||
interface Output {
|
||||
String getName()
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
final class OutputMetaMap {
|
||||
|
||||
@Delegate
|
||||
private final Map<String, OutputMeta> map = [:]
|
||||
|
||||
OutputMetaMap(Collection<OutputMeta> outputMetas) {
|
||||
outputMetas.each {
|
||||
this.put(it.sourcePath, it)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"OutputMetaMap(map: ${ this.map })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.specialpage.SpecialPage
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
|
||||
@NullCheck
|
||||
@EqualsAndHashCode
|
||||
final class SpecialPageToHtmlFileTask extends AbstractTask<SpecialPageToHtmlFileTask> {
|
||||
|
||||
private static final class SpecialPageToHtmlFileTaskExecutor implements TaskExecutor<SpecialPageToHtmlFileTask> {
|
||||
|
||||
@Override
|
||||
void execute(SpecialPageToHtmlFileTask task, TaskExecutorContext context) {
|
||||
task.output.file.write(task.output.getContent(
|
||||
context.allTasks, context.allTypes, context.onDiagnostics
|
||||
))
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
'SpecialPageToHtmlFileTaskExecutor()'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final TaskType<SpecialPageToHtmlFileTask> type = new TaskType<>(
|
||||
'specialPageToHtmlFile', new SpecialPageToHtmlFileTaskExecutor()
|
||||
)
|
||||
|
||||
final SpecialPage input
|
||||
final HtmlFileOutput output
|
||||
|
||||
SpecialPageToHtmlFileTask(String name, SpecialPage input, HtmlFileOutput output) {
|
||||
super(type, name)
|
||||
this.input = input
|
||||
this.output = output
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpecialPageToHtmlFileTask getThis() {
|
||||
this
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"SpecialPageToHtmlFileTask(input: ${ this.input }, output: ${ this.output }, super: ${ super })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.Build
|
||||
import com.jessebrault.ssg.Result
|
||||
import com.jessebrault.ssg.renderer.RenderContext
|
||||
import com.jessebrault.ssg.util.ExtensionsUtil
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.Marker
|
||||
import org.slf4j.MarkerFactory
|
||||
|
||||
final class SpecialPageToHtmlFileTaskFactory implements TaskFactory<SpecialPageToHtmlFileTask> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpecialPageToHtmlFileTaskFactory)
|
||||
private static final Marker enter = MarkerFactory.getMarker('ENTER')
|
||||
private static final Marker exit = MarkerFactory.getMarker('EXIT')
|
||||
|
||||
@Override
|
||||
Result<TaskCollection<SpecialPageToHtmlFileTask>> getTasks(Build build) {
|
||||
logger.trace(enter, 'build: {}', build)
|
||||
logger.info('processing build with name {} for SpecialPageToHtmlFileTasks', build.name)
|
||||
|
||||
def config = build.config
|
||||
def siteSpec = build.siteSpec
|
||||
def globals = build.globals
|
||||
|
||||
def specialPages = config.specialPagesProviders.collectMany { it.provide() }
|
||||
def templates = config.templatesProviders.collectMany { it.provide() }
|
||||
def parts = config.partsProviders.collectMany { it.provide() }
|
||||
def texts = config.textProviders.collectMany { it.provide() }
|
||||
|
||||
logger.debug('\n\tspecialPages: {}\n\ttemplates: {}\n\tparts: {}', specialPages, templates, parts)
|
||||
|
||||
def tasks = new TaskCollection<SpecialPageToHtmlFileTask>(specialPages.findResults {
|
||||
logger.trace(enter, 'specialPage: {}', it)
|
||||
logger.info('processing specialPage with path: {}', it.path)
|
||||
|
||||
def htmlPath = ExtensionsUtil.stripExtension(it.path) + '.html'
|
||||
|
||||
def renderSpecialPage = { TaskContainer tasks, TaskTypeContainer taskTypes, Closure<Void> onDiagnostics ->
|
||||
def renderResult = it.type.renderer.render(
|
||||
it,
|
||||
new RenderContext(
|
||||
config,
|
||||
siteSpec,
|
||||
globals,
|
||||
texts,
|
||||
parts,
|
||||
it.path,
|
||||
htmlPath,
|
||||
tasks,
|
||||
taskTypes
|
||||
)
|
||||
)
|
||||
|
||||
if (!renderResult.v1.isEmpty()) {
|
||||
onDiagnostics(renderResult.v1)
|
||||
''
|
||||
} else {
|
||||
renderResult.v2
|
||||
}
|
||||
}
|
||||
|
||||
def result = new SpecialPageToHtmlFileTask(
|
||||
"specialPageToHtmlFileTask:${ it.path }:${ htmlPath }",
|
||||
it,
|
||||
new HtmlFileOutput(
|
||||
new File(build.outDir, htmlPath),
|
||||
htmlPath,
|
||||
renderSpecialPage
|
||||
)
|
||||
)
|
||||
logger.trace(exit, 'result: {}', result)
|
||||
result
|
||||
})
|
||||
|
||||
def result = new Result<>([], tasks)
|
||||
logger.trace(exit, 'result: {}', result)
|
||||
result
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface Task {
|
||||
Output getOutput()
|
||||
OutputMeta getOutputMeta()
|
||||
String getName()
|
||||
void execute(TaskExecutorContext context)
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import static java.util.Objects.requireNonNull
|
||||
|
||||
class TaskCollection<T extends Task> {
|
||||
|
||||
@Delegate
|
||||
private final Collection<T> tasks = new ArrayList<T>()
|
||||
|
||||
TaskCollection(Collection<? extends T> tasks = null) {
|
||||
if (tasks != null) {
|
||||
this.tasks.addAll(requireNonNull(tasks))
|
||||
}
|
||||
}
|
||||
|
||||
def <U extends T> TaskCollection<U> findAllByType(
|
||||
Class<U> taskClass
|
||||
) {
|
||||
new TaskCollection<>(this.tasks.findResults {
|
||||
taskClass.isAssignableFrom(it.class) ? taskClass.cast(it) : null
|
||||
})
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
final class TaskContainer extends TaskCollection<Task> {
|
||||
|
||||
TaskContainer(Collection<? extends Task> tasks = null) {
|
||||
super(tasks)
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.Config
|
||||
import com.jessebrault.ssg.SiteSpec
|
||||
import groovy.transform.TupleConstructor
|
||||
import groovy.transform.builder.Builder
|
||||
|
||||
@Builder
|
||||
@TupleConstructor(defaults = false)
|
||||
final class TaskContext {
|
||||
|
||||
final Config config
|
||||
final SiteSpec siteSpec
|
||||
final Collection<OutputMeta> outputMetas
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"TaskContext(config: ${ this.config }, siteSpec: ${ this.siteSpec }, outputMetas: ${ this.outputMetas })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface TaskExecutor<T extends Task> {
|
||||
void execute(T task, TaskExecutorContext context)
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.Build
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class TaskExecutorContext {
|
||||
|
||||
final Build build
|
||||
final TaskContainer allTasks
|
||||
final TaskTypeContainer allTypes
|
||||
final Closure onDiagnostics
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"TaskExecutorContext(build: ${ this.build }, allTasks: ${ this.allTasks }, allTypes: ${ this.allTypes })"
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import org.jetbrains.annotations.Nullable
|
||||
import com.jessebrault.ssg.Build
|
||||
import com.jessebrault.ssg.Result
|
||||
|
||||
interface TaskFactory {
|
||||
@Nullable Task getTask(Input input, TaskContext context)
|
||||
interface TaskFactory<T extends Task> {
|
||||
Result<TaskCollection<T>> getTasks(Build build)
|
||||
}
|
@ -5,16 +5,16 @@ import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class OutputMeta {
|
||||
final class TaskType<T extends Task> {
|
||||
|
||||
final String sourcePath
|
||||
final String targetPath
|
||||
final String name
|
||||
final TaskExecutor<T> executor
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"OutputMeta(sourcePath: ${ sourcePath }, targetPath: ${ targetPath })"
|
||||
"TaskType(${ this.name }, ${ this.executor })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
final class TaskTypeContainer {
|
||||
|
||||
private static final Pattern taskTypeNamePattern = ~/(.*)Task/
|
||||
|
||||
@Delegate
|
||||
private final Set<Class<? extends Task>> taskTypes = []
|
||||
|
||||
TaskTypeContainer(Collection<Class<? extends Task>> taskTypes = null) {
|
||||
if (taskTypes) {
|
||||
this.taskTypes.addAll(taskTypes)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends Task> getProperty(String propertyName) {
|
||||
def result = this.taskTypes.find {
|
||||
def m = taskTypeNamePattern.matcher(it.simpleName)
|
||||
if (m.matches()) {
|
||||
def withoutTaskEnd = m.group(1)
|
||||
def uncapitalized = withoutTaskEnd.uncapitalize()
|
||||
return propertyName == uncapitalized
|
||||
} else {
|
||||
throw new IllegalStateException("invalid task type name: ${ it.simpleName }")
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
throw new IllegalStateException("no such taskType: ${ propertyName }")
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.text.Text
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
final class TextInput implements Input {
|
||||
final String name
|
||||
final Text text
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.text.Text
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
|
||||
@NullCheck
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
final class TextToHtmlFileTask extends AbstractTask<TextToHtmlFileTask> {
|
||||
|
||||
private static final class TextToHtmlFileTaskExecutor implements TaskExecutor<TextToHtmlFileTask> {
|
||||
|
||||
@Override
|
||||
void execute(TextToHtmlFileTask task, TaskExecutorContext context) {
|
||||
task.output.file.write(task.output.getContent(
|
||||
context.allTasks, context.allTypes, context.onDiagnostics
|
||||
))
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
'TextToHtmlFileTaskExecutor()'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final TaskType<TextToHtmlFileTask> type = new TaskType<>(
|
||||
'textToHtmlFile', new TextToHtmlFileTaskExecutor()
|
||||
)
|
||||
|
||||
final Text input
|
||||
final HtmlFileOutput output
|
||||
|
||||
TextToHtmlFileTask(String name, Text input, HtmlFileOutput output) {
|
||||
super(type, name)
|
||||
this.input = input
|
||||
this.output = output
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TextToHtmlFileTask getThis() {
|
||||
this
|
||||
}
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
"TextToHtmlFileTask(input: ${ this.input }, output: ${ this.output }, super: ${ super })"
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import com.jessebrault.ssg.Build
|
||||
import com.jessebrault.ssg.Diagnostic
|
||||
import com.jessebrault.ssg.Result
|
||||
import com.jessebrault.ssg.renderer.RenderContext
|
||||
import com.jessebrault.ssg.text.FrontMatter
|
||||
import com.jessebrault.ssg.util.ExtensionsUtil
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.Marker
|
||||
import org.slf4j.MarkerFactory
|
||||
|
||||
final class TextToHtmlFileTaskFactory implements TaskFactory<TextToHtmlFileTask> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TextToHtmlFileTaskFactory)
|
||||
private static final Marker enter = MarkerFactory.getMarker('ENTER')
|
||||
private static final Marker exit = MarkerFactory.getMarker('EXIT')
|
||||
|
||||
@Override
|
||||
Result<TaskCollection<TextToHtmlFileTask>> getTasks(Build build) {
|
||||
logger.trace(enter, 'build: {}', build)
|
||||
logger.info('getting TextToHtmlFileTasks for build with name: {}', build.name)
|
||||
|
||||
def config = build.config
|
||||
def siteSpec = build.siteSpec
|
||||
def globals = build.globals
|
||||
def diagnostics = []
|
||||
|
||||
// Get all texts, templates, parts, and specialPages
|
||||
def texts = config.textProviders.collectMany { it.provide() }
|
||||
def templates = config.templatesProviders.collectMany { it.provide() }
|
||||
def parts = config.partsProviders.collectMany { it.provide() }
|
||||
|
||||
logger.debug('\n\ttexts: {}\n\ttemplates: {}\n\tparts: {}', texts, templates, parts)
|
||||
|
||||
def tasks = new TaskCollection<TextToHtmlFileTask>(texts.findResults {
|
||||
logger.trace(enter, 'text: {}', it)
|
||||
logger.info('processing text with path: {}', it.path)
|
||||
|
||||
def frontMatterResult = it.type.frontMatterGetter.get(it)
|
||||
FrontMatter frontMatter
|
||||
if (!frontMatterResult.v1.isEmpty()) {
|
||||
diagnostics.addAll(frontMatterResult.v1)
|
||||
logger.trace(exit, 'result: {}', null)
|
||||
return null
|
||||
} else {
|
||||
frontMatter = frontMatterResult.v2
|
||||
logger.debug('frontMatter: {}', frontMatter)
|
||||
}
|
||||
|
||||
def desiredTemplate = frontMatter.find('template')
|
||||
if (desiredTemplate.isEmpty()) {
|
||||
logger.info('text with path {} has no \'template\' key in its frontMatter; skipping', it.path)
|
||||
logger.trace(exit, 'result: {}', null)
|
||||
return null
|
||||
}
|
||||
def template = templates.find { it.path == desiredTemplate.get() }
|
||||
if (template == null) {
|
||||
diagnostics << new Diagnostic("in text with path ${ it.path }, frontMatter.template refers to an unknown template: ${ desiredTemplate.get() }")
|
||||
logger.trace(exit, 'result: {}', null)
|
||||
return null
|
||||
}
|
||||
logger.debug('found template: {}', template)
|
||||
|
||||
def htmlPath = ExtensionsUtil.stripExtension(it.path) + '.html'
|
||||
|
||||
def renderTemplate = { TaskContainer tasks, TaskTypeContainer taskTypes, Closure<Void> onDiagnostics ->
|
||||
def templateRenderResult = template.type.renderer.render(
|
||||
template,
|
||||
it,
|
||||
new RenderContext(
|
||||
config,
|
||||
siteSpec,
|
||||
globals,
|
||||
texts,
|
||||
parts,
|
||||
it.path,
|
||||
htmlPath,
|
||||
tasks,
|
||||
taskTypes
|
||||
)
|
||||
)
|
||||
|
||||
if (!templateRenderResult.v1.isEmpty()) {
|
||||
onDiagnostics(templateRenderResult.v1)
|
||||
''
|
||||
} else {
|
||||
templateRenderResult.v2
|
||||
}
|
||||
}
|
||||
|
||||
def result = new TextToHtmlFileTask(
|
||||
"textToHtmlFileTask:${ it.path }:${ htmlPath }",
|
||||
it,
|
||||
new HtmlFileOutput(
|
||||
new File(build.outDir, htmlPath),
|
||||
htmlPath,
|
||||
renderTemplate
|
||||
)
|
||||
)
|
||||
|
||||
logger.trace(exit, 'result: {}', result)
|
||||
result
|
||||
})
|
||||
|
||||
def result = new Result<>(diagnostics, tasks)
|
||||
logger.trace(exit, 'result: {}', result)
|
||||
result
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface WithInput<I extends Input> {
|
||||
I getInput()
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
interface WithOutput<O extends Output> {
|
||||
O getOutput()
|
||||
}
|
@ -1,18 +1,17 @@
|
||||
package com.jessebrault.ssg.text
|
||||
|
||||
import com.jessebrault.ssg.task.Input
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
import groovy.transform.TupleConstructor
|
||||
|
||||
@TupleConstructor(defaults = false)
|
||||
@NullCheck
|
||||
@NullCheck(includeGenerated = true)
|
||||
@EqualsAndHashCode
|
||||
class Text implements Input {
|
||||
final class Text {
|
||||
|
||||
String text
|
||||
String path
|
||||
TextType type
|
||||
final String text
|
||||
final String path
|
||||
final TextType type
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
|
@ -6,6 +6,10 @@ import com.jessebrault.ssg.part.PartType
|
||||
import com.jessebrault.ssg.specialpage.GspSpecialPageRenderer
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageFileSpecialPagesProvider
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageType
|
||||
import com.jessebrault.ssg.task.SpecialPageToHtmlFileTask
|
||||
import com.jessebrault.ssg.task.Task
|
||||
import com.jessebrault.ssg.task.TaskTypeContainer
|
||||
import com.jessebrault.ssg.task.TextToHtmlFileTask
|
||||
import com.jessebrault.ssg.template.GspTemplateRenderer
|
||||
import com.jessebrault.ssg.template.TemplateFileTemplatesProvider
|
||||
import com.jessebrault.ssg.template.TemplateType
|
||||
@ -18,6 +22,7 @@ import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
import static com.jessebrault.ssg.testutil.DiagnosticsUtil.assertEmptyDiagnostics
|
||||
import static com.jessebrault.ssg.testutil.DiagnosticsUtil.getDiagnosticsMessageSupplier
|
||||
import static org.junit.jupiter.api.Assertions.*
|
||||
|
||||
class SimpleStaticSiteGeneratorIntegrationTests {
|
||||
@ -68,11 +73,15 @@ class SimpleStaticSiteGeneratorIntegrationTests {
|
||||
def result = this.ssg.generate(this.build)
|
||||
|
||||
assertEmptyDiagnostics(result)
|
||||
assertTrue(result.v2.size() == 1)
|
||||
def tasks = result.get()
|
||||
assertTrue(tasks.size() == 1)
|
||||
|
||||
def p0 = result.v2[0]
|
||||
assertEquals('test.html', p0.meta.targetPath)
|
||||
assertEquals('<p><strong>Hello, World!</strong></p>\n', p0.content)
|
||||
def t0 = tasks.findAllByType(TextToHtmlFileTask)[0]
|
||||
assertEquals('test.html', t0.output.htmlPath)
|
||||
def contentResult = t0.output.getContent(tasks, new TaskTypeContainer([TextToHtmlFileTask])) { Collection<Diagnostic> diagnostics ->
|
||||
fail(getDiagnosticsMessageSupplier(diagnostics))
|
||||
}
|
||||
assertEquals('<p><strong>Hello, World!</strong></p>\n', contentResult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -88,11 +97,18 @@ class SimpleStaticSiteGeneratorIntegrationTests {
|
||||
def result = this.ssg.generate(this.build)
|
||||
|
||||
assertEmptyDiagnostics(result)
|
||||
assertTrue(result.v2.size() == 1)
|
||||
def tasks = result.get()
|
||||
assertTrue(tasks.size() == 1)
|
||||
|
||||
def p0 = result.v2[0]
|
||||
assertEquals('nested/nested.html', p0.meta.targetPath)
|
||||
assertEquals('<p><strong>Hello, World!</strong></p>\n', p0.content)
|
||||
def t0 = tasks.findAllByType(TextToHtmlFileTask)[0]
|
||||
assertEquals('nested/nested.html', t0.output.htmlPath)
|
||||
def contentResult = t0.output.getContent(
|
||||
tasks,
|
||||
new TaskTypeContainer([TextToHtmlFileTask])
|
||||
) { Collection<Diagnostic> diagnostics ->
|
||||
fail(getDiagnosticsMessageSupplier(diagnostics))
|
||||
}
|
||||
assertEquals('<p><strong>Hello, World!</strong></p>\n', contentResult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -105,15 +121,28 @@ class SimpleStaticSiteGeneratorIntegrationTests {
|
||||
def result = this.ssg.generate(this.build)
|
||||
|
||||
assertEmptyDiagnostics(result)
|
||||
assertEquals(2, result.v2.size())
|
||||
def tasks = result.get()
|
||||
assertEquals(2, tasks.size())
|
||||
|
||||
def testPage = result.v2.find { it.meta.targetPath == 'test.html' }
|
||||
assertNotNull(testPage)
|
||||
assertEquals('2', testPage.content)
|
||||
def taskTypes = new TaskTypeContainer([TextToHtmlFileTask, SpecialPageToHtmlFileTask])
|
||||
|
||||
def specialPage = result.v2.find { it.meta.targetPath == 'special.html' }
|
||||
assertNotNull(specialPage)
|
||||
assertEquals('<p>Hello, World!</p>\n', specialPage.content)
|
||||
def testPageTask = tasks.findAllByType(TextToHtmlFileTask).find {
|
||||
it.output.htmlPath == 'test.html'
|
||||
}
|
||||
assertNotNull(testPageTask)
|
||||
def testPageContent = testPageTask.output.getContent(tasks, taskTypes) { Collection<Diagnostic> diagnostics ->
|
||||
fail(getDiagnosticsMessageSupplier(diagnostics))
|
||||
}
|
||||
assertEquals('2', testPageContent)
|
||||
|
||||
def specialPageTask = tasks.findAllByType(SpecialPageToHtmlFileTask).find {
|
||||
it.output.htmlPath == 'special.html'
|
||||
}
|
||||
assertNotNull(specialPageTask)
|
||||
def specialPageContent = specialPageTask.output.getContent(tasks, taskTypes) { Collection<Diagnostic> diagnostics ->
|
||||
fail(getDiagnosticsMessageSupplier(diagnostics))
|
||||
}
|
||||
assertEquals('<p>Hello, World!</p>\n', specialPageContent)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -121,7 +150,7 @@ class SimpleStaticSiteGeneratorIntegrationTests {
|
||||
new File(this.textsDir, 'test.md').write('Hello, World!')
|
||||
def result = this.ssg.generate(this.build)
|
||||
assertEmptyDiagnostics(result)
|
||||
assertEquals(0, result.v2.size())
|
||||
assertEquals(0, result.get().size())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.jessebrault.ssg.text
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
import static com.jessebrault.ssg.text.TextMocks.renderableText
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals
|
||||
|
||||
class ExcerptGetterTests {
|
||||
@ -10,7 +11,7 @@ class ExcerptGetterTests {
|
||||
|
||||
@Test
|
||||
void takesAllIfTextLessThanLimit() {
|
||||
def text = new Text('One Two Three Four Five', null, null)
|
||||
def text = renderableText('One Two Three Four Five')
|
||||
def result = this.excerptGetter.getExcerpt(text, 10)
|
||||
assertEquals(0, result.v1.size())
|
||||
assertEquals('One Two Three Four Five', result.v2)
|
||||
@ -18,7 +19,7 @@ class ExcerptGetterTests {
|
||||
|
||||
@Test
|
||||
void takesTheLimit() {
|
||||
def text = new Text('One Two Three Four Five', null, null)
|
||||
def text = renderableText('One Two Three Four Five')
|
||||
def result = this.excerptGetter.getExcerpt(text, 2)
|
||||
assertEquals(0, result.v1.size())
|
||||
assertEquals('One Two', result.v2)
|
||||
@ -26,7 +27,7 @@ class ExcerptGetterTests {
|
||||
|
||||
@Test
|
||||
void worksWithHeading() {
|
||||
def text = new Text('# Heading\nOne Two Three', null, null)
|
||||
def text = renderableText('# Heading\nOne Two Three')
|
||||
def result = this.excerptGetter.getExcerpt(text, 1)
|
||||
assertEquals(0, result.v1.size())
|
||||
assertEquals('Heading', result.v2)
|
||||
@ -34,7 +35,7 @@ class ExcerptGetterTests {
|
||||
|
||||
@Test
|
||||
void worksWithFrontMatter() {
|
||||
def text = new Text('---\ntest: hello\n---\nOne Two Three', null, null)
|
||||
def text = renderableText('---\ntest: hello\n---\nOne Two Three')
|
||||
def result = this.excerptGetter.getExcerpt(text, 1)
|
||||
assertEquals(0, result.v1.size())
|
||||
assertEquals('One', result.v2)
|
||||
|
@ -8,6 +8,10 @@ import com.jessebrault.ssg.part.PartRenderer
|
||||
import com.jessebrault.ssg.part.PartType
|
||||
import com.jessebrault.ssg.renderer.RenderContext
|
||||
import com.jessebrault.ssg.tagbuilder.TagBuilder
|
||||
import com.jessebrault.ssg.task.HtmlFileOutput
|
||||
import com.jessebrault.ssg.task.TaskContainer
|
||||
import com.jessebrault.ssg.task.TaskTypeContainer
|
||||
import com.jessebrault.ssg.task.TextToHtmlFileTask
|
||||
import com.jessebrault.ssg.text.EmbeddableTextsCollection
|
||||
import com.jessebrault.ssg.url.UrlBuilder
|
||||
import org.junit.jupiter.api.Test
|
||||
@ -18,8 +22,11 @@ import org.mockito.junit.jupiter.MockitoExtension
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
import static com.jessebrault.ssg.task.SpecialPageToHtmlFileTaskMocks.blankSpecialPageToHtmlFileTask
|
||||
import static com.jessebrault.ssg.task.TextToHtmlFileTaskMocks.blankTextToHtmlFileTask
|
||||
import static com.jessebrault.ssg.testutil.DiagnosticsUtil.assertEmptyDiagnostics
|
||||
import static com.jessebrault.ssg.testutil.RenderContextUtil.getRenderContext
|
||||
import static com.jessebrault.ssg.text.TextMocks.blankText
|
||||
import static com.jessebrault.ssg.text.TextMocks.renderableTextWithPath
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals
|
||||
import static org.junit.jupiter.api.Assertions.fail
|
||||
@ -146,6 +153,48 @@ interface StandardDslConsumerTests {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
default void tasksAvailable() {
|
||||
this.doDslAssertionTest("<% assert tasks != null && tasks instanceof ${ TaskContainer.name } %>")
|
||||
}
|
||||
|
||||
@Test
|
||||
default void tasksFind() {
|
||||
def task = new TextToHtmlFileTask(
|
||||
'testTask',
|
||||
blankText(),
|
||||
new HtmlFileOutput(
|
||||
new File('test.html'),
|
||||
'test.html',
|
||||
{ '' }
|
||||
)
|
||||
)
|
||||
this.doDslRenderTest(
|
||||
'test.html',
|
||||
'<%= tasks.find { it.name == "testTask" }.output.htmlPath %>',
|
||||
getRenderContext(tasks: new TaskContainer([task]))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
default void taskTypesAvailable() {
|
||||
this.doDslAssertionTest(
|
||||
"<% assert taskTypes != null && taskTypes instanceof ${ TaskTypeContainer.name } %>"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
default void taskFindAllByType() {
|
||||
def t0 = blankTextToHtmlFileTask()
|
||||
def t1 = blankSpecialPageToHtmlFileTask()
|
||||
this.doDslAssertionTest(
|
||||
'<% assert tasks.size() == 2 && ' +
|
||||
'tasks.findAllByType(taskTypes.textToHtmlFile).size() == 1 &&' +
|
||||
'tasks.findAllByType(taskTypes.specialPageToHtmlFile).size() == 1 %>',
|
||||
getRenderContext(tasks: new TaskContainer([t0, t1]))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
default void textsAvailable() {
|
||||
this.doDslAssertionTest(
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.jessebrault.ssg.specialpage
|
||||
|
||||
import static org.mockito.Mockito.mock
|
||||
|
||||
final class SpecialPageMocks {
|
||||
|
||||
static SpecialPage blankSpecialPage() {
|
||||
def renderer = mock(SpecialPageRenderer)
|
||||
new SpecialPage(
|
||||
'',
|
||||
'',
|
||||
new SpecialPageType([], renderer)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import static com.jessebrault.ssg.specialpage.SpecialPageMocks.blankSpecialPage
|
||||
|
||||
final class SpecialPageToHtmlFileTaskMocks {
|
||||
|
||||
static SpecialPageToHtmlFileTask blankSpecialPageToHtmlFileTask() {
|
||||
new SpecialPageToHtmlFileTask(
|
||||
'',
|
||||
blankSpecialPage(),
|
||||
new HtmlFileOutput(
|
||||
new File(''),
|
||||
'',
|
||||
{ '' }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.jessebrault.ssg.task
|
||||
|
||||
import static com.jessebrault.ssg.text.TextMocks.blankText
|
||||
|
||||
final class TextToHtmlFileTaskMocks {
|
||||
|
||||
static TextToHtmlFileTask blankTextToHtmlFileTask() {
|
||||
new TextToHtmlFileTask(
|
||||
'',
|
||||
blankText(),
|
||||
new HtmlFileOutput(
|
||||
new File(''),
|
||||
'',
|
||||
{ '' }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.jessebrault.ssg.testutil
|
||||
|
||||
import com.jessebrault.ssg.Diagnostic
|
||||
import com.jessebrault.ssg.Result
|
||||
import com.jessebrault.ssg.text.ExcerptGetter
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.FirstParam
|
||||
@ -25,6 +26,10 @@ class DiagnosticsUtil {
|
||||
assertTrue(result.v1.isEmpty(), getDiagnosticsMessageSupplier(result.v1))
|
||||
}
|
||||
|
||||
static void assertEmptyDiagnostics(Result<?> result) {
|
||||
assertTrue(!result.hasDiagnostics(), getDiagnosticsMessageSupplier(result.diagnostics))
|
||||
}
|
||||
|
||||
static <E extends Exception> void assertDiagnosticException(
|
||||
Class<E> expectedException,
|
||||
Diagnostic diagnostic,
|
||||
|
@ -3,6 +3,8 @@ package com.jessebrault.ssg.testutil
|
||||
import com.jessebrault.ssg.Config
|
||||
import com.jessebrault.ssg.SiteSpec
|
||||
import com.jessebrault.ssg.renderer.RenderContext
|
||||
import com.jessebrault.ssg.task.Task
|
||||
import com.jessebrault.ssg.task.TaskContainer
|
||||
|
||||
class RenderContextUtil {
|
||||
|
||||
@ -14,7 +16,9 @@ class RenderContextUtil {
|
||||
args?.texts as Collection ?: [],
|
||||
args?.parts as Collection ?: [],
|
||||
args?.sourcePath as String ?: '',
|
||||
args?.targetPath as String ?: ''
|
||||
args?.targetPath as String ?: '',
|
||||
args?.tasks as TaskContainer ?: new TaskContainer(),
|
||||
args?.taskTypes as Set<Class<? extends Task>> ?: [] as Set<Class<? extends Task>>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class TextMocks {
|
||||
when(textRenderer.render(any(), any())).thenReturn(new Tuple2<>([], text))
|
||||
def frontMatterGetter = mock(FrontMatterGetter)
|
||||
def excerptGetter = mock(ExcerptGetter)
|
||||
new Text('', '', new TextType([], textRenderer, frontMatterGetter, excerptGetter))
|
||||
new Text(text, '', new TextType([], textRenderer, frontMatterGetter, excerptGetter))
|
||||
}
|
||||
|
||||
static Text textWithPath(String path) {
|
||||
@ -33,7 +33,7 @@ class TextMocks {
|
||||
when(textRenderer.render(any(), any())).thenReturn(new Tuple2<>([], text))
|
||||
def frontMatterGetter = mock(FrontMatterGetter)
|
||||
def excerptGetter = mock(ExcerptGetter)
|
||||
new Text('', path, new TextType([], textRenderer, frontMatterGetter, excerptGetter))
|
||||
new Text(text, path, new TextType([], textRenderer, frontMatterGetter, excerptGetter))
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user