diff --git a/assets/mods/basegame/books/btex.xml b/assets/mods/basegame/books/btex.xml index 668519b1f..a0b3c5be4 100644 --- a/assets/mods/basegame/books/btex.xml +++ b/assets/mods/basegame/books/btex.xml @@ -47,7 +47,7 @@ Introduction -

is a markup language based on XML, with a resemblance of the . +

(pronounced as /biːtɛk/) is a markup language based on XML, with a resemblance of the . abstracts away the meticulous styling and typesetting configurations, so you can focus on actually writing your texts than debugging the macros. This does come with a downside of not being able to change the given style.

@@ -74,23 +74,23 @@ The Cover

The Cover defines the text on the cover of the book. If your text has no cover, this part can be omitted. Its syntax is as follows:

- <cover>
-  <title>Title of your book</title>
-  <subtitle>Subtitle if necessary</subtitle>
-  <author>Who wrote this book</author>
-  <edition>Edition information if necessary</edition>
+ <cover hue="358">
+  <title>Title of your book&zwsp;</title>
+  <subtitle>Subtitle if necessary&zwsp;</subtitle>
+  <author>Who wrote this book&zwsp;</author>
+  <edition>Edition information if necessary&zwsp;</edition>
</cover>

Only the title tag is mandatory. Cover texts will be printed using a special font that has wider gaps between characters. The title text will be printed in a double-size.

- +

The cover can have different colour with the hue attribute, which takes a number between 0 and 360.

The Table of Contents

The contents of the Table of Contents is filled in automatically by reading through your manuscript; parts, chapters and sections will be added. Its syntax is as follows:

- <tocpage title="Custom page name if necessary"><tableofcontents/></tocpage> + <tocpage title="Custom page name if necessary">&zwsp;<tableofcontents/>&zwsp;</tocpage>

The optional title attribute allows a custom name can be given to this page. @@ -132,7 +132,7 @@

  • I — use majuscule Roman numeral for the number (I, II, III, …)
  • 1 — use numbers (1, 2, 3)
  • -

    By default, parts use majuscule Roman numerals and others use just numbers.

    +

    By default, parts use majuscule Roman numerals and others use just numbers. Alternative styling for the part and the chapter can be defined using the Macro Definition.

    Paragraph Styling
    @@ -159,7 +159,7 @@

    The contents of the Index Page is filled in automatically by reading through your manuscript. All the usage of index tags will be shown here. Its syntax is as follows:

    - <indexpage title="Custom page name if necessary"><tableofindices/></indexpage> + <indexpage title="Custom page name if necessary">&zwsp;<tableofindices/>&zwsp;</indexpage>

    The optional title attribute allows a custom name can be given to this page. If unspecified, diff --git a/assets/mods/basegame/books/btex_ko.xml b/assets/mods/basegame/books/btex_ko.xml new file mode 100644 index 000000000..caf211f24 --- /dev/null +++ b/assets/mods/basegame/books/btex_ko.xml @@ -0,0 +1,176 @@ + + + + + + + + 문자를 모아 책을 찍어내어 엮는 머나먼 여정으로의 소개 + 책 쓰고 찍어내는 법 + Terran Publishing + 시험판 + + + + + + + + 책이란 무엇인가 + +

    본 견본은 책 조판 언어의 예시를 위해 제작되었다.

    + +
    책이란 정말 무엇인가
    + +

    책 조판 시스템에서 책이란 페이지 번호와 그림과 하이퍼링크와 같은 요소를 포함하여 가독성 좋게 편집된 글의 뭉치를 말한다.

    +

    책은 ‘엮인’ 글로 취급되어 두 페이지가 한번에 보여진다.

    + + 타자기를 사용한 집필 + +

    타자기는 글 쓰기의 시작을 빠르고 편리하게 해 준다. 타자기를 클릭하면 바로 작성이 가능하다.

    +

    하지만 타자기를 사용할 때는 여러 문자 사용 불가, 사진 첨부 불가, 하이퍼링크 사용 불가, 너덜너덜해 못생긴 문단과 같은 크나큰 단점이 따라온다.

    +

    타자기로 찍은 문서는 ‘엮이지 않은’ 글로 취급되어 한번에 한 페이지만 보여진다.

    +

    위와 같은 이유로 타자기로는 책다운 책을 만들 수 없다.

    + + 출판사와 인쇄소를 이용한 집필 + +

    출판사를 통하면 진짜배기 책의 모든 장점을 담은 책다운 책을 고작 한 권도 아닌 여러 권을 원하는 만큼 찍어낼 수 있다.

    +

    책을 인쇄하려면 원고를 출판사로 보내야 한다. 책을 찍어내기 위한 원고는 이라는 특수한 언어로 작성되어야 한다.

    +

    을 통하며 책 전체의 생김새를 간단히 기술할 수 있다. 사용할 수 있는 스타일은 조판 시스템이 지원하는 범위 안에서 제약이 없다. 타자기로 찍어낸 듯한 글도 원한다면 얼마든지 인쇄되도록 할 수 있다.

    + + + + + 소개 + +

    (발음: [비ː텍])은 과 유사하게 설계된 XML 기반의 마크업 언어이다. + 은 세세한 스타일 정의문과 조판 설정을 추상화하여, 글을 쓰면서 매크로를 디버깅하는 등의 일 없이 글쓰기에 집중할 수 있도록 설계되었다. 다만 이러한 이유로 미리 정의된 스타일을 뜯어고치는 것은 어렵다.

    +

    문서는 다음의 다섯 부분으로 나뉘어진다. 스타일 정의문, + 표지 정의문, 목차 정의문, 원고, 색인 페이지. 이 중 스타일 정의문과 원고는 필수로 존재하여야 하는 부분이다.

    + + + 스타일 정의문 + +

    스타일 정의문은 문서의 가장 첫 부분이다. 스타일 정의문의 구조는 다음과 같다.

    + + <btexdoc cover="hardcover" inner="standard" papersize="standard"> + + +

    btexdoc 태그는 다음의 속성을 지원한다.

    +
      +
    • cover — 표지의 스타일을 지정함. 지원하는 값: hardcover, none
    • +
    • inner — 내용의 스타일을 지정함. 지원하는 값: standard, typewriter
    • +
    • papersize — 판형을 지정함. 지원하는 값: standard
    • +
    + + 표지 정의문 + +

    cover 태그는 책의 표지를 지정한다. 표지가 없는 책이라면 이 부분은 생략 가능하다. 표지 정의문의 구조는 다음과 같다.

    + <cover hue="358">
    +   <title>책 제목&zwsp;</title>
    +   <subtitle>필요한 경우 부제목&zwsp;</subtitle>
    +   <author>누가 이 책을 집필하였는가&zwsp;</author>
    +   <edition>필요한 경우 판본 정보&zwsp;</edition>
    + </cover> +
    +

    이 중 title 태그만이 필수 태그이다. 표지의 문구는 글자간 간격이 넓게 인쇄된다. 책 제목은 두배 큰 크기로 인쇄된다.

    +

    표지의 색깔은 hue 속성을 사용해 바꿀 수 있다. 0에서 360 사이의 숫자를 사용할 수 있다.

    + + + 목차 정의문 + +

    목차 페이지의 내용은 원고를 읽어 자동으로 채워진다. 목차 정의문의 구조는 다음과 같다.

    + + <tocpage title="목차 혹은 필요한 다른 제목">&zwsp;<tableofcontents/>&zwsp;</tocpage> + + +

    title 속성은 목차 페이지의 장제목을 지정한다. 지정하지 않았으면 “Table of Contents”가 인자된다.

    +

    <tableofcontents/> 태그는 조판 시스템이 내부적으로 사용하는 태그이다.

    + + + 원고 + +

    원고는 실제 책의 본문이 담긴 부분을 말한다. 본문에는 다음의 태그를 사용할 수 있다.

    +
      +
    • part — inserts part separation page to your book
    • +
    • chapter, section — inserts a new chapter/section. If an alternative name is required on the Table of Contents, the alt attribute can be used. If the chapter/section needs to be hidden on the Table of Contents, add the hide="1" attribute. If the chapter must start on a new page, simply add newpage in front of the chapter tag
    • +
    • p — inserts a new paragraph. The body texts must be written inside this tag. All paragraphs will have a 16-pixel indentation, with the following exceptions: first p of the part/chapter/section; first p after br, newpage, callout, ul, ol or anonbreak
    • +
    • span — allows changing the colour of the texts. The colour must be specified in the colour attribute. Six-digit hex code, three-digit hex code and CSS Colors Level 4 named colours are supported. Note that all the colours will be rounded to the nearest three-digit hex code
    • +
    • emph — is a special case of the span tag. The resulting text will be red
    • +
    • itemname — is a special case of the span tag used to highlight the name of the ingame item. The resulting text will be blue
    • +
    • targetname — is a special case of the span tag used to highlight the name of an arbitrary target or goals. The resulting text will be green
    • +
    • code — is a special case of the span tag used to highlight the code element in-line. The resulting text will be surrounded in a grey box
    • +
    • br — self-closing tag; inserts an anonymous line break
    • +
    • newpage — self-closing tag; inserts an anonymous page break
    • +
    • anonbreak — self-closing tag; inserts a paragraph break in the text. The break will be in a form of a long straight line on the centre of the text. Useful for typesetting novels
    • +
    • callout — is a paragraph box that holds a text in a grey box, a style similar to the code tag
    • +
    • ul — starts an unordered list. List elements are defined using the li tag
    • +
    • ol — starts an ordered list. List elements are defined using the li tag
    • +
    • fullpagebox — is used to typeset its child tags into a box that fills an entire page, with its contents centred on the page. Must be used after the newpage
    • +
    • btex — self-closing tag; inserts an inline form of the logo in the text
    • +
    +

    스스로 닫는 태그는 하위 내용을 담을 수 없다. 스스로 닫는 태그는, 예를 들어 tagname이라는 태그가 있으면, 다음과 같이 쓴다. <tagname/>.

    + + +
    장절제목 스타일
    + +

    부와 장과 절은 type 속성을 사용해 번호가 찍히는 스타일을 지정할 수 있다. 지원하는 스타일은 다음과 같다.

    +
      +
    • a — 번호로 알파벳을 사용함 (a, b, c, …)
    • +
    • A — 번호로 알파벳 대문자를 사용함 (A, B, C, …)
    • +
    • i — 번호로 로마 숫자를 사용함 (i, ii, iii, …)
    • +
    • I — 번호로 로마 숫자 대문자를 사용함 (I, II, III, …)
    • +
    • 1 — 번호를 사용함 (1, 2, 3)
    • +
    +

    기본값은, 부는 로마 숫자 대문자, 장과 절은 그냥 번호를 사용한다. “Part I”로 찍히는 것을 “제1절”로 변경하는 등의 심화된 스타일은 매크로 정의문에서 정의할 수 있다.

    + + +
    문단 스타일
    + +

    pcallout 태그는 align 속성을 지원한다. 지원하는 스타일은 다음과 같다.

    +
      +
    • left — 문단을 좌측정렬함
    • +
    • justify — 문단을 양끝정렬함. 기본값
    • +
    +

    p, span, callout 태그는 추가로 class="code" 속성을 지원한다. 이 속성이 적용된 문구는 코드꼴(code font)을 사용해 인자된다.

    + + +
    하이퍼링크
    + +

    하이퍼링크는indexa 태그를 사용해 적용할 수 있다.

    +
      +
    • index — 링크의 목적지를 정의함. 링크의 이름은 문서 전체에서 유일하여야 하며, id 속성에 작성함
    • +
    • a — 태그 내부의 문구를 클릭 가능하게 함. 링크의 목적지는 (index 태그의 id) href 속성에 작성함
    • +
    + + + 색인 페이지 + +

    색인 페이지의 내용은 원고를 읽어 자동으로 채워진다. + 문서에 사용된 모든 index 태그가 이 페이지에 인쇄된다. 색인 페이지의 구조는 다음과 같다.

    + + <indexpage title="색인 혹은 필요한 다른 제목">&zwsp;<tableofindices/>&zwsp;</indexpage> + + +

    title 속성은 색인 페이지의 장제목을 지정한다. 지정하지 않았으면 “Index”가 인자된다.

    + + + 문서 끝맺기 + +

    문서는 btexdoc 태그로 시작되었으니, 반드시 같은 태그로 끝나야 한다. </btexdoc>을 써 넣어 문서를 마무리하자.

    + + + 마무리 + +

    으로 작성된 최종 원고는 출판사에 도착한 후 인쇄가 시작된다. 원고에 오류가 없다면 주문한 부수대로 책이 인쇄되어 합리적인 영업일 내에 우편으로 배송된다. 즐거운 글쓰기가 되길!

    + + + + +

    이 페이지는 의도적으로 비워 두었습니다

    +
    + + + + + diff --git a/btexdoc.dtd b/btexdoc.dtd index 2451551fa..b4b177d43 100644 --- a/btexdoc.dtd +++ b/btexdoc.dtd @@ -1,5 +1,6 @@ + @@ -53,16 +54,17 @@ - + + - + diff --git a/src/net/torvald/btex/BTeXParser.kt b/src/net/torvald/btex/BTeXParser.kt index 6b0c71bea..ad14430f8 100644 --- a/src/net/torvald/btex/BTeXParser.kt +++ b/src/net/torvald/btex/BTeXParser.kt @@ -31,6 +31,7 @@ import org.xml.sax.helpers.DefaultHandler import java.io.File import java.io.FileInputStream import java.io.StringReader +import java.util.regex.Pattern import javax.xml.parsers.SAXParserFactory import kotlin.math.roundToInt import kotlin.reflect.KFunction @@ -137,6 +138,17 @@ object BTeXParser { private val bodyTextShadowAlpha = 0.36f + private val macrodefs = hashMapOf( + "thepart" to "Part %1\$s", + "thechapter" to "%1\$s" + ) + + private fun invokeMacro(name: String, vararg args: String): String { + val name = name.lowercase() + val template = macrodefs[name] ?: throw IllegalArgumentException("No macro '$name' exists") + return String.format(template, *args) + } + private fun Int.toListNumStr(style: String) = when (style) { "I" -> this.toRomanNum() @@ -675,11 +687,16 @@ object BTeXParser { @OpenTag // reflective access is impossible with 'private' fun processElemPAIR(handler: BTeXHandler, doc: BTeXDocument, uri: String, attribs: HashMap) { - if (tagStack.size == 3 && tagStack.getOrNull(1) == "blocklut") { + if (tagStack.size == 3 && tagStack.getOrNull(1) == "BLOCKLUT") { blockLut[attribs["key"]!!] = attribs["value"]!! } + else if (tagStack.size == 3 && tagStack.getOrNull(1) == "MACRODEF") { + val key = attribs["key"]!! + val value = attribs["value"]!! + macrodefs[key.lowercase()] = value + } else { - throw BTeXParsingException(" used outside of ") + throw BTeXParsingException(" used outside of or ") } } @@ -873,10 +890,11 @@ object BTeXParser { val heading = if (part == null && cpt == null && sect == null) "" else if (part != null && cpt == null && sect == null) - "Part $part${glueToString(HEADING_NUM_TITLE_GAP)}" + "${invokeMacro("thepart", part)}${glueToString(HEADING_NUM_TITLE_GAP)}" + else if (cpt != null && sect == null) + "${invokeMacro("thechapter", cpt)}${glueToString(HEADING_NUM_TITLE_GAP)}" else - listOfNotNull(cpt, sect).joinToString(".") + "${glueToString(HEADING_NUM_TITLE_GAP)}" + - (if (cpt != null && cpt.length < 2 && cpt.isNum()) "${glueToString(HEADING_NUM_TITLE_GAP)}" else "") + "$cpt.$sect${glueToString(HEADING_NUM_TITLE_GAP)}" typesetTOCline("$heading", name, pg, handler, indent, tocPage) } @@ -1103,7 +1121,7 @@ object BTeXParser { val cptSectInfo = cptSectStack.removeLast() val partNumStr = partOrder.toListNumStr(cptSectInfo.style) - typesetPartHeading(partNumStr, thePar, handler) + typesetPartHeading(invokeMacro("thepart", partNumStr), thePar, handler) if (!cptSectInfo.type.endsWith("-hidden")) cptSectMap.add(CptSectInfo("part", cptSectInfo.alt ?: thePar, doc.currentPage, partNumStr, null, null)) @@ -1123,7 +1141,7 @@ object BTeXParser { val partNumStr = partOrder.toListNumStr(cptSectStack.findLast { it.type.startsWith("part") }?.type ?: "1") val cptNumStr = cptOrder.toListNumStr(cptSectInfo.style) - typesetChapterHeading(cptNumStr, thePar, handler, 16) + typesetChapterHeading(invokeMacro("thechapter", cptNumStr), thePar, handler, 16) if (!cptSectInfo.type.endsWith("-hidden")) cptSectMap.add(CptSectInfo("chapter", cptSectInfo.alt ?: thePar, doc.currentPage, partNumStr, cptNumStr, null)) @@ -1241,7 +1259,7 @@ object BTeXParser { } private fun typesetPartHeading(num: String, thePar: String, handler: BTeXHandler, indent: Int = PAR_INDENTATION, width: Int = doc.textWidth) { - typesetParagraphs("${ccDefault}⁃ Part $num ⁃", handler, align = "left") + typesetParagraphs("${ccDefault}⁃ $num ⁃", handler, align = "left") typesetParagraphs(" ", handler, align = "left") // typesetParagraphs(getTitleFont(), "$ccDefault$thePar", handler) typesetParagraphs(getSubtitleFont(), "$ccDefault$thePar", handler, align = "left") diff --git a/src/net/torvald/terrarum/tests/BTeXTest.kt b/src/net/torvald/terrarum/tests/BTeXTest.kt index 0a7ab07f8..ce335ff2d 100644 --- a/src/net/torvald/terrarum/tests/BTeXTest.kt +++ b/src/net/torvald/terrarum/tests/BTeXTest.kt @@ -26,7 +26,7 @@ import kotlin.system.measureTimeMillis */ class BTeXTest : ApplicationAdapter() { - val filePath = "btex.xml" + val filePath = "btex_ko.xml" // val filePath = "test.xml" // val filePath = "literature/en/daniel_defoe_robinson_crusoe.xml" // val filePath = "literature/ruRU/anton_chekhov_palata_no_6.xml"