Skip to content

Commit

Permalink
[build] add syncImage Gradle task
Browse files Browse the repository at this point in the history
  • Loading branch information
h1romas4 committed Oct 4, 2023
1 parent 07e0f1d commit d10f3dc
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 3 deletions.
31 changes: 28 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,46 @@ asciidoctorj {
attributes 'source-highlighter': 'rouge'
}

/**
* docs/ 配下のファイルを全て削除するタスク
* docs タスクの依存で直接は実行しない。
*/
task cleanDocs(type: Delete) {
// Delete all files in the docs directory once
delete fileTree('docs/') {
include '**/*'
}
}

/**
* Asciidoc 文章とファイルシステムの画像の整合性を確認するユーティリティタスク
* 未使用画像とリンク切れ画像の一覧を出力する。
*
* ./gradlew syncImage
*
* @see buildSrc/src/main/groovy/AsciidocTasks.groovy
*/
tasks.register('syncImage', SyncImageTask) {
// 起点の文書ディレクトリ
baseDir = file('src/docs/asciidoc')
// 起点の Asciidoc 文書(include を辿る)
index = 'index.adoc'
// ファイルシステム上で画像として認識する拡張子
imageExt = ['png', 'jpg', 'jpeg', 'svg']
}

/**
* Asciidoc 文書から HTML/PDF 文書を生成し docs 配下に出力するタスク
*
* ./gradlew docs
*/
task docs(dependsOn: [asciidoctor, asciidoctorPdf, cleanDocs]) doLast {
// Copy documents created by asciidoctor to the docs directory
// build に生成された文書を docs にコピー
copy {
from 'build/docs/asciidoc/index.html'
from 'build/docs/asciidocPdf/index.pdf'
into 'docs/'
}
// Copy images to docs directory for index.html
// build に出力されたダイアログ生成画像を含む全ての画像を HTML 文書用に docs にコピー
copy {
from 'build/docs/asciidoc/'
include 'Chapter*/images/*'
Expand Down
13 changes: 13 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
id 'groovy'
}

repositories {
mavenCentral()
}

dependencies {
implementation gradleApi()
implementation localGroovy()
implementation 'org.asciidoctor:asciidoctorj:2.5.6'
}
117 changes: 117 additions & 0 deletions buildSrc/src/main/groovy/AsciidocTasks.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import java.lang.Comparable.PathSensitivity.*

import groovy.io.FileType

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.Input

import org.asciidoctor.Asciidoctor
import org.asciidoctor.SafeMode
import org.asciidoctor.Options

/**
* Asciidoc 文章とファイルシステムの画像の整合性を確認する Gradle タスク
*
* - 未使用画像の抽出
* - リンク切れ画像の抽出
*/
abstract class SyncImageTask extends DefaultTask {
/**
* 処理起点ディレクトリ
*/
@InputDirectory
File baseDir

/**
* 起点 Asciidoc 文書(include も処理する)
*/
@Input
def index

/**
* 画像として認識するファイルシステム上の拡張子
*/
@Input
def imageExt = ['png', 'jpg']

/**
* 未使用画像をファイルシステムから削除するかどうかを決定するフラグ(TODO: 未実装)
*/
@Input
boolean remove = false

/**
* Asciidoc 文書から image ブロックの画像パスをリスト取得
*
* @param File baseDir Asciidoc 文書が格納されているディレクトリ
* @param String index 起点となる Asciidoc 文書(この文書から include を辿る)
* @return [] baseDir からの相対画像パスリスト
*/
static def searchImageInAdoc(baseDir, index) {
def asciidoctor = Asciidoctor.Factory.create();
def options = Options.builder().safe(SafeMode.SAFE).baseDir(baseDir).build()
def document = asciidoctor.load(new File("${baseDir}/${index}").getText(), options);

document.findBy(["context": ":image"]).collect {
"${it.attributes.imagesdir}/${it.attributes.target}"
}
}

/**
* ディレクトリから指定された拡張子のファイルをリストで返却
* @param File baseDir 検索ベースディレクトリ
* @param extension 検索拡張子文字列リスト
* @return [] baseDir からの相対パスリスト
*/
static def searchExtInDir(File baseDir, extension) {
def list = []
def basePath = "${baseDir}/"
def ext = extension.collect {
".${it}"
}
baseDir.eachFileRecurse(FileType.FILES) {file ->
ext.each {
if(file.name.endsWith(it)) {
list << (file.path - basePath)
}
}
}
list
}

/**
* リスト形式の文字列を表示用に縦に出力
* @param lists 文字列リスト
* @param prefix 前置文字列
*/
static def print(lists, prefix = "") {
lists.each {
println "${prefix}${it}"
}
}

/**
* Gradle タスクエントリーポイント
*
* @return
*/
@TaskAction
def sync() {
def imagesInAdoc = searchImageInAdoc(baseDir, index).sort()
def imagesInDir = searchExtInDir(baseDir, imageExt).sort()

def unused = imagesInDir - imagesInAdoc
def notFound = imagesInAdoc - imagesInDir

if(unused.size() != 0) {
println "@Unused images:"
print unused
}
if(notFound.size() != 0) {
println "@Image not found:"
print notFound
}
}
}

0 comments on commit d10f3dc

Please sign in to comment.