27def export(configDictionary = {}, projectURL = str(), pagesLocationList = [], pageData = []):
28 path = Path(os.path.join(projectURL, configDictionary[
"exportLocation"]))
29 exportPath = path /
"EPUB-files"
30 metaInf = exportPath /
"META-INF"
31 oebps = exportPath /
"OEBPS"
32 imagePath = oebps /
"Images"
35 textPath = oebps /
"Text"
37 if exportPath.exists()
is False:
50 title = configDictionary[
"projectName"]
51 if "title" in configDictionary.keys():
52 title = str(configDictionary[
"title"]).replace(
" ",
"_")
55 url = str(path / str(title +
".epub"))
58 epubArchive = zipfile.ZipFile(url, mode=
"w", compression=zipfile.ZIP_STORED)
60 mimetype = open(str(Path(exportPath /
"mimetype")), mode=
"w")
61 mimetype.write(
"application/epub+zip")
65 epubArchive.write(Path(exportPath /
"mimetype"), Path(
"mimetype"))
67 container = QDomDocument()
68 cRoot = container.createElement(
"container")
69 cRoot.setAttribute(
"version",
"1.0")
70 cRoot.setAttribute(
"xmlns",
"urn:oasis:names:tc:opendocument:xmlns:container")
71 container.appendChild(cRoot)
72 rootFiles = container.createElement(
"rootfiles")
73 rootfile = container.createElement(
"rootfile")
74 rootfile.setAttribute(
"full-path",
"OEBPS/content.opf")
75 rootfile.setAttribute(
"media-type",
"application/oebps-package+xml")
76 rootFiles.appendChild(rootfile)
77 cRoot.appendChild(rootFiles)
79 containerFileName = str(Path(metaInf /
"container.xml"))
81 containerFile = open(containerFileName,
'w', newline=
"", encoding=
"utf-8")
82 containerFile.write(container.toString(indent=2))
86 epubArchive.write(containerFileName, os.path.relpath(containerFileName, str(exportPath)))
90 if len(pagesLocationList)>0:
91 if "cover" in configDictionary.keys():
92 coverNumber = configDictionary[
"pages"].index(configDictionary[
"cover"])
95 for p
in pagesLocationList:
97 shutil.copy2(p, str(imagePath))
98 filename = str(Path(imagePath / os.path.basename(p)))
99 pagesList.append(filename)
100 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
101 if len(pagesLocationList) >= coverNumber:
102 coverpageurl = pagesList[coverNumber]
104 print(
"CPMT: Couldn't find the location for the epub images.")
113 for i
in range(len(pagesList)):
114 pageName =
"Page" + str(i) +
".xhtml"
116 html = doc.createElement(
"html")
117 doc.appendChild(html)
118 html.setAttribute(
"xmlns",
"http://www.w3.org/1999/xhtml")
119 html.setAttribute(
"xmlns:epub",
"http://www.idpf.org/2007/ops")
125 head = doc.createElement(
"head")
126 viewport = doc.createElement(
"meta")
127 viewport.setAttribute(
"name",
"viewport")
130 img.load(pagesLocationList[i])
134 widthHeight =
"width="+str(w)+
", height="+str(h)
136 viewport.setAttribute(
"content", widthHeight)
137 head.appendChild(viewport)
138 html.appendChild(head)
144 transform = data[
"transform"]
145 for v
in data[
"vector"]:
147 dominantColor = QColor(Qt.GlobalColor.white)
149 for point
in v[
"boundingBox"]:
150 offset = QPointF(transform[
"offsetX"], transform[
"offsetY"])
151 pixelPoint = QPointF(point.x() * transform[
"resDiff"], point.y() * transform[
"resDiff"])
152 newPoint = pixelPoint - offset
153 x = max(0, min(w, int(newPoint.x() * transform[
"scaleWidth"])))
154 y = max(0, min(h, int(newPoint.y() * transform[
"scaleHeight"])))
155 listOfColors.append(img.pixelColor(QPointF(x, y).toPoint()))
156 pointsList.append(QPointF((x/w)*100, (y/h)*100))
158 if "text" in v.keys():
160 if len(listOfColors)>0:
161 dominantColor = listOfColors[-1]
162 listOfColors = listOfColors[:-1]
163 for color
in listOfColors:
164 dominantColor.setRedF(0.5*(dominantColor.redF()+color.redF()))
165 dominantColor.setGreenF(0.5*(dominantColor.greenF()+color.greenF()))
166 dominantColor.setBlueF(0.5*(dominantColor.blueF()+color.blueF()))
168 bounds = QPolygonF(pointsList).boundingRect()
169 region[
"points"] = bounds
170 region[
"type"] = regionType
171 region[
"page"] = str(Path(textPath / pageName))
172 region[
"primaryColor"] = dominantColor.name()
173 regions.append(region)
177 if "acbf_title" in data[
"keys"]:
178 listOfNavItems[str(Path(textPath / pageName))] = data[
"title"]
182 if "epub_spread" in data[
"keys"]:
183 listofSpreads.append(str(Path(textPath / pageName)))
185 body = doc.createElement(
"body")
187 img = doc.createElement(
"img")
188 img.setAttribute(
"src", os.path.relpath(pagesList[i], str(textPath)))
189 img.setAttribute(
"width",
"100%")
190 body.appendChild(img)
192 html.appendChild(body)
194 filename = str(Path(textPath / pageName))
195 docFile = open(filename,
'w', newline=
"", encoding=
"utf-8")
196 docFile.write(doc.toString(indent=2))
199 if pagesList[i] == coverpageurl:
200 coverpagehtml = os.path.relpath(filename, str(oebps))
201 htmlFiles.append(filename)
204 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
208 filename =
write_opf_file(oebps, configDictionary, htmlFiles, pagesList, coverpageurl, coverpagehtml, listofSpreads)
209 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
212 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
215 filename =
write_nav_file(oebps, configDictionary, htmlFiles, listOfNavItems)
216 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
218 filename =
write_ncx_file(oebps, configDictionary, htmlFiles, listOfNavItems)
219 epubArchive.write(filename, os.path.relpath(filename, str(exportPath)))
226Write OPF metadata file
230def write_opf_file(path, configDictionary, htmlFiles, pagesList, coverpageurl, coverpagehtml, listofSpreads):
234 marcRelators = {
"abr":i18n(
"Abridger"),
"acp":i18n(
"Art copyist"),
"act":i18n(
"Actor"),
"adi":i18n(
"Art director"),
"adp":i18n(
"Adapter"),
"ann":i18n(
"Annotator"),
"ant":i18n(
"Bibliographic antecedent"),
"arc":i18n(
"Architect"),
"ard":i18n(
"Artistic director"),
"art":i18n(
"Artist"),
"asn":i18n(
"Associated name"),
"ato":i18n(
"Autographer"),
"att":i18n(
"Attributed name"),
"aud":i18n(
"Author of dialog"),
"aut":i18n(
"Author"),
"bdd":i18n(
"Binding designer"),
"bjd":i18n(
"Bookjacket designer"),
"bkd":i18n(
"Book designer"),
"bkp":i18n(
"Book producer"),
"blw":i18n(
"Blurb writer"),
"bnd":i18n(
"Binder"),
"bpd":i18n(
"Bookplate designer"),
"bsl":i18n(
"Bookseller"),
"cll":i18n(
"Calligrapher"),
"clr":i18n(
"Colorist"),
"cns":i18n(
"Censor"),
"cov":i18n(
"Cover designer"),
"cph":i18n(
"Copyright holder"),
"cre":i18n(
"Creator"),
"ctb":i18n(
"Contributor"),
"cur":i18n(
"Curator"),
"cwt":i18n(
"Commentator for written text"),
"drm":i18n(
"Draftsman"),
"dsr":i18n(
"Designer"),
"dub":i18n(
"Dubious author"),
"edt":i18n(
"Editor"),
"etr":i18n(
"Etcher"),
"exp":i18n(
"Expert"),
"fnd":i18n(
"Funder"),
"ill":i18n(
"Illustrator"),
"ilu":i18n(
"Illuminator"),
"ins":i18n(
"Inscriber"),
"lse":i18n(
"Licensee"),
"lso":i18n(
"Licensor"),
"ltg":i18n(
"Lithographer"),
"mdc":i18n(
"Metadata contact"),
"oth":i18n(
"Other"),
"own":i18n(
"Owner"),
"pat":i18n(
"Patron"),
"pbd":i18n(
"Publishing director"),
"pbl":i18n(
"Publisher"),
"prt":i18n(
"Printer"),
"sce":i18n(
"Scenarist"),
"scr":i18n(
"Scribe"),
"spn":i18n(
"Sponsor"),
"stl":i18n(
"Storyteller"),
"trc":i18n(
"Transcriber"),
"trl":i18n(
"Translator"),
"tyd":i18n(
"Type designer"),
"tyg":i18n(
"Typographer"),
"wac":i18n(
"Writer of added commentary"),
"wal":i18n(
"Writer of added lyrics"),
"wam":i18n(
"Writer of accompanying material"),
"wat":i18n(
"Writer of added text"),
"win":i18n(
"Writer of introduction"),
"wpr":i18n(
"Writer of preface"),
"wst":i18n(
"Writer of supplementary textual content")}
237 opfFile = QDomDocument()
238 opfRoot = opfFile.createElement(
"package")
239 opfRoot.setAttribute(
"version",
"3.0")
240 opfRoot.setAttribute(
"unique-identifier",
"BookId")
241 opfRoot.setAttribute(
"xmlns",
"http://www.idpf.org/2007/opf")
242 opfRoot.setAttribute(
"prefix",
"rendition: http://www.idpf.org/vocab/rendition/#")
243 opfFile.appendChild(opfRoot)
245 opfMeta = opfFile.createElement(
"metadata")
246 opfMeta.setAttribute(
"xmlns:dc",
"http://purl.org/dc/elements/1.1/")
247 opfMeta.setAttribute(
"xmlns:dcterms",
"http://purl.org/dc/terms/")
252 if "language" in configDictionary.keys():
253 langString = str(configDictionary[
"language"]).replace(
"_",
"-")
255 bookLang = opfFile.createElement(
"dc:language")
256 bookLang.appendChild(opfFile.createTextNode(langString))
257 opfMeta.appendChild(bookLang)
259 bookTitle = opfFile.createElement(
"dc:title")
260 if "title" in configDictionary.keys():
261 bookTitle.appendChild(opfFile.createTextNode(str(configDictionary[
"title"])))
263 bookTitle.appendChild(opfFile.createTextNode(
"Comic with no Name"))
264 opfMeta.appendChild(bookTitle)
267 if "seriesName" in configDictionary.keys():
268 bookTitle.setAttribute(
"id",
"main")
270 refine = opfFile.createElement(
"meta")
271 refine.setAttribute(
"refines",
"#main")
272 refine.setAttribute(
"property",
"title-type")
273 refine.appendChild(opfFile.createTextNode(
"main"))
274 opfMeta.appendChild(refine)
276 refine2 = opfFile.createElement(
"meta")
277 refine2.setAttribute(
"refines",
"#main")
278 refine2.setAttribute(
"property",
"display-seq")
279 refine2.appendChild(opfFile.createTextNode(
"1"))
280 opfMeta.appendChild(refine2)
282 seriesTitle = opfFile.createElement(
"dc:title")
283 seriesTitle.appendChild(opfFile.createTextNode(str(configDictionary[
"seriesName"])))
284 seriesTitle.setAttribute(
"id",
"series")
285 opfMeta.appendChild(seriesTitle)
287 refineS = opfFile.createElement(
"meta")
288 refineS.setAttribute(
"refines",
"#series")
289 refineS.setAttribute(
"property",
"title-type")
290 refineS.appendChild(opfFile.createTextNode(
"collection"))
291 opfMeta.appendChild(refineS)
293 refineS2 = opfFile.createElement(
"meta")
294 refineS2.setAttribute(
"refines",
"#series")
295 refineS2.setAttribute(
"property",
"display-seq")
296 refineS2.appendChild(opfFile.createTextNode(
"2"))
297 opfMeta.appendChild(refineS2)
299 if "seriesNumber" in configDictionary.keys():
300 refineS3 = opfFile.createElement(
"meta")
301 refineS3.setAttribute(
"refines",
"#series")
302 refineS3.setAttribute(
"property",
"group-position")
303 refineS3.appendChild(opfFile.createTextNode(str(configDictionary[
"seriesNumber"])))
304 opfMeta.appendChild(refineS3)
306 uuid = str(configDictionary[
"uuid"])
307 uuid = uuid.strip(
"{")
308 uuid = uuid.strip(
"}")
311 uniqueID = opfFile.createElement(
"dc:identifier")
312 uniqueID.appendChild(opfFile.createTextNode(
"urn:uuid:"+uuid))
313 uniqueID.setAttribute(
"id",
"BookId")
314 opfMeta.appendChild(uniqueID)
316 if "authorList" in configDictionary.keys():
318 for authorE
in range(len(configDictionary[
"authorList"])):
319 authorDict = configDictionary[
"authorList"][authorE]
320 authorType =
"dc:creator"
321 if "role" in authorDict.keys():
323 if str(authorDict[
"role"]).lower()
in [
"editor",
"assistant editor",
"proofreader",
"beta",
"patron",
"funder"]:
324 authorType =
"dc:contributor"
325 author = opfFile.createElement(authorType)
327 if "last-name" in authorDict.keys():
328 authorName.append(authorDict[
"last-name"])
329 if "first-name" in authorDict.keys():
330 authorName.append(authorDict[
"first-name"])
331 if "initials" in authorDict.keys():
332 authorName.append(authorDict[
"initials"])
333 if "nickname" in authorDict.keys():
334 authorName.append(
"(" + authorDict[
"nickname"] +
")")
335 author.appendChild(opfFile.createTextNode(
", ".join(authorName)))
336 author.setAttribute(
"id",
"cre" + str(authorE))
337 opfMeta.appendChild(author)
338 if "role" in authorDict.keys():
339 role = opfFile.createElement(
"meta")
340 role.setAttribute(
"refines",
"#cre" + str(authorE))
341 role.setAttribute(
"scheme",
"marc:relators")
342 role.setAttribute(
"property",
"role")
343 roleString = str(authorDict[
"role"])
344 if roleString
in marcRelators.values()
or roleString
in marcRelators.keys():
345 i = list(marcRelators.values()).index(roleString)
346 roleString = list(marcRelators.keys())[i]
349 role.appendChild(opfFile.createTextNode(roleString))
350 opfMeta.appendChild(role)
351 refine = opfFile.createElement(
"meta")
352 refine.setAttribute(
"refines",
"#cre"+str(authorE))
353 refine.setAttribute(
"property",
"display-seq")
354 refine.appendChild(opfFile.createTextNode(str(authorE+1)))
355 opfMeta.appendChild(refine)
357 if "publishingDate" in configDictionary.keys():
358 date = opfFile.createElement(
"dc:date")
359 date.appendChild(opfFile.createTextNode(configDictionary[
"publishingDate"]))
360 opfMeta.appendChild(date)
363 modified = opfFile.createElement(
"meta")
364 modified.setAttribute(
"property",
"dcterms:modified")
365 modified.appendChild(opfFile.createTextNode(QDateTime.currentDateTimeUtc().toString(Qt.DateFormat.ISODate)))
366 opfMeta.appendChild(modified)
368 if "source" in configDictionary.keys():
369 if len(configDictionary[
"source"])>0:
370 source = opfFile.createElement(
"dc:source")
371 source.appendChild(opfFile.createTextNode(configDictionary[
"source"]))
372 opfMeta.appendChild(source)
374 description = opfFile.createElement(
"dc:description")
375 if "summary" in configDictionary.keys():
376 description.appendChild(opfFile.createTextNode(configDictionary[
"summary"]))
378 description.appendChild(opfFile.createTextNode(
"There was no summary upon generation of this file."))
379 opfMeta.appendChild(description)
385 if "publisherName" in configDictionary.keys():
386 publisher = opfFile.createElement(
"dc:publisher")
387 publisher.appendChild(opfFile.createTextNode(configDictionary[
"publisherName"]))
388 opfMeta.appendChild(publisher)
391 if "isbn-number" in configDictionary.keys():
392 isbnnumber = configDictionary[
"isbn-number"]
394 if len(isbnnumber)>0:
395 publishISBN = opfFile.createElement(
"dc:identifier")
396 publishISBN.appendChild(opfFile.createTextNode(str(
"urn:isbn:") + isbnnumber))
397 opfMeta.appendChild(publishISBN)
399 if "license" in configDictionary.keys():
401 if len(configDictionary[
"license"])>0:
402 rights = opfFile.createElement(
"dc:rights")
403 rights.appendChild(opfFile.createTextNode(configDictionary[
"license"]))
404 opfMeta.appendChild(rights)
408 Relation - This is for whether the work has a relationship with another work.
409 It could be fanart, but also adaptation, an academic work, etc.
410 Coverage - This is for the time/place that the work covers. Typically to determine
411 whether an academic work deals with a certain time period or place.
412 For comics you could use this to mark historical comics, but other than
413 that we'd need a much better ui to define this.
420 if "genre" in configDictionary.keys():
421 genreListConf = configDictionary[
"genre"]
422 if isinstance(configDictionary[
"genre"], dict):
423 genreListConf = configDictionary[
"genre"].keys()
424 for g
in genreListConf:
425 subject = opfFile.createElement(
"dc:subject")
426 subject.appendChild(opfFile.createTextNode(g))
427 opfMeta.appendChild(subject)
428 if "characters" in configDictionary.keys():
429 for name
in configDictionary[
"characters"]:
430 char = opfFile.createElement(
"dc:subject")
431 char.appendChild(opfFile.createTextNode(name))
432 opfMeta.appendChild(char)
433 if "format" in configDictionary.keys():
434 for formatF
in configDictionary[
"format"]:
435 f = opfFile.createElement(
"dc:subject")
436 f.appendChild(opfFile.createTextNode(formatF))
437 opfMeta.appendChild(f)
438 if "otherKeywords" in configDictionary.keys():
439 for key
in configDictionary[
"otherKeywords"]:
440 word = opfFile.createElement(
"dc:subject")
441 word.appendChild(opfFile.createTextNode(key))
442 opfMeta.appendChild(word)
447 elLayout = opfFile.createElement(
"meta")
448 elLayout.setAttribute(
"property",
"rendition:layout")
449 elLayout.appendChild(opfFile.createTextNode(
"pre-paginated"))
450 opfMeta.appendChild(elLayout)
453 elOrientation = opfFile.createElement(
"meta")
454 elOrientation.setAttribute(
"property",
"rendition:orientation")
455 elOrientation.appendChild(opfFile.createTextNode(
"portrait"))
456 opfMeta.appendChild(elOrientation)
458 elSpread = opfFile.createElement(
"meta")
459 elSpread.setAttribute(
"property",
"rendition:spread")
460 elSpread.appendChild(opfFile.createTextNode(
"landscape"))
461 opfMeta.appendChild(elSpread)
463 opfRoot.appendChild(opfMeta)
467 opfManifest = opfFile.createElement(
"manifest")
468 toc = opfFile.createElement(
"item")
469 toc.setAttribute(
"id",
"ncx")
470 toc.setAttribute(
"href",
"toc.ncx")
471 toc.setAttribute(
"media-type",
"application/x-dtbncx+xml")
472 opfManifest.appendChild(toc)
474 region = opfFile.createElement(
"item")
475 region.setAttribute(
"id",
"regions")
476 region.setAttribute(
"href",
"region-nav.xhtml")
477 region.setAttribute(
"media-type",
"application/xhtml+xml")
478 region.setAttribute(
"properties",
"data-nav")
479 opfManifest.appendChild(region)
481 nav = opfFile.createElement(
"item")
482 nav.setAttribute(
"id",
"nav")
483 nav.setAttribute(
"href",
"nav.xhtml")
484 nav.setAttribute(
"media-type",
"application/xhtml+xml")
485 nav.setAttribute(
"properties",
"nav")
486 opfManifest.appendChild(nav)
490 item = opfFile.createElement(
"item")
491 item.setAttribute(
"id",
"img"+str(ids))
493 item.setAttribute(
"href", os.path.relpath(p, str(path)))
494 item.setAttribute(
"media-type",
"image/png")
495 if os.path.basename(p) == os.path.basename(coverpageurl):
496 item.setAttribute(
"properties",
"cover-image")
497 opfManifest.appendChild(item)
502 item = opfFile.createElement(
"item")
503 item.setAttribute(
"id",
"p"+str(ids))
505 item.setAttribute(
"href", os.path.relpath(p, str(path)))
506 item.setAttribute(
"media-type",
"application/xhtml+xml")
507 opfManifest.appendChild(item)
510 opfRoot.appendChild(opfManifest)
514 opfSpine = opfFile.createElement(
"spine")
516 opfSpine.setAttribute(
"toc",
"ncx")
521 if "readingDirection" in configDictionary.keys():
522 if configDictionary[
"readingDirection"] ==
"rightToLeft":
523 opfSpine.setAttribute(
"page-progression-direction",
"rtl")
527 opfSpine.setAttribute(
"page-progression-direction",
"ltr")
533 item = opfFile.createElement(
"itemref")
534 item.setAttribute(
"idref",
"p"+str(ids))
537 if p
in listofSpreads:
539 props.append(
"rendition:page-spread-center")
550 props.append(
"page-spread-right")
553 props.append(
"page-spread-left")
555 item.setAttribute(
"properties",
" ".join(props))
556 opfSpine.appendChild(item)
557 opfRoot.appendChild(opfSpine)
561 opfGuide = opfFile.createElement(
"guide")
562 if coverpagehtml
is not None and coverpagehtml.isspace()
is False and len(coverpagehtml) > 0:
563 item = opfFile.createElement(
"reference")
564 item.setAttribute(
"type",
"cover")
565 item.setAttribute(
"title",
"Cover")
566 item.setAttribute(
"href", coverpagehtml)
567 opfGuide.appendChild(item)
568 opfRoot.appendChild(opfGuide)
570 docFile = open(str(Path(path /
"content.opf")),
'w', newline=
"", encoding=
"utf-8")
571 docFile.write(opfFile.toString(indent=2))
573 return str(Path(path /
"content.opf"))
576Write a region navmap file.
580 navDoc = QDomDocument()
581 navRoot = navDoc.createElement(
"html")
582 navRoot.setAttribute(
"xmlns",
"http://www.w3.org/1999/xhtml")
583 navRoot.setAttribute(
"xmlns:epub",
"http://www.idpf.org/2007/ops")
584 navDoc.appendChild(navRoot)
586 head = navDoc.createElement(
"head")
587 title = navDoc.createElement(
"title")
588 title.appendChild(navDoc.createTextNode(
"Region Navigation"))
589 head.appendChild(title)
590 navRoot.appendChild(head)
592 body = navDoc.createElement(
"body")
593 navRoot.appendChild(body)
595 nav = navDoc.createElement(
"nav")
596 nav.setAttribute(
"epub:type",
"region-based")
597 nav.setAttribute(
"prefix",
"ahl: http://idpf.org/epub/vocab/ahl")
598 body.appendChild(nav)
602 olPanels = navDoc.createElement(
"ol")
603 for region
in regions:
604 if region[
"type"] ==
"panel":
605 pageName = os.path.relpath(region[
"page"], str(path))
606 print(
"accessing panel")
607 li = navDoc.createElement(
"li")
608 li.setAttribute(
"epub:type",
"panel")
610 anchor = navDoc.createElement(
"a")
611 bounds = region[
"points"]
612 anchor.setAttribute(
"href", pageName+
"#xywh=percent:"+str(bounds.x())+
","+str(bounds.y())+
","+str(bounds.width())+
","+str(bounds.height()))
614 if len(region[
"primaryColor"])>0:
615 primaryC = navDoc.createElement(
"meta")
616 primaryC.setAttribute(
"property",
"ahl:primary-color")
617 primaryC.setAttribute(
"content", region[
"primaryColor"])
618 anchor.appendChild(primaryC)
620 li.appendChild(anchor)
621 olBalloons = navDoc.createElement(
"ol")
624 The region nav spec specifies that we should have text-areas/balloons as a refinement on
626 For each panel, we'll check if there's balloons/text-areas inside, and we'll do that by
627 checking whether the center point is inside the panel because some comics have balloons
628 that overlap the gutters.
630 for balloon
in regions:
631 if balloon[
"type"] ==
"text" and balloon[
"page"] == region[
"page"]
and bounds.contains(balloon[
"points"].center()):
632 liBalloon = navDoc.createElement(
"li")
633 liBalloon.setAttribute(
"epub:type",
"text-area")
635 anchorBalloon = navDoc.createElement(
"a")
636 BBounds = balloon[
"points"]
637 anchorBalloon.setAttribute(
"href", pageName+
"#xywh=percent:"+str(BBounds.x())+
","+str(BBounds.y())+
","+str(BBounds.width())+
","+str(BBounds.height()))
639 liBalloon.appendChild(anchorBalloon)
640 olBalloons.appendChild(liBalloon)
642 if olBalloons.hasChildNodes():
643 li.appendChild(olBalloons)
644 olPanels.appendChild(li)
645 nav.appendChild(olPanels)
647 navFile = open(str(Path(path /
"region-nav.xhtml")),
'w', newline=
"", encoding=
"utf-8")
648 navFile.write(navDoc.toString(indent=2))
650 return str(Path(path /
"region-nav.xhtml"))
655This is virtually the same as the NCX file, except that
656the navigation document can be styled, and is what 3.1 and
6573.2 expect as a primary navigation document.
659This function will both create a table of contents, using the
660"acbf_title" feature, as well as a regular pageslist.
664 navDoc = QDomDocument()
665 navRoot = navDoc.createElement(
"html")
666 navRoot.setAttribute(
"xmlns",
"http://www.w3.org/1999/xhtml")
667 navRoot.setAttribute(
"xmlns:epub",
"http://www.idpf.org/2007/ops")
668 navDoc.appendChild(navRoot)
670 head = navDoc.createElement(
"head")
671 title = navDoc.createElement(
"title")
672 title.appendChild(navDoc.createTextNode(
"Table of Contents"))
673 head.appendChild(title)
674 navRoot.appendChild(head)
676 body = navDoc.createElement(
"body")
677 navRoot.appendChild(body)
681 toc = navDoc.createElement(
"nav")
682 toc.setAttribute(
"epub:type",
"toc")
683 oltoc = navDoc.createElement(
"ol")
684 li = navDoc.createElement(
"li")
685 anchor = navDoc.createElement(
"a")
686 anchor.setAttribute(
"href", os.path.relpath(htmlFiles[0], str(path)))
687 anchor.appendChild(navDoc.createTextNode(
"Start"))
688 li.appendChild(anchor)
689 oltoc.appendChild(li)
690 for fileName
in listOfNavItems.keys():
691 li = navDoc.createElement(
"li")
692 anchor = navDoc.createElement(
"a")
693 anchor.setAttribute(
"href", os.path.relpath(fileName, str(path)))
694 anchor.appendChild(navDoc.createTextNode(listOfNavItems[fileName]))
695 li.appendChild(anchor)
696 oltoc.appendChild(li)
698 toc.appendChild(oltoc)
699 body.appendChild(toc)
703 pageslist = navDoc.createElement(
"nav")
704 pageslist.setAttribute(
"epub:type",
"page-list")
705 olpages = navDoc.createElement(
"ol")
708 for i
in range(len(htmlFiles)):
709 li = navDoc.createElement(
"li")
710 anchor = navDoc.createElement(
"a")
711 anchor.setAttribute(
"href", os.path.relpath(htmlFiles[1], str(path)))
712 anchor.appendChild(navDoc.createTextNode(str(i)))
713 li.appendChild(anchor)
714 olpages.appendChild(li)
715 pageslist.appendChild(olpages)
717 body.appendChild(pageslist)
721 navFile = open(str(Path(path /
"nav.xhtml")),
'w', newline=
"", encoding=
"utf-8")
722 navFile.write(navDoc.toString(indent=2))
724 return str(Path(path /
"nav.xhtml"))
729This is the same as the navigation document above, but then
730for 2.0 backward compatibility.
734 tocDoc = QDomDocument()
735 ncx = tocDoc.createElement(
"ncx")
736 ncx.setAttribute(
"version",
"2005-1")
737 ncx.setAttribute(
"xmlns",
"http://www.daisy.org/z3986/2005/ncx/")
738 tocDoc.appendChild(ncx)
740 tocHead = tocDoc.createElement(
"head")
745 uuid = str(configDictionary[
"uuid"])
746 uuid = uuid.strip(
"{")
747 uuid = uuid.strip(
"}")
748 metaID = tocDoc.createElement(
"meta")
749 metaID.setAttribute(
"content", uuid)
750 metaID.setAttribute(
"name",
"dtb:uid")
751 tocHead.appendChild(metaID)
752 metaDepth = tocDoc.createElement(
"meta")
753 metaDepth.setAttribute(
"content", str(1))
754 metaDepth.setAttribute(
"name",
"dtb:depth")
755 tocHead.appendChild(metaDepth)
756 metaTotal = tocDoc.createElement(
"meta")
757 metaTotal.setAttribute(
"content", str(len(htmlFiles)))
758 metaTotal.setAttribute(
"name",
"dtb:totalPageCount")
759 tocHead.appendChild(metaTotal)
760 metaMax = tocDoc.createElement(
"meta")
761 metaMax.setAttribute(
"content", str(len(htmlFiles)))
762 metaMax.setAttribute(
"name",
"dtb:maxPageNumber")
763 tocHead.appendChild(metaDepth)
764 ncx.appendChild(tocHead)
766 docTitle = tocDoc.createElement(
"docTitle")
767 text = tocDoc.createElement(
"text")
768 if "title" in configDictionary.keys():
769 text.appendChild(tocDoc.createTextNode(str(configDictionary[
"title"])))
771 text.appendChild(tocDoc.createTextNode(
"Comic with no Name"))
772 docTitle.appendChild(text)
773 ncx.appendChild(docTitle)
777 navmap = tocDoc.createElement(
"navMap")
778 navPoint = tocDoc.createElement(
"navPoint")
779 navPoint.setAttribute(
"id",
"navPoint-1")
780 navPoint.setAttribute(
"playOrder",
"1")
781 navLabel = tocDoc.createElement(
"navLabel")
782 navLabelText = tocDoc.createElement(
"text")
783 navLabelText.appendChild(tocDoc.createTextNode(
"Start"))
784 navLabel.appendChild(navLabelText)
785 navContent = tocDoc.createElement(
"content")
786 navContent.setAttribute(
"src", os.path.relpath(htmlFiles[0], str(path)))
787 navPoint.appendChild(navLabel)
788 navPoint.appendChild(navContent)
789 navmap.appendChild(navPoint)
791 for fileName
in listOfNavItems.keys():
793 navPointT = tocDoc.createElement(
"navPoint")
794 navPointT.setAttribute(
"id",
"navPoint-"+str(entry))
795 navPointT.setAttribute(
"playOrder", str(entry))
796 navLabelT = tocDoc.createElement(
"navLabel")
797 navLabelTText = tocDoc.createElement(
"text")
798 navLabelTText.appendChild(tocDoc.createTextNode(listOfNavItems[fileName]))
799 navLabelT.appendChild(navLabelTText)
800 navContentT = tocDoc.createElement(
"content")
801 navContentT.setAttribute(
"src", os.path.relpath(fileName, str(path)))
802 navPointT.appendChild(navLabelT)
803 navPointT.appendChild(navContentT)
804 navmap.appendChild(navPointT)
805 ncx.appendChild(navmap)
809 pagesList = tocDoc.createElement(
"pageList")
810 navLabelPages = tocDoc.createElement(
"navLabel")
811 navLabelPagesText = tocDoc.createElement(
"text")
812 navLabelPagesText.appendChild(tocDoc.createTextNode(
"Pages"))
813 navLabelPages.appendChild(navLabelPagesText)
814 pagesList.appendChild(navLabelPages)
815 for i
in range(len(htmlFiles)):
816 pageTarget = tocDoc.createElement(
"pageTarget")
817 pageTarget.setAttribute(
"type",
"normal")
818 pageTarget.setAttribute(
"id",
"page-"+str(i))
819 pageTarget.setAttribute(
"value", str(i))
820 navLabelPagesTarget = tocDoc.createElement(
"navLabel")
821 navLabelPagesTargetText = tocDoc.createElement(
"text")
822 navLabelPagesTargetText.appendChild(tocDoc.createTextNode(str(i+1)))
823 navLabelPagesTarget.appendChild(navLabelPagesTargetText)
824 pageTarget.appendChild(navLabelPagesTarget)
825 pageTargetContent = tocDoc.createElement(
"content")
826 pageTargetContent.setAttribute(
"src", os.path.relpath(htmlFiles[i], str(path)))
827 pageTarget.appendChild(pageTargetContent)
828 pagesList.appendChild(pageTarget)
829 ncx.appendChild(pagesList)
833 docFile = open(str(Path(path /
"toc.ncx")),
'w', newline=
"", encoding=
"utf-8")
834 docFile.write(tocDoc.toString(indent=2))
836 return str(Path(path /
"toc.ncx"))