laporan-generator 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/.agents/skills/laporan-generator/SKILL.md +132 -0
  2. package/.agents/skills/laporan-generator/agents/openai.yaml +3 -0
  3. package/.agents/skills/laporan-generator/references/campus-guide.md +120 -0
  4. package/.agents/skills/laporan-generator/references/metadata-schema.md +76 -0
  5. package/.agents/skills/laporan-generator/references/preset-schema.md +79 -0
  6. package/.agents/skills/laporan-generator/references/syntax-cheatsheet.md +122 -0
  7. package/.agents/skills/laporan-generator/references/template-guide.md +100 -0
  8. package/.agents/skills/laporan-generator/references/troubleshooting.md +105 -0
  9. package/.agents/skills/laporan-generator/resources/Makefile +90 -0
  10. package/.agents/skills/laporan-generator/resources/apa.csl +2273 -0
  11. package/.agents/skills/laporan-generator/resources/build-docx.sh +122 -0
  12. package/.agents/skills/laporan-generator/resources/build.sh +102 -0
  13. package/.agents/skills/laporan-generator/resources/chapters/bab1-pendahuluan.md +60 -0
  14. package/.agents/skills/laporan-generator/resources/chapters/bab2-tinjauan-pustaka.md +83 -0
  15. package/.agents/skills/laporan-generator/resources/chapters/bab3-metodologi.md +116 -0
  16. package/.agents/skills/laporan-generator/resources/chapters/bab4-hasil-dan-pembahasan.md +93 -0
  17. package/.agents/skills/laporan-generator/resources/chapters/bab5-penutup.md +27 -0
  18. package/.agents/skills/laporan-generator/resources/cover.md +50 -0
  19. package/.agents/skills/laporan-generator/resources/docx.lua +416 -0
  20. package/.agents/skills/laporan-generator/resources/laporan +464 -0
  21. package/.agents/skills/laporan-generator/resources/laporan.ps1 +552 -0
  22. package/.agents/skills/laporan-generator/resources/logo.jpg +0 -0
  23. package/.agents/skills/laporan-generator/resources/metadata.yml +35 -0
  24. package/.agents/skills/laporan-generator/resources/presets/itb-ta.yml +27 -0
  25. package/.agents/skills/laporan-generator/resources/presets/its-skripsi.yml +26 -0
  26. package/.agents/skills/laporan-generator/resources/presets/skripsi-4433.yml +26 -0
  27. package/.agents/skills/laporan-generator/resources/presets/standard.yml +26 -0
  28. package/.agents/skills/laporan-generator/resources/presets/ugm-skripsi.yml +26 -0
  29. package/.agents/skills/laporan-generator/resources/presets/ui-skripsi.yml +26 -0
  30. package/.agents/skills/laporan-generator/resources/presets/unpad-skripsi.yml +27 -0
  31. package/.agents/skills/laporan-generator/resources/reference.docx +0 -0
  32. package/.agents/skills/laporan-generator/resources/references.bib +115 -0
  33. package/.agents/skills/laporan-generator/resources/scripts/bundle.py +75 -0
  34. package/.agents/skills/laporan-generator/resources/scripts/docx-pagenum.py +192 -0
  35. package/.agents/skills/laporan-generator/resources/scripts/finalize-docx.py +291 -0
  36. package/.agents/skills/laporan-generator/resources/scripts/make-reference-docx.py +670 -0
  37. package/.agents/skills/laporan-generator/resources/scripts/report-doctor.py +211 -0
  38. package/.agents/skills/laporan-generator/resources/scripts/report-stats.py +149 -0
  39. package/.agents/skills/laporan-generator/resources/scripts/scan-preset.py +311 -0
  40. package/.agents/skills/laporan-generator/resources/scripts/setup-deps.ps1 +152 -0
  41. package/.agents/skills/laporan-generator/resources/scripts/setup-deps.sh +113 -0
  42. package/.agents/skills/laporan-generator/resources/scripts/test_scripts.py +128 -0
  43. package/.agents/skills/laporan-generator/resources/scripts/validate-preset.py +166 -0
  44. package/.agents/skills/laporan-generator/resources/template.typ +394 -0
  45. package/.agents/skills/laporan-generator/scripts/build.sh +78 -0
  46. package/.agents/skills/laporan-generator/scripts/bundle.py +75 -0
  47. package/.agents/skills/laporan-generator/scripts/docx-pagenum.py +192 -0
  48. package/.agents/skills/laporan-generator/scripts/finalize-docx.py +152 -0
  49. package/.agents/skills/laporan-generator/scripts/laporan +447 -0
  50. package/.agents/skills/laporan-generator/scripts/laporan.ps1 +529 -0
  51. package/.agents/skills/laporan-generator/scripts/make-reference-docx.py +630 -0
  52. package/.agents/skills/laporan-generator/scripts/report-doctor.py +211 -0
  53. package/.agents/skills/laporan-generator/scripts/report-stats.py +149 -0
  54. package/.agents/skills/laporan-generator/scripts/scan-preset.py +311 -0
  55. package/.agents/skills/laporan-generator/scripts/setup-deps.ps1 +152 -0
  56. package/.agents/skills/laporan-generator/scripts/setup-deps.sh +113 -0
  57. package/.agents/skills/laporan-generator/scripts/test_scripts.py +103 -0
  58. package/.agents/skills/laporan-generator/scripts/validate-preset.py +166 -0
  59. package/.agents/workflows/laporan-generator.md +8 -0
  60. package/LICENSE +21 -0
  61. package/Makefile +90 -0
  62. package/README.md +389 -0
  63. package/apa.csl +2273 -0
  64. package/bin/laporan-generator.js +71 -0
  65. package/build-docx.sh +122 -0
  66. package/build.sh +102 -0
  67. package/chapters/bab1-pendahuluan.md +60 -0
  68. package/chapters/bab2-tinjauan-pustaka.md +83 -0
  69. package/chapters/bab3-metodologi.md +116 -0
  70. package/chapters/bab4-hasil-dan-pembahasan.md +93 -0
  71. package/chapters/bab5-penutup.md +27 -0
  72. package/cover.md +50 -0
  73. package/docs/campus-guide.md +120 -0
  74. package/docs/metadata-schema.md +76 -0
  75. package/docs/preset-schema.md +79 -0
  76. package/docs/syntax-cheatsheet.md +122 -0
  77. package/docs/template-guide.md +100 -0
  78. package/docs/troubleshooting.md +105 -0
  79. package/docx.lua +416 -0
  80. package/laporan +464 -0
  81. package/laporan.ps1 +552 -0
  82. package/lib/init.js +118 -0
  83. package/lib/setup.js +33 -0
  84. package/lib/sync-hosts.js +194 -0
  85. package/lib/uninstall.js +123 -0
  86. package/logo.jpg +0 -0
  87. package/metadata.yml +35 -0
  88. package/package.json +65 -0
  89. package/presets/itb-ta.yml +27 -0
  90. package/presets/its-skripsi.yml +26 -0
  91. package/presets/skripsi-4433.yml +26 -0
  92. package/presets/standard.yml +26 -0
  93. package/presets/ugm-skripsi.yml +26 -0
  94. package/presets/ui-skripsi.yml +26 -0
  95. package/presets/unpad-skripsi.yml +27 -0
  96. package/reference.docx +0 -0
  97. package/references.bib +115 -0
  98. package/scripts/bundle.py +75 -0
  99. package/scripts/docx-pagenum.py +192 -0
  100. package/scripts/finalize-docx.py +291 -0
  101. package/scripts/make-reference-docx.py +670 -0
  102. package/scripts/report-doctor.py +211 -0
  103. package/scripts/report-stats.py +149 -0
  104. package/scripts/scan-preset.py +311 -0
  105. package/scripts/setup-deps.ps1 +152 -0
  106. package/scripts/setup-deps.sh +113 -0
  107. package/scripts/test_scripts.py +128 -0
  108. package/scripts/validate-preset.py +166 -0
  109. package/template.typ +394 -0
@@ -0,0 +1,670 @@
1
+ #!/usr/bin/env python3
2
+ """Generate reference.docx untuk pandoc --reference-doc.
3
+
4
+ Memodifikasi reference.docx bawaan pandoc agar gaya dokumen Word
5
+ mengikuti pedoman laporan akademik:
6
+
7
+ - Ukuran halaman A4, margin atas 2cm / bawah 3cm / kiri-kanan 2.5cm
8
+ - Normal (teks isi): Times New Roman 12pt, justify, spasi 1.5
9
+ - Heading 1 (judul BAB): Times New Roman 14pt bold, rata tengah, hitam
10
+ - Heading 2/3 (sub-bab): Times New Roman 12pt bold, rata kiri, hitam
11
+ - Title/Subtitle/Author/Date: Times New Roman, rata tengah, hitam
12
+
13
+ Usage:
14
+ python3 scripts/make-reference-docx.py [input.docx] [output.docx]
15
+
16
+ input.docx - hasil `pandoc --print-default-data-file reference.docx`
17
+ output.docx - reference.docx hasil styling (default: reference.docx)
18
+ """
19
+
20
+ import re
21
+ import sys
22
+ import zipfile
23
+
24
+ TNR = '<w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman"/>'
25
+
26
+ STYLES = {
27
+ "Normal": f"""<w:style w:type="paragraph" w:styleId="Normal">
28
+ <w:name w:val="Normal"/>
29
+ <w:qFormat/>
30
+ <w:pPr>
31
+ <w:spacing w:after="0" w:line="360" w:lineRule="auto"/>
32
+ <w:jc w:val="both"/>
33
+ </w:pPr>
34
+ <w:rPr>
35
+ {TNR}
36
+ <w:sz w:val="24"/>
37
+ <w:szCs w:val="24"/>
38
+ </w:rPr>
39
+ </w:style>""",
40
+ "BodyText": f"""<w:style w:type="paragraph" w:styleId="BodyText">
41
+ <w:name w:val="Body Text"/>
42
+ <w:basedOn w:val="Normal"/>
43
+ <w:link w:val="BodyTextChar"/>
44
+ <w:qFormat/>
45
+ <w:pPr>
46
+ <w:spacing w:after="0" w:line="360" w:lineRule="auto"/>
47
+ <w:ind w:firstLine="709"/>
48
+ <w:jc w:val="both"/>
49
+ </w:pPr>
50
+ <w:rPr>
51
+ {TNR}
52
+ <w:sz w:val="24"/>
53
+ <w:szCs w:val="24"/>
54
+ </w:rPr>
55
+ </w:style>""",
56
+ "FirstParagraph": f"""<w:style w:type="paragraph" w:styleId="FirstParagraph">
57
+ <w:name w:val="First Paragraph"/>
58
+ <w:basedOn w:val="BodyText"/>
59
+ <w:link w:val="BodyTextChar"/>
60
+ <w:qFormat/>
61
+ <w:pPr>
62
+ <w:spacing w:after="0" w:line="360" w:lineRule="auto"/>
63
+ <w:ind w:firstLine="709"/>
64
+ <w:jc w:val="both"/>
65
+ </w:pPr>
66
+ <w:rPr>
67
+ {TNR}
68
+ <w:sz w:val="24"/>
69
+ <w:szCs w:val="24"/>
70
+ </w:rPr>
71
+ </w:style>""",
72
+ "Heading1": f"""<w:style w:type="paragraph" w:styleId="Heading1">
73
+ <w:name w:val="heading 1"/>
74
+ <w:basedOn w:val="Normal"/>
75
+ <w:next w:val="BodyText"/>
76
+ <w:link w:val="Heading1Char"/>
77
+ <w:uiPriority w:val="9"/>
78
+ <w:qFormat/>
79
+ <w:pPr>
80
+ <w:keepNext/>
81
+ <w:keepLines/>
82
+ <w:spacing w:before="360" w:after="720"/>
83
+ <w:jc w:val="center"/>
84
+ <w:outlineLvl w:val="0"/>
85
+ </w:pPr>
86
+ <w:rPr>
87
+ {TNR}
88
+ <w:color w:val="000000"/>
89
+ <w:sz w:val="28"/>
90
+ <w:szCs w:val="28"/>
91
+ <w:b/>
92
+ <w:bCs/>
93
+ </w:rPr>
94
+ </w:style>""",
95
+ "Heading2": f"""<w:style w:type="paragraph" w:styleId="Heading2">
96
+ <w:name w:val="heading 2"/>
97
+ <w:basedOn w:val="Normal"/>
98
+ <w:next w:val="BodyText"/>
99
+ <w:link w:val="Heading2Char"/>
100
+ <w:uiPriority w:val="9"/>
101
+ <w:qFormat/>
102
+ <w:pPr>
103
+ <w:keepNext/>
104
+ <w:keepLines/>
105
+ <w:spacing w:before="160" w:after="80"/>
106
+ <w:outlineLvl w:val="1"/>
107
+ </w:pPr>
108
+ <w:rPr>
109
+ {TNR}
110
+ <w:color w:val="000000"/>
111
+ <w:sz w:val="24"/>
112
+ <w:szCs w:val="24"/>
113
+ <w:b/>
114
+ <w:bCs/>
115
+ </w:rPr>
116
+ </w:style>""",
117
+ "Heading3": f"""<w:style w:type="paragraph" w:styleId="Heading3">
118
+ <w:name w:val="heading 3"/>
119
+ <w:basedOn w:val="Normal"/>
120
+ <w:next w:val="BodyText"/>
121
+ <w:link w:val="Heading3Char"/>
122
+ <w:uiPriority w:val="9"/>
123
+ <w:qFormat/>
124
+ <w:pPr>
125
+ <w:keepNext/>
126
+ <w:keepLines/>
127
+ <w:spacing w:before="160" w:after="80"/>
128
+ <w:outlineLvl w:val="2"/>
129
+ </w:pPr>
130
+ <w:rPr>
131
+ {TNR}
132
+ <w:color w:val="000000"/>
133
+ <w:sz w:val="24"/>
134
+ <w:szCs w:val="24"/>
135
+ <w:b/>
136
+ <w:bCs/>
137
+ </w:rPr>
138
+ </w:style>""",
139
+ "Title": f"""<w:style w:type="paragraph" w:styleId="Title">
140
+ <w:name w:val="Title"/>
141
+ <w:basedOn w:val="Normal"/>
142
+ <w:next w:val="BodyText"/>
143
+ <w:link w:val="TitleChar"/>
144
+ <w:uiPriority w:val="10"/>
145
+ <w:qFormat/>
146
+ <w:pPr>
147
+ <w:spacing w:after="80" w:line="240" w:lineRule="auto"/>
148
+ <w:jc w:val="center"/>
149
+ </w:pPr>
150
+ <w:rPr>
151
+ {TNR}
152
+ <w:color w:val="000000"/>
153
+ <w:sz w:val="28"/>
154
+ <w:szCs w:val="28"/>
155
+ <w:b/>
156
+ <w:bCs/>
157
+ </w:rPr>
158
+ </w:style>""",
159
+ "Subtitle": f"""<w:style w:type="paragraph" w:styleId="Subtitle">
160
+ <w:name w:val="Subtitle"/>
161
+ <w:basedOn w:val="Title"/>
162
+ <w:next w:val="BodyText"/>
163
+ <w:link w:val="SubtitleChar"/>
164
+ <w:uiPriority w:val="11"/>
165
+ <w:qFormat/>
166
+ <w:pPr>
167
+ <w:spacing w:after="80" w:line="240" w:lineRule="auto"/>
168
+ <w:jc w:val="center"/>
169
+ </w:pPr>
170
+ <w:rPr>
171
+ {TNR}
172
+ <w:color w:val="000000"/>
173
+ <w:sz w:val="24"/>
174
+ <w:szCs w:val="24"/>
175
+ <w:b/>
176
+ <w:bCs/>
177
+ </w:rPr>
178
+ </w:style>""",
179
+ "Author": f"""<w:style w:type="paragraph" w:styleId="Author">
180
+ <w:name w:val="Author"/>
181
+ <w:basedOn w:val="Title"/>
182
+ <w:next w:val="BodyText"/>
183
+ <w:uiPriority w:val="9"/>
184
+ <w:qFormat/>
185
+ <w:pPr>
186
+ <w:keepNext/>
187
+ <w:keepLines/>
188
+ <w:jc w:val="center"/>
189
+ </w:pPr>
190
+ <w:rPr>
191
+ {TNR}
192
+ <w:color w:val="000000"/>
193
+ <w:sz w:val="24"/>
194
+ <w:szCs w:val="24"/>
195
+ </w:rPr>
196
+ </w:style>""",
197
+ "Date": f"""<w:style w:type="paragraph" w:styleId="Date">
198
+ <w:name w:val="Date"/>
199
+ <w:basedOn w:val="Title"/>
200
+ <w:next w:val="BodyText"/>
201
+ <w:uiPriority w:val="9"/>
202
+ <w:qFormat/>
203
+ <w:pPr>
204
+ <w:keepNext/>
205
+ <w:keepLines/>
206
+ <w:jc w:val="center"/>
207
+ </w:pPr>
208
+ <w:rPr>
209
+ {TNR}
210
+ <w:color w:val="000000"/>
211
+ <w:sz w:val="24"/>
212
+ <w:szCs w:val="24"/>
213
+ </w:rPr>
214
+ </w:style>""",
215
+ "AbstractTitle": f"""<w:style w:type="paragraph" w:styleId="AbstractTitle">
216
+ <w:name w:val="Abstract Title"/>
217
+ <w:basedOn w:val="Normal"/>
218
+ <w:next w:val="Abstract"/>
219
+ <w:qFormat/>
220
+ <w:pPr>
221
+ <w:keepNext/>
222
+ <w:keepLines/>
223
+ <w:spacing w:before="300" w:after="0"/>
224
+ <w:jc w:val="center"/>
225
+ </w:pPr>
226
+ <w:rPr>
227
+ {TNR}
228
+ <w:color w:val="000000"/>
229
+ <w:sz w:val="24"/>
230
+ <w:szCs w:val="24"/>
231
+ <w:b/>
232
+ <w:bCs/>
233
+ </w:rPr>
234
+ </w:style>""",
235
+ "Abstract": f"""<w:style w:type="paragraph" w:styleId="Abstract">
236
+ <w:name w:val="Abstract"/>
237
+ <w:basedOn w:val="Normal"/>
238
+ <w:next w:val="BodyText"/>
239
+ <w:qFormat/>
240
+ <w:pPr>
241
+ <w:keepNext/>
242
+ <w:keepLines/>
243
+ <w:spacing w:before="100" w:after="300"/>
244
+ <w:jc w:val="both"/>
245
+ </w:pPr>
246
+ <w:rPr>
247
+ {TNR}
248
+ <w:color w:val="000000"/>
249
+ <w:sz w:val="24"/>
250
+ <w:szCs w:val="24"/>
251
+ </w:rPr>
252
+ </w:style>""",
253
+ "Compact": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="Compact">
254
+ <w:name w:val="Compact"/>
255
+ <w:basedOn w:val="Normal"/>
256
+ <w:qFormat/>
257
+ <w:pPr>
258
+ <w:spacing w:before="60" w:after="60" w:line="240" w:lineRule="auto"/>
259
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
260
+ <w:jc w:val="left"/>
261
+ </w:pPr>
262
+ <w:rPr>
263
+ {TNR}
264
+ <w:sz w:val="24"/>
265
+ <w:szCs w:val="24"/>
266
+ </w:rPr>
267
+ </w:style>""",
268
+ "SourceCode": f"""<w:style w:type="paragraph" w:styleId="SourceCode">
269
+ <w:name w:val="Source Code"/>
270
+ <w:basedOn w:val="Normal"/>
271
+ <w:qFormat/>
272
+ <w:pPr>
273
+ <w:spacing w:before="120" w:after="120" w:line="240" w:lineRule="auto"/>
274
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
275
+ <w:jc w:val="left"/>
276
+ </w:pPr>
277
+ <w:rPr>
278
+ <w:rFonts w:ascii="DejaVu Sans Mono" w:hAnsi="DejaVu Sans Mono" w:cs="DejaVu Sans Mono"/>
279
+ <w:sz w:val="18"/>
280
+ <w:szCs w:val="18"/>
281
+ </w:rPr>
282
+ </w:style>""",
283
+ "ImageCaption": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="ImageCaption">
284
+ <w:name w:val="Image Caption"/>
285
+ <w:basedOn w:val="Normal"/>
286
+ <w:qFormat/>
287
+ <w:pPr>
288
+ <w:spacing w:before="120" w:after="240" w:line="240" w:lineRule="auto"/>
289
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
290
+ <w:jc w:val="center"/>
291
+ </w:pPr>
292
+ <w:rPr>
293
+ {TNR}
294
+ <w:sz w:val="24"/>
295
+ <w:szCs w:val="24"/>
296
+ <w:i/>
297
+ </w:rPr>
298
+ </w:style>""",
299
+ "TableCaption": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="TableCaption">
300
+ <w:name w:val="Table Caption"/>
301
+ <w:basedOn w:val="Normal"/>
302
+ <w:qFormat/>
303
+ <w:pPr>
304
+ <w:keepNext/>
305
+ <w:spacing w:before="240" w:after="120" w:line="240" w:lineRule="auto"/>
306
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
307
+ <w:jc w:val="left"/>
308
+ </w:pPr>
309
+ <w:rPr>
310
+ {TNR}
311
+ <w:sz w:val="24"/>
312
+ <w:szCs w:val="24"/>
313
+ <w:i/>
314
+ </w:rPr>
315
+ </w:style>""",
316
+ "BlockText": f"""<w:style w:type="paragraph" w:styleId="BlockText">
317
+ <w:name w:val="Block Text"/>
318
+ <w:basedOn w:val="Normal"/>
319
+ <w:next w:val="Normal"/>
320
+ <w:qFormat/>
321
+ <w:pPr>
322
+ <w:spacing w:before="120" w:after="120" w:line="240" w:lineRule="auto"/>
323
+ <w:ind w:left="720" w:right="720" w:firstLine="0"/>
324
+ <w:jc w:val="both"/>
325
+ </w:pPr>
326
+ <w:rPr>
327
+ {TNR}
328
+ <w:sz w:val="24"/>
329
+ <w:szCs w:val="24"/>
330
+ <w:i/>
331
+ </w:rPr>
332
+ </w:style>""",
333
+ "TOCHeading": f"""<w:style w:type="paragraph" w:styleId="TOCHeading">
334
+ <w:name w:val="TOC Heading"/>
335
+ <w:basedOn w:val="Normal"/>
336
+ <w:next w:val="Normal"/>
337
+ <w:uiPriority w:val="39"/>
338
+ <w:qFormat/>
339
+ <w:pPr>
340
+ <w:spacing w:before="360" w:after="360" w:line="240" w:lineRule="auto"/>
341
+ <w:jc w:val="center"/>
342
+ <w:outlineLvl w:val="9"/>
343
+ </w:pPr>
344
+ <w:rPr>
345
+ {TNR}
346
+ <w:color w:val="000000"/>
347
+ <w:sz w:val="28"/>
348
+ <w:szCs w:val="28"/>
349
+ <w:b/>
350
+ <w:bCs/>
351
+ </w:rPr>
352
+ </w:style>""",
353
+ "TOC1": f"""<w:style w:type="paragraph" w:styleId="TOC1">
354
+ <w:name w:val="toc 1"/>
355
+ <w:basedOn w:val="Normal"/>
356
+ <w:next w:val="Normal"/>
357
+ <w:qFormat/>
358
+ <w:pPr>
359
+ <w:tabs>
360
+ <w:tab w:val="right" w:leader="dot" w:pos="9072"/>
361
+ </w:tabs>
362
+ <w:spacing w:before="120" w:after="40" w:line="260" w:lineRule="auto"/>
363
+ <w:ind w:left="0" w:right="0"/>
364
+ <w:jc w:val="left"/>
365
+ </w:pPr>
366
+ <w:rPr>
367
+ {TNR}
368
+ <w:color w:val="000000"/>
369
+ <w:sz w:val="24"/>
370
+ <w:szCs w:val="24"/>
371
+ <w:b/>
372
+ <w:bCs/>
373
+ </w:rPr>
374
+ </w:style>""",
375
+ "TOC2": f"""<w:style w:type="paragraph" w:styleId="TOC2">
376
+ <w:name w:val="toc 2"/>
377
+ <w:basedOn w:val="TOC1"/>
378
+ <w:next w:val="Normal"/>
379
+ <w:qFormat/>
380
+ <w:pPr>
381
+ <w:tabs>
382
+ <w:tab w:val="right" w:leader="dot" w:pos="9072"/>
383
+ </w:tabs>
384
+ <w:spacing w:before="20" w:after="20" w:line="240" w:lineRule="auto"/>
385
+ <w:ind w:left="360" w:right="0"/>
386
+ <w:jc w:val="left"/>
387
+ </w:pPr>
388
+ <w:rPr>
389
+ {TNR}
390
+ <w:color w:val="000000"/>
391
+ <w:sz w:val="24"/>
392
+ <w:szCs w:val="24"/>
393
+ <w:b w:val="0"/>
394
+ <w:bCs w:val="0"/>
395
+ </w:rPr>
396
+ </w:style>""",
397
+ "TOC3": f"""<w:style w:type="paragraph" w:styleId="TOC3">
398
+ <w:name w:val="toc 3"/>
399
+ <w:basedOn w:val="TOC2"/>
400
+ <w:next w:val="Normal"/>
401
+ <w:qFormat/>
402
+ <w:pPr>
403
+ <w:tabs>
404
+ <w:tab w:val="right" w:leader="dot" w:pos="9072"/>
405
+ </w:tabs>
406
+ <w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
407
+ <w:ind w:left="720" w:right="0"/>
408
+ <w:jc w:val="left"/>
409
+ </w:pPr>
410
+ <w:rPr>
411
+ {TNR}
412
+ <w:color w:val="000000"/>
413
+ <w:sz w:val="24"/>
414
+ <w:szCs w:val="24"/>
415
+ <w:b w:val="0"/>
416
+ <w:bCs w:val="0"/>
417
+ </w:rPr>
418
+ </w:style>""",
419
+ "CoverImage": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverImage">
420
+ <w:name w:val="CoverImage"/>
421
+ <w:basedOn w:val="Normal"/>
422
+ <w:qFormat/>
423
+ <w:pPr>
424
+ <w:spacing w:after="0"/>
425
+ <w:jc w:val="center"/>
426
+ </w:pPr>
427
+ </w:style>""",
428
+ "CoverTitle": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverTitle">
429
+ <w:name w:val="CoverTitle"/>
430
+ <w:basedOn w:val="Normal"/>
431
+ <w:qFormat/>
432
+ <w:pPr>
433
+ <w:spacing w:before="567" w:after="0" w:line="300" w:lineRule="auto"/>
434
+ <w:jc w:val="center"/>
435
+ </w:pPr>
436
+ <w:rPr>
437
+ {TNR}
438
+ <w:color w:val="000000"/>
439
+ <w:sz w:val="28"/>
440
+ <w:szCs w:val="28"/>
441
+ <w:b/>
442
+ <w:bCs/>
443
+ </w:rPr>
444
+ </w:style>""",
445
+ "CoverSubtitle": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverSubtitle">
446
+ <w:name w:val="CoverSubtitle"/>
447
+ <w:basedOn w:val="Normal"/>
448
+ <w:qFormat/>
449
+ <w:pPr>
450
+ <w:spacing w:before="170" w:after="0" w:line="300" w:lineRule="auto"/>
451
+ <w:jc w:val="center"/>
452
+ </w:pPr>
453
+ <w:rPr>
454
+ {TNR}
455
+ <w:color w:val="000000"/>
456
+ <w:sz w:val="28"/>
457
+ <w:szCs w:val="28"/>
458
+ <w:b/>
459
+ <w:bCs/>
460
+ </w:rPr>
461
+ </w:style>""",
462
+ "CoverCourse": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverCourse">
463
+ <w:name w:val="CoverCourse"/>
464
+ <w:basedOn w:val="CoverLine"/>
465
+ <w:qFormat/>
466
+ <w:pPr>
467
+ <w:spacing w:before="454" w:after="0" w:line="300" w:lineRule="auto"/>
468
+ </w:pPr>
469
+ </w:style>""",
470
+ "CoverLecturer": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverLecturer">
471
+ <w:name w:val="CoverLecturer"/>
472
+ <w:basedOn w:val="CoverLine"/>
473
+ <w:qFormat/>
474
+ <w:pPr>
475
+ <w:spacing w:before="227" w:after="0" w:line="300" w:lineRule="auto"/>
476
+ </w:pPr>
477
+ </w:style>""",
478
+ "CoverName": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverName">
479
+ <w:name w:val="CoverName"/>
480
+ <w:basedOn w:val="CoverLine"/>
481
+ <w:qFormat/>
482
+ <w:pPr>
483
+ <w:spacing w:before="170" w:after="0" w:line="300" w:lineRule="auto"/>
484
+ </w:pPr>
485
+ </w:style>""",
486
+ "CoverLine": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverLine">
487
+ <w:name w:val="CoverLine"/>
488
+ <w:basedOn w:val="Normal"/>
489
+ <w:qFormat/>
490
+ <w:pPr>
491
+ <w:spacing w:after="0" w:line="300" w:lineRule="auto"/>
492
+ <w:jc w:val="center"/>
493
+ </w:pPr>
494
+ <w:rPr>
495
+ {TNR}
496
+ <w:color w:val="000000"/>
497
+ <w:sz w:val="24"/>
498
+ <w:szCs w:val="24"/>
499
+ </w:rPr>
500
+ </w:style>""",
501
+ "CoverInstitution": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverInstitution">
502
+ <w:name w:val="CoverInstitution"/>
503
+ <w:basedOn w:val="Normal"/>
504
+ <w:qFormat/>
505
+ <w:pPr>
506
+ <w:spacing w:after="0" w:line="300" w:lineRule="auto"/>
507
+ <w:jc w:val="center"/>
508
+ </w:pPr>
509
+ <w:rPr>
510
+ {TNR}
511
+ <w:color w:val="000000"/>
512
+ <w:sz w:val="28"/>
513
+ <w:szCs w:val="28"/>
514
+ <w:b/>
515
+ <w:bCs/>
516
+ </w:rPr>
517
+ </w:style>""",
518
+ "Bibliography": f"""<w:style w:type="paragraph" w:styleId="Bibliography">
519
+ <w:name w:val="Bibliography"/>
520
+ <w:basedOn w:val="Normal"/>
521
+ <w:qFormat/>
522
+ <w:pPr>
523
+ <w:spacing w:after="120" w:line="360" w:lineRule="auto"/>
524
+ <w:ind w:left="709" w:hanging="709"/>
525
+ <w:jc w:val="both"/>
526
+ </w:pPr>
527
+ <w:rPr>
528
+ {TNR}
529
+ <w:sz w:val="24"/>
530
+ <w:szCs w:val="24"/>
531
+ </w:rPr>
532
+ </w:style>""",
533
+ "Table": f"""<w:style w:type="table" w:styleId="Table">
534
+ <w:name w:val="Table"/>
535
+ <w:basedOn w:val="TableNormal"/>
536
+ <w:uiPriority w:val="59"/>
537
+ <w:qFormat/>
538
+ <w:tblPr>
539
+ <w:tblInd w:type="dxa" w:w="0"/>
540
+ <w:tblBorders>
541
+ <w:top w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
542
+ <w:left w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
543
+ <w:bottom w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
544
+ <w:right w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
545
+ <w:insideH w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
546
+ <w:insideV w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
547
+ </w:tblBorders>
548
+ <w:tblCellMar>
549
+ <w:top w:type="dxa" w:w="80"/>
550
+ <w:left w:type="dxa" w:w="120"/>
551
+ <w:bottom w:type="dxa" w:w="80"/>
552
+ <w:right w:type="dxa" w:w="120"/>
553
+ </w:tblCellMar>
554
+ </w:tblPr>
555
+ <w:tblStylePr w:type="firstRow">
556
+ <w:pPr>
557
+ <w:jc w:val="left"/>
558
+ <w:spacing w:before="60" w:after="60" w:line="240" w:lineRule="auto"/>
559
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
560
+ </w:pPr>
561
+ <w:rPr>
562
+ <w:b/>
563
+ <w:bCs/>
564
+ </w:rPr>
565
+ <w:tcPr>
566
+ <w:vAlign w:val="center"/>
567
+ </w:tcPr>
568
+ </w:tblStylePr>
569
+ <w:tblStylePr w:type="lastRow"/>
570
+ <w:tblStylePr w:type="firstCol"/>
571
+ <w:tblStylePr w:type="lastCol"/>
572
+ <w:tblStylePr w:type="band1Vert"/>
573
+ <w:tblStylePr w:type="band2Vert"/>
574
+ <w:tblStylePr w:type="band1Horz"/>
575
+ <w:tblStylePr w:type="band2Horz"/>
576
+ </w:style>""",
577
+ }
578
+
579
+ SECTPR = """<w:sectPr>
580
+ <w:footerReference r:id="rIdF1" w:type="default"/>
581
+ <w:footnotePr>
582
+ <w:numRestart w:val="eachSect"/>
583
+ </w:footnotePr>
584
+ <w:pgSz w:w="11906" w:h="16838"/>
585
+ <w:pgMar w:top="1134" w:right="1417" w:bottom="1701" w:left="1417" w:header="720" w:footer="720" w:gutter="0"/>
586
+ </w:sectPr>"""
587
+
588
+ FOOTER1 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
589
+ <w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
590
+ <w:p>
591
+ <w:pPr><w:jc w:val="center"/></w:pPr>
592
+ <w:r><w:fldChar w:fldCharType="begin"/></w:r>
593
+ <w:r><w:instrText xml:space="preserve"> PAGE </w:instrText></w:r>
594
+ <w:r><w:fldChar w:fldCharType="separate"/></w:r>
595
+ <w:r><w:t>1</w:t></w:r>
596
+ <w:r><w:fldChar w:fldCharType="end"/></w:r>
597
+ </w:p>
598
+ </w:ftr>"""
599
+
600
+
601
+ def main():
602
+ src = sys.argv[1] if len(sys.argv) > 1 else "/tmp/ref-default.docx"
603
+ dst = sys.argv[2] if len(sys.argv) > 2 else "reference.docx"
604
+
605
+ with zipfile.ZipFile(src, "r") as zin:
606
+ names = zin.namelist()
607
+ items = {n: zin.read(n) for n in names}
608
+
609
+ styles = items["word/styles.xml"].decode("utf-8")
610
+ missing = []
611
+ for style_id, block in STYLES.items():
612
+ pattern = re.compile(
613
+ rf'<w:style\b[^>]*w:styleId="{style_id}"[^>]*>.*?</w:style>',
614
+ re.S,
615
+ )
616
+ if pattern.search(styles):
617
+ styles = pattern.sub(block, styles)
618
+ else:
619
+ missing.append(style_id)
620
+ if missing:
621
+ styles = styles.replace("</w:styles>", "".join(STYLES[s] for s in missing) + "</w:styles>")
622
+ print(f"[add] style baru ditambahkan: {', '.join(missing)}")
623
+ items["word/styles.xml"] = styles.encode("utf-8")
624
+
625
+ doc = items["word/document.xml"].decode("utf-8")
626
+ if re.search(r"<w:sectPr>.*?</w:sectPr>", doc, re.S):
627
+ doc = re.sub(r"<w:sectPr>.*?</w:sectPr>", SECTPR, doc, flags=re.S)
628
+ else:
629
+ print("[warn] sectPr tidak ditemukan di document.xml")
630
+ items["word/document.xml"] = doc.encode("utf-8")
631
+
632
+ settings = items["word/settings.xml"].decode("utf-8")
633
+ if "<w:updateFields" not in settings:
634
+ settings = settings.replace(
635
+ "</w:settings>", '<w:updateFields w:val="true"/></w:settings>'
636
+ )
637
+ print("[add] updateFields diaktifkan di settings.xml")
638
+ items["word/settings.xml"] = settings.encode("utf-8")
639
+
640
+ if "word/footer1.xml" not in items:
641
+ items["word/footer1.xml"] = FOOTER1.encode("utf-8")
642
+ ct = items["[Content_Types].xml"].decode("utf-8")
643
+ if "footer1.xml" not in ct:
644
+ ct = ct.replace(
645
+ "</Types>",
646
+ '<Override PartName="/word/footer1.xml" '
647
+ 'ContentType="application/vnd.openxmlformats-officedocument.'
648
+ 'wordprocessingml.footer+xml"/></Types>',
649
+ )
650
+ items["[Content_Types].xml"] = ct.encode("utf-8")
651
+ rels = items["word/_rels/document.xml.rels"].decode("utf-8")
652
+ if 'Id="rIdF1"' not in rels:
653
+ rels = rels.replace(
654
+ "</Relationships>",
655
+ '<Relationship Id="rIdF1" '
656
+ 'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" '
657
+ 'Target="footer1.xml"/></Relationships>',
658
+ )
659
+ items["word/_rels/document.xml.rels"] = rels.encode("utf-8")
660
+ print("[add] footer1.xml (nomor halaman PAGE) + rels + content-types")
661
+
662
+ with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zout:
663
+ for n, content in items.items():
664
+ zout.writestr(n, content)
665
+
666
+ print(f"[OK] reference.docx dibuat: {dst}")
667
+
668
+
669
+ if __name__ == "__main__":
670
+ main()