Skip to content

Commit

Permalink
Merge pull request #1 from melkassib/refactor/generator-dsl
Browse files Browse the repository at this point in the history
- Renamed base package: 'gen' to 'generator'
- Update gradle config
- Added documentation (KDoc)
- Updated CI build file
  • Loading branch information
melkassib authored Feb 13, 2025
2 parents efe4da0 + bcc8b8b commit 025f1db
Show file tree
Hide file tree
Showing 40 changed files with 2,090 additions and 475 deletions.
37 changes: 27 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
name: Run Gradle
name: Build and run sonar analysis

on:
push:

branches:
- main
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 17
java-version: 21
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@v2
- name: Cache SonarQube packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Gradle packages
uses: actions/cache@v4
with:
gradle-version: 8.4
arguments: build
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build and analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: ./gradlew build sonar --info
192 changes: 192 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# DSL for AltaCV Resume

This project aims to provide a simple and flexible way to generate resumes in the [AltaCV](https://github.com/liantze/AltaCV) LaTeX format using a typesafe Kotlin DSL.

## AltaCV Resume Structure
![Sample Resume](docs/images/altacv-structure.png)


## Usage example
Sample files used in this example are located in the [samples](docs/samples) directory.

1. Generate a resume in Kotlin project:

Create a Kotlin file (e.g., `Main.kt`) and use the provided DSL to define your resume:

```kotlin
import com.melkassib.altacv.generator.dsl.domain.section.event.EventPeriodDate.Companion.eventDurationDate
import com.melkassib.altacv.generator.dsl.domain.section.event.EventPeriodString.Companion.eventDurationStr
import com.melkassib.altacv.generator.dsl.domain.builders.altacv
import com.melkassib.altacv.generator.dsl.domain.userInfo.*
import com.melkassib.altacv.generator.dsl.domain.section.*
import com.melkassib.altacv.generator.dsl.domain.*
import com.melkassib.altacv.generator.dsl.utils.*

fun main() {
val resume =
altacv {
config {
photoShape = PhotoShape.NORMAL
theme = PredefinedColorPalette.THEME3
}

header {
tagline = " Your Position or Tagline Here"
photo = Photo(2.8, "Globe_High.png")
userInfo = UserInfo("Your Name Here", setOf(
EmailField("your_name@email.com"),
PhoneField("000-00-0000"),
MailAddressField("Address, Street, 00000 Country"),
LocationField("Location, COUNTRY"),
HomePageField("www.homepage.com"),
TwitterField("@twitterhandle"),
LinkedinField("your_id"),
GithubField("your_id"),
OrcidField("0000-0000-0000-0000"),
UserInfoField("gitlab", "\\faGitlab", "https://gitlab.com/", "your_id")
))
}

sections {
section("Experience", firstColumn(1), Divider) {
contents {
event("Job Title 1") {
holder = "Company 1"
location = "Location"
duration = eventDurationStr("Month XXXX", "Ongoing")
description = listOf(
Item("Job description 1"),
Item("Job description 2"),
Item("Job description 3", false)
)
}

event("Job Title 2") {
holder = "Company 2"
location = "Location"
duration = eventDurationDate("2023-10", "2023-10")
description = listOf(Item("Item1"))
}

event("Job Title 3") {
holder = "Company 3"
location = "Location"
}
}
}

section("Most Proud of", firstColumn(2), ignored = false) {
contents {
achievement("faTrophy", "Fantastic Achievement", "and some details about it")
achievement("faHeartbeat", "Another achievement", "more details about it of course")
achievement("faHeartbeat", "Another achievement", "more details about it of course")
}
}

section("My Life Philosophy", firstColumn(1)) {
contents {
quote("Something smart or heartfelt, preferably in one sentence.")
}
}

section("Strengths", firstColumn(3)) {
contents {
tag("Hard-working")
tag("Eye for detail")
content(NewLine)

tag("Motivator & Leader")
content(Divider)

tag("C++")
tag("Embedded Systems")
content(NewLine)

tag("Statistical Analysis")
}
}

section("Languages", firstColumn(4)) {
contents {
skill("Arabic", "Native/Bilingual")
skill("English", "Professional working proficiency")
skill("Spanish", "Limited working proficiency")
skill("German", 2.0)
}
}

section("Projects", firstColumn(2), separator = Divider) {
contents {
event("Project 1") {
holder = "Funding agency/institution"
description = listOf(Item("Details"))
}

event("Project 1") {
holder = "Funding agency/institution"
duration = eventDurationStr("Project duration")
description = listOf(Item(" A short abstract would also work.", withBullet = false))
}
}
}

section("A day of my life", firstColumn(3)) {
contents {
wheelchart(1.5, 0.5) {
item(6, 8, "accent!30", "Sleep,\\\\beautiful sleep")
item(3, 8, "accent!40", "Hopeful novelist by night")
item(8, 8, "accent!60", "Daytime job")
item(2, 10, "accent", "Sports and relaxation")
item(5, 8, "accent!20", "Spending time with family")
}
content("\\newpage")
}
}

section("Education", firstColumn(4), separator = Divider) {
contents {
event("Ph.D. in Your Discipline") {
holder = "Your University"
duration = eventDurationDate("2002-09", "2006-06")
description = listOf(Item("Thesis title: Wonderful Research", false))
}

event("M.Sc. in Your Discipline") {
holder = "Your University"
duration = eventDurationDate("2001-09", "2002-06")
}

event("B.Sc. in Your Discipline") {
holder = "Stanford University"
duration = eventDurationDate("1998-09", "2001-06")
}
}
}
}
}

println(resume.toLaTeX()) // Generate LaTeX output
println(resume.toJson()) // Generate JSON representation of the resume
}
```

2. Generate resume from JSON (e.g. [sample-resume.json](docs/samples/sample-resume.json)) in Java project:
```java
import static com.melkassib.altacv.generator.dsl.serialization.JsonSerializers.buildResumeFromJson;
import static com.melkassib.altacv.generator.dsl.utils.ResumeTemplate.toLaTeX;

public class Main {
public static void main(String[] args) {
final String resumeAsJson = "...";

final Resume resume = buildResumeFromJson(resumeAsJson);
final String resumeLatexContent = toLaTeX(resume);

System.out.println(resumeLatexContent); // Generate LaTeX output
}
}
```
3. The easiest way to generate your resume PDF:
1. Copy the generated LaTeX content to the online LaTeX editor [Overleaf](https://www.overleaf.com/).
2. Add the AltaCV package class [altacv.cls](https://github.com/liantze/AltaCV/blob/main/altacv.cls) to the same directory as your LaTeX file.
3. Compile the LaTeX file to generate the PDF (using XeLaTeX compiler, Tex Live version 2024).
65 changes: 46 additions & 19 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import io.gitlab.arturbosch.detekt.Detekt

plugins {
kotlin("jvm") version "1.9.20"
id("io.gitlab.arturbosch.detekt") version "1.23.3"
kotlin("jvm") version "2.1.0"
alias(libs.plugins.detekt)
alias(libs.plugins.dokka)
alias(libs.plugins.sonar)
`java-library`
jacoco
}

group = "com.melkassib"
version = "1.0.0"
version = "0.0.1"

repositories {
mavenCentral()
mavenLocal()
}

dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.20")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.3")
implementation(libs.jackson.module.kotlin)

testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.0")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.10.1")
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("com.jayway.jsonpath:json-path-assert:2.8.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
testImplementation(kotlin("test"))
testImplementation(libs.hamcrest)
testImplementation(libs.json.path.assert)
testImplementation(libs.junit.jupiter.params)

detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.3")
detektPlugins(libs.detekt.formatting)
}

tasks.test {
useJUnitPlatform()
}

kotlin {
jvmToolchain(17)
jvmToolchain(21)
}

tasks.withType<Detekt>().configureEach {
Expand All @@ -41,11 +43,11 @@ tasks.withType<Detekt>().configureEach {
autoCorrect = true

reports {
html.required.set(true)
xml.required.set(false)
txt.required.set(false)
sarif.required.set(false)
md.required.set(false)
html.required = true
xml.required = true
txt.required = false
sarif.required = false
md.required = false
}
}

Expand All @@ -55,7 +57,32 @@ tasks.test {

tasks.jacocoTestReport {
reports {
xml.required = false
csv.required = false
xml.required = true
html.required = true
}
}

dokka {
dokkaSourceSets.main {
includes.from("docs/AltaCVGeneratorModule.md")

sourceLink {
localDirectory.set(file("src/main/kotlin"))
remoteUrl("https://github.com/melkassib/altacv-generator-dsl/blob/main/src/main/kotlin")
remoteLineSuffix.set("#L")
}
}

pluginsConfiguration.html {
footerMessage.set("(c) Mohcine EL KASSIB")
}
}

sonar {
properties {
property("sonar.projectKey", "melkassib:altacv-generator-dsl")
property("sonar.projectDescription", "Kotlin DSL for AltaCV Resume")
property("sonar.organization", "melkassib")
property("sonar.host.url", "https://sonarcloud.io")
}
}
15 changes: 15 additions & 0 deletions docs/AltaCVGeneratorModule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Module AltaCV Generator DSL

This module contains the DSL for generating an AltaCV resume (LaTeX).

# Package com.melkassib.altacv.generator.dsl.domain

Domain classes for the DSL.

# Package com.melkassib.altacv.generator.dsl.serialization

Contains the serialization logic for the DSL.

# Package com.melkassib.altacv.generator.dsl.utils

Contains utility functions and classes for the DSL.
Binary file added docs/images/altacv-structure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 025f1db

Please sign in to comment.