diff --git a/bonus2/.svnignore b/bonus2/.svnignore
new file mode 100644
index 0000000..917d690
--- /dev/null
+++ b/bonus2/.svnignore
@@ -0,0 +1,13 @@
+*.iml
+.idea
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+/lib
+*.jar
+/dist
+
diff --git a/bonus2/bonus2.iml b/bonus2/bonus2.iml
new file mode 100644
index 0000000..b6a671e
--- /dev/null
+++ b/bonus2/bonus2.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bonus2/build.gradle b/bonus2/build.gradle
new file mode 100644
index 0000000..0cb9257
--- /dev/null
+++ b/bonus2/build.gradle
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+
+buildscript {
+ ext.kotlin_version = '1.3.0'
+
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.0'
+ }
+}
+
+apply plugin: 'kotlin'
+apply plugin: 'com.github.johnrengelman.shadow'
+apply plugin: 'application'
+
+defaultTasks 'run'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'org.jsoup:jsoup:1.11.3'
+}
+
+mainClassName = 'ch.usi.inf.atelier.group1.Main'
+
+sourceSets {
+ main.java.srcDirs += 'src'
+}
+
+task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from 'src'
+}
+
+jar {
+ manifest {
+ attributes 'Main-Class': 'ch.usi.inf.atelier.group1.MainKt'
+ }
+}
+
+shadowJar {
+ baseName = 'bonus2'
+ classifier = null
+ version = null
+}
diff --git a/bonus2/res/test.html b/bonus2/res/test.html
new file mode 100644
index 0000000..0170136
--- /dev/null
+++ b/bonus2/res/test.html
@@ -0,0 +1,59 @@
+---
+layout: page
+category-title: Basic commands
+category-page: basic
+tags: directory change navigate
+author: Alessandro Marinelli
+title: cd
+previous-page: pages/cmd/basic/open.html
+next-page: pages/cmd/basic/ls.html
+---
+
+
+The cd
command is used to change the working directory
+The name stands for Change Directory.
+
+The default cd command syntax is:
+
+
+cd [flags] [path]
+
+
+Where [flags] are the cd flags, read below for more info,and [path] is the
+path (absolute or relative), of the directory which we want to make as working directory.
+
+Change the working directory
+Let's see how to use the command cd
in order to change the working directory
+
+
+pwd
+ ~
+cd Desktop/multimedia
+pwd
+ ~/Desktop/multimedia
+
+
+As you can see, we changed the working directory from ~ (which stands for HOME),
+to "multimedia". Now our Shell will work on the directory "multimedia"
+until a new cd will occour.
+
+Notice: If you want to move to a directory which is not contained in the
+current working directory, you MUST use the absolute path.
+
+
+Header 1
+
+Header 2
+
+Header 4
+
+
+ - A
+ - B: Hello there
+ - C
+ - D
+
+
+
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/Main.kt b/bonus2/src/ch/usi/inf/atelier/group1/Main.kt
new file mode 100644
index 0000000..6b8688d
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/Main.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1
+
+import ch.usi.inf.atelier.group1.html.HtmlParser
+
+object Main {
+
+ @JvmStatic
+ fun main(args: Array) {
+
+ for (arg in args) {
+ println(HtmlParser(arg).parse())
+ }
+ }
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/html/HtmlParser.kt b/bonus2/src/ch/usi/inf/atelier/group1/html/HtmlParser.kt
new file mode 100644
index 0000000..2cfa3cf
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/html/HtmlParser.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.html
+
+import ch.usi.inf.atelier.group1.tex.TexDocument
+import ch.usi.inf.atelier.group1.util.Log
+import ch.usi.inf.atelier.group1.util.extensions.writeJekyllHeader
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+import java.io.File
+
+class HtmlParser(path: String) {
+ private val file = JekyllHtmlFile(File(path))
+ private val document = Jsoup.parse(file.content)
+ private val texDocument = TexDocument()
+
+ fun parse(): String {
+ if (!file.isValid()) {
+ return ""
+ }
+
+ texDocument.start()
+ texDocument.writeJekyllHeader(file)
+ texDocument.beginDocument()
+
+ document.body().children().forEach { element -> parseToTex(element) }
+
+ texDocument.endDocument()
+
+ return texDocument.toString()
+ }
+
+ private fun parseToTex(element: Element) {
+ val text = element.ownText()
+
+ // TODO: fix span elements inside the paragraph senteces (tag-less items)
+
+ texDocument.apply {
+ when (element.tagName()) {
+ TAG_BOLD -> addBold(text)
+ TAG_BR -> addBr()
+ TAG_CODE -> addCode(text)
+ TAG_H1 -> addSection(text)
+ TAG_H2 -> addSubSection(text)
+ TAG_H3, TAG_H4 -> addSubSubSection(text)
+ TAG_ITALICS -> addItalics(text)
+ TAG_LINK -> addLink(text, element.attr("href"))
+ TAG_P -> addParagraph(text)
+ TAG_PRE -> addPre(text)
+ TAG_UL -> element.parseList()
+ "", null -> addText(element.text())
+ }
+ }
+ }
+
+ private fun Element.parseList() {
+ texDocument.apply {
+ beginList()
+
+ children().filter { TAG_LI == it.tagName() }
+ .forEach { e -> addListItem(e.text()) }
+
+ endList()
+ }
+ }
+
+ companion object {
+ private const val TAG_BOLD = "b"
+ private const val TAG_BR = "br"
+ private const val TAG_CODE = "code"
+ private const val TAG_H1 = "h1"
+ private const val TAG_H2 = "h2"
+ private const val TAG_H3 = "h3"
+ private const val TAG_H4 = "h4"
+ private const val TAG_ITALICS = "i"
+ private const val TAG_LI = "li"
+ private const val TAG_LINK = "a"
+ private const val TAG_P = "p"
+ private const val TAG_PRE = "pre"
+ private const val TAG_UL = "ul"
+ }
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/html/JekyllHtmlFile.kt b/bonus2/src/ch/usi/inf/atelier/group1/html/JekyllHtmlFile.kt
new file mode 100644
index 0000000..0cc09f0
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/html/JekyllHtmlFile.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.html
+
+import ch.usi.inf.atelier.group1.util.extensions.getContent
+import java.io.BufferedReader
+import java.io.File
+import java.io.StringReader
+
+class JekyllHtmlFile(file: File) {
+ val header = HashMap()
+ val content: String
+
+ init {
+ val fileContent = file.getContent()
+ val contentBuilder = StringBuilder()
+
+ var isIteratingInHeader = false
+ var line: String? = ""
+
+ val reader = BufferedReader(StringReader(fileContent))
+
+ while (line != null) {
+ if (!isIteratingInHeader && HEADER_START == line) {
+ isIteratingInHeader = true
+ } else if (isIteratingInHeader) {
+ isIteratingInHeader = HEADER_END != line
+
+ if (isIteratingInHeader) {
+ val values = line.split(":")
+ if (values.size == 2) {
+ header[values[0]] = values[1].trim()
+ }
+ }
+ } else {
+ contentBuilder.append(line).append('\n')
+ }
+
+ line = reader.readLine()
+ }
+
+ content = contentBuilder.toString()
+ }
+
+ fun isValid() = header.isNotEmpty() && content.isNotBlank()
+
+ override fun toString() =
+ "Header:\n$header\nContent:\n$content"
+
+ companion object {
+ private const val HEADER_START = "---"
+ private const val HEADER_END = "---"
+ }
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/tex/TexDocument.kt b/bonus2/src/ch/usi/inf/atelier/group1/tex/TexDocument.kt
new file mode 100644
index 0000000..75dead2
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/tex/TexDocument.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.tex
+
+class TexDocument {
+ private val document = StringBuilder()
+
+ fun start() {
+ document.clear()
+
+ insert(HEADER, false, true)
+ }
+
+ fun beginDocument() {
+ insert("\\begin{document}", false, true)
+ insert("\\maketitle", false, true)
+ insert("\\tableofcontents", false, true)
+ insert("\\newpage", false, true)
+ }
+
+ fun endDocument() {
+ insert("\\end{document}", false, true)
+ }
+
+ fun addParagraph(content: String) {
+ if (content.isNotBlank()) {
+ insert(content, true, true)
+ }
+ }
+
+ fun addText(content: String) {
+ if (content.isNotBlank()) {
+ insert(content, false, true)
+ }
+ }
+
+ fun addSection(content: String) {
+ insert(SECTION.format(content, content.trim().toLowerCase()), false, true)
+ }
+
+ fun addSubSection(content: String) {
+ insert(SUB_SECTION.format(content), false, true)
+ }
+
+ fun addSubSubSection(content: String) {
+ insert(SUB_SUB_SECTION.format(content), false, true)
+ }
+
+ fun addBold(content: String) {
+ insert(BOLD.format(content), false, false)
+ }
+
+ fun addItalics(content: String) {
+ insert(ITALICS.format(content), false, false)
+ }
+
+ fun addCode(content: String) {
+ insert(CODE.format(content), false, false)
+ }
+
+ fun addPre(content: String) {
+ insert(PRE.format(content), false, true)
+ }
+
+ fun addLink(content: String, url: String) {
+ insert(LINK.format(content, url), false, true)
+ }
+
+ fun beginList() {
+ insert("\\begin{itemize}", false, true)
+ }
+
+ fun endList() {
+ insert("\\end{itemize}", false, true)
+
+ }
+
+ fun addListItem(content: String) {
+ insert(LIST_ITEM.format(content), false, true)
+ }
+
+ fun addBr() {
+ insert("", false, false)
+ }
+
+ fun setAuthor(content: String) {
+ insert(AUTHOR.format(content), false, true)
+ }
+
+ fun setTitle(content: String) {
+ insert(TITLE.format(content), false, true)
+ }
+
+ private fun insert(string: String, newLine: Boolean, endLine: Boolean) {
+ document.apply {
+ append(string)
+ if(newLine) {
+ append("\\\\")
+ }
+ if (endLine) {
+ append("\n")
+ }
+ }
+ }
+
+ override fun toString() = document.toString()
+
+ companion object {
+ private const val AUTHOR = "\\author{%1\$s}\n"
+ private const val BOLD = "\\textbf{%1\$s}"
+ private const val CODE = "\\texttt{%1\$s}"
+ private const val ITALICS = "\\emph{%1\$s}"
+ private const val LINK = "\\emph{%1\$s} \\footnote{\\url{%2\$s}}"
+ private const val LIST_ITEM = "\\item %1\$s"
+ private const val PRE = "\n\\begin{verbatim}\n%1\$s\n\\end{verbatim}"
+ private const val SECTION = "\\section{%1\$s}\\label{%2\$s}"
+ private const val SUB_SECTION = "\\subsection{%1\$s}"
+ private const val SUB_SUB_SECTION = "\\subsubsection{%1\$s}"
+ private const val TITLE = "\\title{%1\$s}\n"
+
+ private const val HEADER =
+ "\\documentclass[hidelinks,12pt,a4paper,numbers=enddot]{scrartcl}\n\n" +
+ "\\usepackage[margin=2cm]{geometry}\n" +
+ "\\usepackage{hyperref}\n"
+
+ }
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/util/Log.kt b/bonus2/src/ch/usi/inf/atelier/group1/util/Log.kt
new file mode 100644
index 0000000..88ad775
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/util/Log.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.util
+
+import java.lang.Exception
+
+object Log {
+
+ fun e(message: String = "", exception: Exception) {
+ e("$message: ${exception.message ?: "Unknown error"}")
+ }
+
+ fun e(message: String) {
+ System.err.println(message)
+ }
+
+ fun i(obj: Any) {
+ println(obj.toString())
+ }
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/File.kt b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/File.kt
new file mode 100644
index 0000000..af437dd
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/File.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.util.extensions
+
+import ch.usi.inf.atelier.group1.util.Log
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileReader
+import java.io.IOException
+
+fun File.getContent(): String {
+ val content = StringBuilder()
+ try {
+ val reader = BufferedReader(FileReader(this))
+ var line: String? = ""
+
+ while (line != null) {
+ content.append(line)
+ .append('\n')
+ line = reader.readLine()
+ }
+ } catch (e: IOException) {
+ Log.e(exception = e)
+ }
+
+ return content.toString()
+}
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/String.kt b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/String.kt
new file mode 100644
index 0000000..c39e71f
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/String.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.util.extensions
+
+import ch.usi.inf.atelier.group1.util.Log
+import java.io.File
+import java.io.IOException
+
+fun String.toFile(): File? {
+ try {
+ File(this)
+ } catch (e: IOException) {
+ Log.e("Failed to open $this as File", e)
+ throw e
+ }
+
+ return null
+}
+
+fun String.getClosingTag() = "${substring(1, length)}"
\ No newline at end of file
diff --git a/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/TexDocument.kt b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/TexDocument.kt
new file mode 100644
index 0000000..6f405d1
--- /dev/null
+++ b/bonus2/src/ch/usi/inf/atelier/group1/util/extensions/TexDocument.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018. Bevilacqua Joey
+ */
+package ch.usi.inf.atelier.group1.util.extensions
+
+import ch.usi.inf.atelier.group1.html.JekyllHtmlFile
+import ch.usi.inf.atelier.group1.tex.TexDocument
+
+fun TexDocument.writeJekyllHeader(file: JekyllHtmlFile) {
+ val title = file.header["title"] ?: "Unknown title"
+ val author = file.header["author"] ?: "Unknown author"
+
+ setTitle(title)
+ setAuthor(author)
+}
\ No newline at end of file