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,630 @@
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
+ "TOC1": f"""<w:style w:type="paragraph" w:styleId="TOC1">
334
+ <w:name w:val="toc 1"/>
335
+ <w:basedOn w:val="Normal"/>
336
+ <w:next w:val="Normal"/>
337
+ <w:qFormat/>
338
+ <w:pPr>
339
+ <w:spacing w:before="60" w:after="20" w:line="260" w:lineRule="auto"/>
340
+ <w:jc w:val="left"/>
341
+ </w:pPr>
342
+ <w:rPr>
343
+ {TNR}
344
+ <w:color w:val="000000"/>
345
+ <w:sz w:val="24"/>
346
+ <w:szCs w:val="24"/>
347
+ <w:b/>
348
+ <w:bCs/>
349
+ </w:rPr>
350
+ </w:style>""",
351
+ "TOC2": f"""<w:style w:type="paragraph" w:styleId="TOC2">
352
+ <w:name w:val="toc 2"/>
353
+ <w:basedOn w:val="TOC1"/>
354
+ <w:next w:val="Normal"/>
355
+ <w:qFormat/>
356
+ <w:pPr>
357
+ <w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
358
+ <w:jc w:val="left"/>
359
+ </w:pPr>
360
+ <w:rPr>
361
+ <w:b w:val="0"/>
362
+ <w:bCs w:val="0"/>
363
+ </w:rPr>
364
+ </w:style>""",
365
+ "TOC3": f"""<w:style w:type="paragraph" w:styleId="TOC3">
366
+ <w:name w:val="toc 3"/>
367
+ <w:basedOn w:val="TOC2"/>
368
+ <w:next w:val="Normal"/>
369
+ <w:qFormat/>
370
+ <w:pPr>
371
+ <w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
372
+ <w:jc w:val="left"/>
373
+ </w:pPr>
374
+ <w:rPr>
375
+ <w:b w:val="0"/>
376
+ <w:bCs w:val="0"/>
377
+ </w:rPr>
378
+ </w:style>""",
379
+ "CoverImage": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverImage">
380
+ <w:name w:val="CoverImage"/>
381
+ <w:basedOn w:val="Normal"/>
382
+ <w:qFormat/>
383
+ <w:pPr>
384
+ <w:spacing w:after="0"/>
385
+ <w:jc w:val="center"/>
386
+ </w:pPr>
387
+ </w:style>""",
388
+ "CoverTitle": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverTitle">
389
+ <w:name w:val="CoverTitle"/>
390
+ <w:basedOn w:val="Normal"/>
391
+ <w:qFormat/>
392
+ <w:pPr>
393
+ <w:spacing w:before="567" w:after="0" w:line="300" w:lineRule="auto"/>
394
+ <w:jc w:val="center"/>
395
+ </w:pPr>
396
+ <w:rPr>
397
+ {TNR}
398
+ <w:color w:val="000000"/>
399
+ <w:sz w:val="28"/>
400
+ <w:szCs w:val="28"/>
401
+ <w:b/>
402
+ <w:bCs/>
403
+ </w:rPr>
404
+ </w:style>""",
405
+ "CoverSubtitle": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverSubtitle">
406
+ <w:name w:val="CoverSubtitle"/>
407
+ <w:basedOn w:val="Normal"/>
408
+ <w:qFormat/>
409
+ <w:pPr>
410
+ <w:spacing w:before="170" w:after="0" w:line="300" w:lineRule="auto"/>
411
+ <w:jc w:val="center"/>
412
+ </w:pPr>
413
+ <w:rPr>
414
+ {TNR}
415
+ <w:color w:val="000000"/>
416
+ <w:sz w:val="28"/>
417
+ <w:szCs w:val="28"/>
418
+ <w:b/>
419
+ <w:bCs/>
420
+ </w:rPr>
421
+ </w:style>""",
422
+ "CoverCourse": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverCourse">
423
+ <w:name w:val="CoverCourse"/>
424
+ <w:basedOn w:val="CoverLine"/>
425
+ <w:qFormat/>
426
+ <w:pPr>
427
+ <w:spacing w:before="454" w:after="0" w:line="300" w:lineRule="auto"/>
428
+ </w:pPr>
429
+ </w:style>""",
430
+ "CoverLecturer": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverLecturer">
431
+ <w:name w:val="CoverLecturer"/>
432
+ <w:basedOn w:val="CoverLine"/>
433
+ <w:qFormat/>
434
+ <w:pPr>
435
+ <w:spacing w:before="227" w:after="0" w:line="300" w:lineRule="auto"/>
436
+ </w:pPr>
437
+ </w:style>""",
438
+ "CoverName": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverName">
439
+ <w:name w:val="CoverName"/>
440
+ <w:basedOn w:val="CoverLine"/>
441
+ <w:qFormat/>
442
+ <w:pPr>
443
+ <w:spacing w:before="170" w:after="0" w:line="300" w:lineRule="auto"/>
444
+ </w:pPr>
445
+ </w:style>""",
446
+ "CoverLine": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverLine">
447
+ <w:name w:val="CoverLine"/>
448
+ <w:basedOn w:val="Normal"/>
449
+ <w:qFormat/>
450
+ <w:pPr>
451
+ <w:spacing w:after="0" w:line="300" w:lineRule="auto"/>
452
+ <w:jc w:val="center"/>
453
+ </w:pPr>
454
+ <w:rPr>
455
+ {TNR}
456
+ <w:color w:val="000000"/>
457
+ <w:sz w:val="24"/>
458
+ <w:szCs w:val="24"/>
459
+ </w:rPr>
460
+ </w:style>""",
461
+ "CoverInstitution": f"""<w:style w:type="paragraph" w:customStyle="1" w:styleId="CoverInstitution">
462
+ <w:name w:val="CoverInstitution"/>
463
+ <w:basedOn w:val="Normal"/>
464
+ <w:qFormat/>
465
+ <w:pPr>
466
+ <w:spacing w:after="0" w:line="300" w:lineRule="auto"/>
467
+ <w:jc w:val="center"/>
468
+ </w:pPr>
469
+ <w:rPr>
470
+ {TNR}
471
+ <w:color w:val="000000"/>
472
+ <w:sz w:val="28"/>
473
+ <w:szCs w:val="28"/>
474
+ <w:b/>
475
+ <w:bCs/>
476
+ </w:rPr>
477
+ </w:style>""",
478
+ "Bibliography": f"""<w:style w:type="paragraph" w:styleId="Bibliography">
479
+ <w:name w:val="Bibliography"/>
480
+ <w:basedOn w:val="Normal"/>
481
+ <w:qFormat/>
482
+ <w:pPr>
483
+ <w:spacing w:after="120" w:line="360" w:lineRule="auto"/>
484
+ <w:ind w:left="709" w:hanging="709"/>
485
+ <w:jc w:val="both"/>
486
+ </w:pPr>
487
+ <w:rPr>
488
+ {TNR}
489
+ <w:sz w:val="24"/>
490
+ <w:szCs w:val="24"/>
491
+ </w:rPr>
492
+ </w:style>""",
493
+ "Table": f"""<w:style w:type="table" w:styleId="Table">
494
+ <w:name w:val="Table"/>
495
+ <w:basedOn w:val="TableNormal"/>
496
+ <w:uiPriority w:val="59"/>
497
+ <w:qFormat/>
498
+ <w:tblPr>
499
+ <w:tblInd w:type="dxa" w:w="0"/>
500
+ <w:tblBorders>
501
+ <w:top w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
502
+ <w:left w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
503
+ <w:bottom w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
504
+ <w:right w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
505
+ <w:insideH w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
506
+ <w:insideV w:val="single" w:sz="4" w:space="0" w:color="8C8C8C"/>
507
+ </w:tblBorders>
508
+ <w:tblCellMar>
509
+ <w:top w:type="dxa" w:w="80"/>
510
+ <w:left w:type="dxa" w:w="120"/>
511
+ <w:bottom w:type="dxa" w:w="80"/>
512
+ <w:right w:type="dxa" w:w="120"/>
513
+ </w:tblCellMar>
514
+ </w:tblPr>
515
+ <w:tblStylePr w:type="firstRow">
516
+ <w:pPr>
517
+ <w:jc w:val="left"/>
518
+ <w:spacing w:before="60" w:after="60" w:line="240" w:lineRule="auto"/>
519
+ <w:ind w:left="0" w:right="0" w:firstLine="0"/>
520
+ </w:pPr>
521
+ <w:rPr>
522
+ <w:b/>
523
+ <w:bCs/>
524
+ </w:rPr>
525
+ <w:tcPr>
526
+ <w:vAlign w:val="center"/>
527
+ </w:tcPr>
528
+ </w:tblStylePr>
529
+ <w:tblStylePr w:type="lastRow"/>
530
+ <w:tblStylePr w:type="firstCol"/>
531
+ <w:tblStylePr w:type="lastCol"/>
532
+ <w:tblStylePr w:type="band1Vert"/>
533
+ <w:tblStylePr w:type="band2Vert"/>
534
+ <w:tblStylePr w:type="band1Horz"/>
535
+ <w:tblStylePr w:type="band2Horz"/>
536
+ </w:style>""",
537
+ }
538
+
539
+ SECTPR = """<w:sectPr>
540
+ <w:footerReference r:id="rIdF1" w:type="default"/>
541
+ <w:footnotePr>
542
+ <w:numRestart w:val="eachSect"/>
543
+ </w:footnotePr>
544
+ <w:pgSz w:w="11906" w:h="16838"/>
545
+ <w:pgMar w:top="1134" w:right="1417" w:bottom="1701" w:left="1417" w:header="720" w:footer="720" w:gutter="0"/>
546
+ </w:sectPr>"""
547
+
548
+ FOOTER1 = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
549
+ <w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
550
+ <w:p>
551
+ <w:pPr><w:jc w:val="center"/></w:pPr>
552
+ <w:r><w:fldChar w:fldCharType="begin"/></w:r>
553
+ <w:r><w:instrText xml:space="preserve"> PAGE </w:instrText></w:r>
554
+ <w:r><w:fldChar w:fldCharType="separate"/></w:r>
555
+ <w:r><w:t>1</w:t></w:r>
556
+ <w:r><w:fldChar w:fldCharType="end"/></w:r>
557
+ </w:p>
558
+ </w:ftr>"""
559
+
560
+
561
+ def main():
562
+ src = sys.argv[1] if len(sys.argv) > 1 else "/tmp/ref-default.docx"
563
+ dst = sys.argv[2] if len(sys.argv) > 2 else "reference.docx"
564
+
565
+ with zipfile.ZipFile(src, "r") as zin:
566
+ names = zin.namelist()
567
+ items = {n: zin.read(n) for n in names}
568
+
569
+ styles = items["word/styles.xml"].decode("utf-8")
570
+ missing = []
571
+ for style_id, block in STYLES.items():
572
+ pattern = re.compile(
573
+ rf'<w:style\b[^>]*w:styleId="{style_id}"[^>]*>.*?</w:style>',
574
+ re.S,
575
+ )
576
+ if pattern.search(styles):
577
+ styles = pattern.sub(block, styles)
578
+ else:
579
+ missing.append(style_id)
580
+ if missing:
581
+ styles = styles.replace("</w:styles>", "".join(STYLES[s] for s in missing) + "</w:styles>")
582
+ print(f"[add] style baru ditambahkan: {', '.join(missing)}")
583
+ items["word/styles.xml"] = styles.encode("utf-8")
584
+
585
+ doc = items["word/document.xml"].decode("utf-8")
586
+ if re.search(r"<w:sectPr>.*?</w:sectPr>", doc, re.S):
587
+ doc = re.sub(r"<w:sectPr>.*?</w:sectPr>", SECTPR, doc, flags=re.S)
588
+ else:
589
+ print("[warn] sectPr tidak ditemukan di document.xml")
590
+ items["word/document.xml"] = doc.encode("utf-8")
591
+
592
+ settings = items["word/settings.xml"].decode("utf-8")
593
+ if "<w:updateFields" not in settings:
594
+ settings = settings.replace(
595
+ "</w:settings>", '<w:updateFields w:val="true"/></w:settings>'
596
+ )
597
+ print("[add] updateFields diaktifkan di settings.xml")
598
+ items["word/settings.xml"] = settings.encode("utf-8")
599
+
600
+ if "word/footer1.xml" not in items:
601
+ items["word/footer1.xml"] = FOOTER1.encode("utf-8")
602
+ ct = items["[Content_Types].xml"].decode("utf-8")
603
+ if "footer1.xml" not in ct:
604
+ ct = ct.replace(
605
+ "</Types>",
606
+ '<Override PartName="/word/footer1.xml" '
607
+ 'ContentType="application/vnd.openxmlformats-officedocument.'
608
+ 'wordprocessingml.footer+xml"/></Types>',
609
+ )
610
+ items["[Content_Types].xml"] = ct.encode("utf-8")
611
+ rels = items["word/_rels/document.xml.rels"].decode("utf-8")
612
+ if 'Id="rIdF1"' not in rels:
613
+ rels = rels.replace(
614
+ "</Relationships>",
615
+ '<Relationship Id="rIdF1" '
616
+ 'Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" '
617
+ 'Target="footer1.xml"/></Relationships>',
618
+ )
619
+ items["word/_rels/document.xml.rels"] = rels.encode("utf-8")
620
+ print("[add] footer1.xml (nomor halaman PAGE) + rels + content-types")
621
+
622
+ with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zout:
623
+ for n, content in items.items():
624
+ zout.writestr(n, content)
625
+
626
+ print(f"[OK] reference.docx dibuat: {dst}")
627
+
628
+
629
+ if __name__ == "__main__":
630
+ main()