import com.github.jk1.license.render.* import com.github.jk1.license.filter.ExcludeTransitiveDependenciesFilter import com.github.jk1.license.filter.LicenseBundleNormalizer import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer import com.github.jk1.license.render.InventoryMarkdownReportRenderer import org.jsoup.Jsoup //import org.gradle.internal.impldep.org.jsoup.Jsoup buildscript { repositories { mavenCentral() } dependencies { classpath ("org.jsoup:jsoup:1.18.1") // 빌드 스크립트에서 commonmark 라이브러리를 사용할 수 있도록 추가합니다. classpath("org.commonmark:commonmark:0.18.0") } } plugins { kotlin("jvm") version "1.9.25" kotlin("plugin.spring") version "1.9.25" id("org.springframework.boot") version "3.3.4" id("io.spring.dependency-management") version "1.1.6" id("com.github.jk1.dependency-license-report") version "2.0" } group = "kr.lunaticbum.back" version = "0.0.7-SNAPSHOT" java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } configurations { compileOnly { extendsFrom(configurations.annotationProcessor.get()) } } repositories { mavenCentral() maven { url = uri("https://repo.spring.io/milestone") } } dependencies { // implementation ("jakarta.servlet:jakarta.servlet-api") //스프링부트 3.0 이상 // implementation ("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api") //스프링부트 3.0 이상 // implementation ("org.glassfish.web:jakarta.servlet.jsp.jstl") //스프링부트 3.0 이상 implementation ("org.slf4j:jcl-over-slf4j") // implementation ("org.springframework.boot:spring-boot-starter-batch") implementation ("org.springframework.boot:spring-boot-starter-quartz") implementation ("com.google.code.gson:gson:2.11.0") implementation ("org.apache.tomcat.embed:tomcat-embed-jasper") implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive") implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-webflux") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("io.projectreactor.kotlin:reactor-kotlin-extensions") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity6") implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect") implementation ("org.jsoup:jsoup:1.18.1") implementation ("org.seleniumhq.selenium:selenium-java:4.10.0") implementation ("org.commonmark:commonmark:0.18.0") implementation ("net.coobird:thumbnailator:0.4.14") implementation("org.sejda.imageio:webp-imageio:0.1.6") implementation ("com.drewnoakes:metadata-extractor:2.19.0") implementation("org.springframework.boot:spring-boot-starter-security") compileOnly("org.projectlombok:lombok") // implementation(platform("com.google.cloud:libraries-bom: 26.55.0")) // implementation("com.google.cloud:google-cloud-apikeys") implementation ("com.google.maps:google-maps-services:2.2.0") // implementation ("org.springframework.ai:spring-ai-openai-spring-boot-starter:1.0.0-SNAPSHOT") // implementation ("org.springframework.ai:spring-ai-vertex-ai-gemini-spring-boot-starter:1.0.0-SNAPSHOT") // implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-SNAPSHOT") implementation(platform("org.springframework.ai:spring-ai-bom:1.0.0-M6")) implementation("org.springframework.ai:spring-ai-ollama-spring-boot-starter:1.0.0-M6") implementation ("org.springframework.ai:spring-ai-qdrant-store-spring-boot-starter") // implementation ("io.qdrant:client:1.13.0") implementation ("org.slf4j:slf4j-simple:1.7.25") implementation("io.jsonwebtoken:jjwt-api:0.11.5") implementation("io.jsonwebtoken:jjwt-impl:0.11.5") implementation("io.jsonwebtoken:jjwt-jackson:0.11.5") annotationProcessor("org.projectlombok:lombok") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("io.projectreactor:reactor-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } kotlin { compilerOptions { freeCompilerArgs.addAll("-Xjsr305=strict") } } tasks.withType() { duplicatesStrategy = DuplicatesStrategy.EXCLUDE exclude("META-INF/BC1024KE.RSA", "META-INF/BC1024KE.SF", "META-INF/BC1024KE.DSA") exclude("META-INF/BC2048KE.RSA", "META-INF/BC2048KE.SF", "META-INF/BC2048KE.DSA") } tasks.withType { useJUnitPlatform() } tasks.jar { archiveFileName.set("app.jar") manifest { attributes["Main-Class"] = "kr.lunaticbum.back.lun.LunApplicationKt" } configurations["compileClasspath"].forEach { file: File -> from(zipTree(file.absoluteFile)) } duplicatesStrategy = DuplicatesStrategy.EXCLUDE } tasks.jar { // Otherwise you'll get a "No main manifest attribute" error manifest { attributes["Main-Class"] = "kr.lunaticbum.back.lun.LunApplicationKt" } // To avoid the duplicate handling strategy error duplicatesStrategy = DuplicatesStrategy.EXCLUDE // To add all of the dependencies otherwise a "NoClassDefFoundError" error from(sourceSets.main.get().output) dependsOn(configurations.runtimeClasspath) from({ configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) } }) } // ✅ licenseReport는 이전과 동일하게 Markdown을 생성하도록 둡니다. licenseReport { outputDir = "$projectDir/build/licenses" renderers = arrayOf(InventoryMarkdownReportRenderer()) // filters = arrayOf(com.github.jk1.license.filter.LicenseBundleNormalizer(), com.github.jk1.license.filter.ExcludeTransitiveDependenciesFilter()) } tasks.register("updateLicensePage") { dependsOn("generateLicenseReport") doLast { // file("$projectDir/build/licenses").listFiles().forEach { // println("${it.absolutePath}: ${it.name}") // } // ... 로그 출력 로직은 그대로 유지 ... println("🚀 'updateLicensePage' 태스크를 시작합니다.") val licenseMarkdownFile = file("$projectDir/build/licenses/licenses.md") val targetHtmlFile = file("src/main/resources/templates/content/licenses.html") println(" - 원본 마크다운 파일: ${licenseMarkdownFile.path}") println(" - 대상 HTML 파일: ${targetHtmlFile.path}") if (!licenseMarkdownFile.exists()) { throw GradleException("❌ 라이선스 마크다운 파일이 생성되지 않았습니다. '${licenseMarkdownFile.path}'") } val licenseMarkdown = licenseMarkdownFile.readText() println(" - 마크다운 파일을 성공적으로 읽었습니다. (내용 길이: ${licenseMarkdown.length})") val parser = Parser.builder().build() val renderer = HtmlRenderer.builder().build() val licenseHtml = renderer.render(parser.parse(licenseMarkdown)) println(" - 마크다운을 HTML로 변환했습니다. (HTML 길이: ${licenseHtml.length})") // ✅ Jsoup으로 HTML 파일을 파싱합니다. val doc = Jsoup.parse(targetHtmlFile, "UTF-8") // ✅ CSS 선택자를 이용해 ID가 'license-content-container'인 태그를 선택하고 // 그 내부 HTML을 생성된 라이선스 내용으로 교체합니다. doc.selectFirst("#license-content-container")?.html(licenseHtml) println(" - HTML 파일 내 placeholder div의 내용을 교체했습니다.") // ✅ 변경된 HTML 내용을 파일에 다시 씁니다. targetHtmlFile.writeText(doc.outerHtml()) println("✅ 라이선스 정보(HTML)가 '${targetHtmlFile.name}' 파일에 성공적으로 업데이트되었습니다.") } } // 'build' 태스크 실행 시 이 작업이 자동으로 수행되도록 연결 // [수정 전] tasks.build { dependsOn(tasks.getByName("updateLicensePage")) } tasks.named("build") { // [수정 후] 'build' 태스크를 더 안전하게 참조합니다. dependsOn(tasks.named("updateLicensePage")) } tasks.named("bootJar") { // [수정 후] 'build' 태스크를 더 안전하게 참조합니다. dependsOn(tasks.named("updateLicensePage")) } // //// 'build' 태스크 실행 시 이 작업이 자동으로 수행되도록 연결 //tasks.build { // dependsOn(tasks.getByName("updateLicensePage")) //}