Beispiel #1
0
    def __init__(self,
                 pipeline=None,
                 source=None,
                 stdout_level="INFO",
                 stderr_level="INFO",
                 cwd=None):
        assert pipeline
        assert source

        if not cwd:
            cwd = tempfile.gettempdir()

        self.success = False

        Epubcheck.init_environment()

        # epubcheck works better when the input is zipped
        if source.lower().endswith(".opf"):
            pipeline.utils.report.debug("EPUB is not zipped, zipping…")
            root_path = os.path.dirname(source)
            while True:
                assert root_path != os.path.dirname(
                    root_path
                ), "No mimetype file or META-INF directory found in the EPUB, unable to determine root directory"
                is_root = False
                for filename in os.listdir(root_path):
                    if filename == "mimetype" or filename == "META-INF":
                        is_root = True
                        break
                if is_root:
                    break
                else:
                    root_path = os.path.dirname(root_path)

            epub = Epub(pipeline.utils.report, root_path)
            source = epub.asFile()

        try:
            command = ["java", "-jar", Epubcheck.epubcheck_jar]
            command.append(source)

            pipeline.utils.report.debug("Running Epubcheck")
            process = Filesystem.run_static(command,
                                            cwd,
                                            pipeline.utils.report,
                                            stdout_level=stdout_level,
                                            stderr_level=stderr_level)
            self.success = process.returncode == 0

        except subprocess.TimeoutExpired:
            pipeline.utils.report.error(
                "Epubcheck for {} took too long and were therefore stopped.".
                format(os.path.basename(source)))

        except Exception:
            pipeline.utils.report.debug(traceback.format_exc(),
                                        preformatted=True)
            pipeline.utils.report.error(
                "An error occured while running Epubcheck (for " +
                str(source) + ")")
    def on_book(self):
        epub = Epub(self.utils.report, self.book["source"])
        epubTitle = ""
        try:
            epubTitle = " (" + epub.meta("dc:title") + ") "
        except Exception:
            pass
        # sjekk at dette er en EPUB
        if not epub.isepub():
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return

        if not epub.identifier():
            self.utils.report.error(
                self.book["name"] +
                ": Klarte ikke å bestemme boknummer basert på dc:identifier.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return

        self.utils.report.info("Lager en kopi av EPUBen med tomme bildefiler")
        temp_noimages_epubdir_obj = tempfile.TemporaryDirectory()
        temp_noimages_epubdir = temp_noimages_epubdir_obj.name
        Filesystem.copy(self.utils.report, epub.asDir(), temp_noimages_epubdir)
        if os.path.isdir(os.path.join(temp_noimages_epubdir, "EPUB",
                                      "images")):
            temp_xml_obj = tempfile.NamedTemporaryFile()
            temp_xml = temp_xml_obj.name
            opf_image_references = []
            html_image_references = {}
            for root, dirs, files in os.walk(
                    os.path.join(temp_noimages_epubdir, "EPUB")):
                for file in files:
                    if file.endswith(".opf"):
                        opf_file = os.path.join(root, file)
                        self.utils.report.info(
                            "Fjerner alle bildereferanser fra OPFen, og erstatter med en referanse til dummy.jpg..."
                        )
                        opf_xml_document = ElementTree.parse(opf_file)
                        opf_xml = opf_xml_document.getroot()
                        image_items = opf_xml.xpath(
                            "//*[local-name()='item' and starts-with(@media-type, 'image/')]"
                        )
                        replaced = False
                        for image_item in image_items:
                            if image_item.attrib[
                                    "href"] not in opf_image_references:
                                opf_image_references.append(
                                    image_item.attrib["href"])

                            if image_item.get("href") == "images/cover.jpg":
                                pass  # don't change the reference to cover.jpg

                            elif not replaced:
                                image_item.attrib["href"] = "images/dummy.jpg"
                                replaced = True

                            else:
                                image_item.getparent().remove(image_item)

                        opf_xml_document.write(opf_file,
                                               method='XML',
                                               xml_declaration=True,
                                               encoding='UTF-8',
                                               pretty_print=False)

                    if file.endswith(".xhtml"):
                        html_file = os.path.join(root, file)

                        html_xml_document = ElementTree.parse(html_file)
                        html_xml = html_xml_document.getroot()
                        image_references = html_xml.xpath(
                            "//@href | //@src | //@altimg")
                        for reference in image_references:
                            path = reference.split("#")[0]
                            if path.startswith("images/"):
                                if path not in html_image_references:
                                    html_image_references[path] = []
                                html_image_references[path].append(file)

                        self.utils.report.info(
                            "Erstatter alle bildereferanser med images/dummy.jpg..."
                        )
                        self.utils.report.debug("dummy-jpg.xsl")
                        self.utils.report.debug("    source = " + html_file)
                        self.utils.report.debug("    target = " + temp_xml)
                        xslt = Xslt(self,
                                    stylesheet=os.path.join(
                                        Xslt.xslt_dir, IncomingNordic.uid,
                                        "dummy-jpg.xsl"),
                                    source=html_file,
                                    target=temp_xml)
                        if not xslt.success:
                            self.utils.report.title = self.title + ": " + epub.identifier(
                            ) + " feilet 😭👎" + epubTitle
                            return False
                        shutil.copy(temp_xml, html_file)

            # validate for the presence of image files here, since epubcheck won't be able to do it anymore after we change the EPUB
            image_files_present = []
            for root, dirs, files in os.walk(
                    os.path.join(temp_noimages_epubdir, "EPUB", "images")):
                for file in files:
                    fullpath = os.path.join(root, file)
                    relpath = os.path.relpath(
                        fullpath, os.path.join(temp_noimages_epubdir, "EPUB"))
                    image_files_present.append(relpath)
            image_error = False
            for file in image_files_present:
                if file not in opf_image_references:
                    self.utils.report.error(
                        "Bildefilen er ikke deklarert i OPFen: " + file)
                    image_error = True
            for file in opf_image_references:
                if file not in image_files_present:
                    self.utils.report.error(
                        "Bildefilen er deklarert i OPFen, men finnes ikke: " +
                        file)
                    image_error = True
            for file in html_image_references:
                if file not in opf_image_references:
                    self.utils.report.error(
                        "Bildefilen er deklarert i HTMLen, men finnes ikke: " +
                        file + " (deklarert i: " +
                        ", ".join(html_image_references[file]) + ")")
                    image_error = True
            if image_error:
                self.utils.report.title = self.title + ": " + epub.identifier(
                ) + " feilet 😭👎" + epubTitle
                return False

            for root, dirs, files in os.walk(
                    os.path.join(temp_noimages_epubdir, "EPUB", "images")):
                for file in files:
                    if file == "cover.jpg":
                        continue  # don't delete the cover file
                    fullpath = os.path.join(root, file)
                    os.remove(fullpath)
            shutil.copy(
                os.path.join(Xslt.xslt_dir, IncomingNordic.uid,
                             "reference-files", "demobilde.jpg"),
                os.path.join(temp_noimages_epubdir, "EPUB", "images",
                             "dummy.jpg"))

        temp_noimages_epub = Epub(self.utils.report, temp_noimages_epubdir)

        self.utils.report.info(
            "Validerer EPUB med epubcheck og nordiske retningslinjer...")
        epub_noimages_file = temp_noimages_epub.asFile()
        with DaisyPipelineJob(self,
                              "nordic-epub3-validate",
                              {"epub": os.path.basename(epub_noimages_file)},
                              priority="high",
                              pipeline_and_script_version=[
                                  ("1.13.6", "1.4.6"),
                                  ("1.13.4", "1.4.5"),
                                  ("1.12.1", "1.4.2"),
                                  ("1.11.1-SNAPSHOT", "1.3.0"),
                              ],
                              context={
                                  os.path.basename(epub_noimages_file):
                                  epub_noimages_file
                              }) as dp2_job:

            # get validation report
            report_file = os.path.join(dp2_job.dir_output,
                                       "html-report/report.xhtml")
            if os.path.isfile(report_file):
                with open(report_file, 'r') as result_report:
                    self.utils.report.attachment(
                        result_report.readlines(),
                        os.path.join(self.utils.report.reportDir(),
                                     "report.html"),
                        "SUCCESS" if dp2_job.status == "SUCCESS" else "ERROR")

            if dp2_job.status != "SUCCESS":
                self.utils.report.error("Klarte ikke å validere boken")
                self.utils.report.title = self.title + ": " + epub.identifier(
                ) + " feilet 😭👎" + epubTitle
                return

        self.utils.report.debug("Making a copy of the EPUB to work on…")
        epub_fixed, epub_fixed_obj = epub.copy()
        epub_unzipped = epub_fixed.asDir()
        nav_path = os.path.join(epub_unzipped, epub_fixed.nav_path())
        mathML_validation_result = True
        mathml_error_count = 0
        mathml_errors_not_shown = 0
        mathml_report_errors_max = 10
        for root, dirs, files in os.walk(epub_unzipped):
            for f in files:
                file = os.path.join(root, f)
                if not file.endswith(".xhtml") or file is nav_path:
                    continue
                self.utils.report.info("Checking MathML in " + file)
                mathml_validation = Mathml_validator(
                    self,
                    source=file,
                    report_errors_max=mathml_report_errors_max)
                if not mathml_validation.success:
                    mathml_error_count += mathml_validation.error_count
                    mathml_errors_not_shown += max(
                        (mathml_validation.error_count -
                         mathml_report_errors_max), 0)
                    if mathml_error_count > mathml_report_errors_max:
                        mathml_report_errors_max = 0  # don't put any more errors for the other HTML documents in the main report
                    mathML_validation_result = False
        if mathml_errors_not_shown > 0:
            self.utils.report.error(
                "{} additional MathML errors not shown in the main report. Check the log for details."
                .format(mathml_errors_not_shown))
        if mathML_validation_result is False:
            return False

        self.utils.report.debug(
            "Making sure that the EPUB has the correct file and directory permissions…"
        )
        epub_fixed.fix_permissions()

        try:
            self.utils.report.info("Genererer ACE-rapport...")
            ace_dir = os.path.join(self.utils.report.reportDir(),
                                   "accessibility-report")
            process = self.utils.filesystem.run(
                [IncomingNordic.ace_cli, "-o", ace_dir,
                 epub_fixed.asFile()])
            if process.returncode == 0:
                self.utils.report.info("ACE-rapporten ble generert.")
            else:
                self.utils.report.warn(
                    "En feil oppstod ved produksjon av ACE-rapporten for " +
                    epub.identifier())
                self.utils.report.debug(traceback.format_stack())

            # attach report
            ace_status = None
            with open(os.path.join(ace_dir, "report.json")) as json_report:
                ace_status = json.load(
                    json_report)["earl:result"]["earl:outcome"]
            if ace_status == "pass":
                ace_status = "SUCCESS"
            else:
                ace_status = "WARN"
            self.utils.report.attachment(None,
                                         os.path.join(ace_dir, "report.html"),
                                         ace_status)

        except subprocess.TimeoutExpired:
            self.utils.report.warn(
                "Det tok for lang tid å lage ACE-rapporten for " +
                epub.identifier() + ", og prosessen ble derfor stoppet.")

        except Exception:
            self.utils.report.warn(
                "En feil oppstod ved produksjon av ACE-rapporten for " +
                epub.identifier())
            self.utils.report.debug(traceback.format_exc(), preformatted=True)

        self.utils.report.info(
            "Boken er valid. Kopierer til EPUB master-arkiv.")

        archived_path, stored = self.utils.filesystem.storeBook(
            epub_fixed.asDir(), epub.identifier())
        self.utils.report.attachment(None, archived_path, "DEBUG")
        self.utils.report.title = self.title + ": " + epub.identifier(
        ) + " er valid 👍😄" + epubTitle
        self.utils.filesystem.deleteSource()
        return True
Beispiel #3
0
    def on_book(self):
        self.utils.report.attachment(None, self.book["source"], "DEBUG")
        epub = Epub(self.utils.report, self.book["source"])

        epubTitle = ""
        try:
            epubTitle = " (" + epub.meta("dc:title") + ") "
        except Exception:
            pass

        # sjekk at dette er en EPUB
        if not epub.isepub():
            return False

        if not epub.identifier():
            self.utils.report.error(
                self.book["name"] +
                ": Klarte ikke å bestemme boknummer basert på dc:identifier.")
            return False

        if epub.identifier() != self.book["name"].split(".")[0]:
            self.utils.report.error(
                self.book["name"] +
                ": Filnavn stemmer ikke overens med dc:identifier: {}".format(
                    epub.identifier()))
            return False

        temp_xml_file_obj = tempfile.NamedTemporaryFile()
        temp_xml_file = temp_xml_file_obj.name

        self.utils.report.info("Lager en kopi av EPUBen")
        temp_epubdir_withimages_obj = tempfile.TemporaryDirectory()
        temp_epubdir_withimages = temp_epubdir_withimages_obj.name
        Filesystem.copy(self.utils.report, self.book["source"],
                        temp_epubdir_withimages)

        self.utils.report.info("Lager en kopi av EPUBen med tomme bildefiler")
        temp_epubdir_obj = tempfile.TemporaryDirectory()
        temp_epubdir = temp_epubdir_obj.name
        Filesystem.copy(self.utils.report, temp_epubdir_withimages,
                        temp_epubdir)
        for root, dirs, files in os.walk(
                os.path.join(temp_epubdir, "EPUB", "images")):
            for file in files:
                fullpath = os.path.join(root, file)
                os.remove(fullpath)
                Path(fullpath).touch()
        temp_epub = Epub(self.utils.report, temp_epubdir)

        self.utils.report.info("Rydder opp i nordisk EPUB nav.xhtml")
        nav_path = os.path.join(temp_epubdir, temp_epub.nav_path())
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, NordicToNlbpub.uid,
                                            "nordic-cleanup-nav.xsl"),
                    source=nav_path,
                    target=temp_xml_file,
                    parameters={
                        "cover":
                        " ".join([item["href"] for item in temp_epub.spine()]),
                        "base":
                        os.path.dirname(
                            os.path.join(temp_epubdir, temp_epub.opf_path())) +
                        "/"
                    })
        if not xslt.success:
            return False
        shutil.copy(temp_xml_file, nav_path)

        self.utils.report.info("Rydder opp i nordisk EPUB package.opf")
        opf_path = os.path.join(temp_epubdir, temp_epub.opf_path())
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, NordicToNlbpub.uid,
                                            "nordic-cleanup-opf.xsl"),
                    source=opf_path,
                    target=temp_xml_file)
        if not xslt.success:
            return False
        shutil.copy(temp_xml_file, opf_path)

        html_dir_obj = tempfile.TemporaryDirectory()
        html_dir = html_dir_obj.name
        html_file = os.path.join(html_dir, epub.identifier() + ".xhtml")

        self.utils.report.info("Finner ut hvilket bibliotek boka tilhører…")
        edition_metadata = Metadata.get_edition_from_api(
            epub.identifier(), report=self.utils.report)
        library = None
        if edition_metadata is not None and edition_metadata[
                "library"] is not None:
            library = edition_metadata["library"]
        else:
            library = Metadata.get_library_from_identifier(
                epub.identifier(), self.utils.report)
        self.utils.report.info(f"Boka tilhører '{library}'")

        self.utils.report.info("Zipper oppdatert versjon av EPUBen...")
        temp_epub.asFile(rebuild=True)

        self.utils.report.info(
            "Konverterer fra Nordisk EPUB 3 til Nordisk HTML 5...")
        epub_file = temp_epub.asFile()
        with DaisyPipelineJob(self,
                              "nordic-epub3-to-html", {
                                  "epub": os.path.basename(epub_file),
                                  "fail-on-error": "false"
                              },
                              pipeline_and_script_version=[
                                  ("1.13.6", "1.4.6"),
                                  ("1.13.4", "1.4.5"),
                                  ("1.12.1", "1.4.2"),
                                  ("1.11.1-SNAPSHOT", "1.3.0"),
                              ],
                              context={os.path.basename(epub_file):
                                       epub_file}) as dp2_job_convert:
            convert_status = "SUCCESS" if dp2_job_convert.status == "SUCCESS" else "ERROR"

            if convert_status != "SUCCESS":
                self.utils.report.error("Klarte ikke å konvertere boken")
                return False

            dp2_html_dir = os.path.join(dp2_job_convert.dir_output,
                                        "output-dir", epub.identifier())
            dp2_html_file = os.path.join(dp2_job_convert.dir_output,
                                         "output-dir", epub.identifier(),
                                         epub.identifier() + ".xhtml")

            if not os.path.isdir(dp2_html_dir):
                self.utils.report.error(
                    "Finner ikke den konverterte boken: {}".format(
                        dp2_html_dir))
                return False

            if not os.path.isfile(dp2_html_file):
                self.utils.report.error(
                    "Finner ikke den konverterte boken: {}".format(
                        dp2_html_file))
                self.utils.report.info(
                    "Kanskje filnavnet er forskjellig fra IDen?")
                return False

            Filesystem.copy(self.utils.report, dp2_html_dir, html_dir)

        self.utils.report.info("Rydder opp i nordisk HTML")
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, NordicToNlbpub.uid,
                                            "nordic-cleanup.xsl"),
                    source=html_file,
                    target=temp_xml_file)
        if not xslt.success:
            return False
        shutil.copy(temp_xml_file, html_file)

        self.utils.report.info("Rydder opp i ns0 i page-normal")
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, NordicToNlbpub.uid,
                                            "ns0-cleanup.xsl"),
                    source=html_file,
                    target=temp_xml_file)
        if not xslt.success:
            return False
        shutil.copy(temp_xml_file, html_file)

        self.utils.report.info("Rydder opp i innholdsfortegnelsen")
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, NordicToNlbpub.uid,
                                            "fix-toc-span.xsl"),
                    source=html_file,
                    target=temp_xml_file)
        if not xslt.success:
            return False
        shutil.copy(temp_xml_file, html_file)

        self.utils.report.info(
            "Legger til EPUB-filer (OPF, NAV, container.xml, mediatype)...")
        nlbpub_tempdir_obj = tempfile.TemporaryDirectory()
        nlbpub_tempdir = nlbpub_tempdir_obj.name

        nlbpub = Epub.from_html(self, html_dir, nlbpub_tempdir)
        if nlbpub is None:
            return False

        self.utils.report.info(
            "Erstatter tomme bildefiler med faktiske bildefiler")
        for root, dirs, files in os.walk(
                os.path.join(nlbpub_tempdir, "EPUB", "images")):
            for file in files:
                fullpath = os.path.join(root, file)
                relpath = os.path.relpath(fullpath, nlbpub_tempdir)
                os.remove(fullpath)
                Filesystem.copy(self.utils.report,
                                os.path.join(temp_epubdir_withimages, relpath),
                                fullpath)
        temp_epub = Epub(self.utils.report, temp_epubdir)

        nlbpub.update_prefixes()

        self.utils.report.info(
            "Boken ble konvertert. Kopierer til NLBPUB-arkiv.")
        archived_path, stored = self.utils.filesystem.storeBook(
            nlbpub.asDir(), temp_epub.identifier(), overwrite=self.overwrite)
        self.utils.report.attachment(None, archived_path, "DEBUG")
        self.utils.report.title = self.title + ": " + epub.identifier(
        ) + " ble konvertert 👍😄" + epubTitle
        return True
Beispiel #4
0
    def on_book(self):
        self.utils.report.attachment(None, self.book["source"], "DEBUG")
        epub = Epub(self.utils.report, self.book["source"])

        epubTitle = ""
        try:
            epubTitle = " (" + epub.meta("dc:title") + ") "
        except Exception:
            pass

        # sjekk at dette er en EPUB
        if not epub.isepub():
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎"
            return False

        if not epub.identifier():
            self.utils.report.error(
                self.book["name"] +
                ": Klarte ikke å bestemme boknummer basert på dc:identifier.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎"
            return False

        # ---------- lag en kopi av EPUBen ----------

        narration_epubdir_obj = tempfile.TemporaryDirectory()
        narration_epubdir = narration_epubdir_obj.name
        Filesystem.copy(self.utils.report, self.book["source"],
                        narration_epubdir)
        nlbpub = Epub(self.utils.report, narration_epubdir)

        # ---------- gjør tilpasninger i HTML-fila med XSLT ----------

        opf_path = nlbpub.opf_path()
        if not opf_path:
            self.utils.report.error(self.book["name"] +
                                    ": Klarte ikke å finne OPF-fila i EPUBen.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return False
        opf_path = os.path.join(narration_epubdir, opf_path)

        xml = ElementTree.parse(opf_path).getroot()
        html_file = xml.xpath(
            "/*/*[local-name()='manifest']/*[@id = /*/*[local-name()='spine']/*[1]/@idref]/@href"
        )
        html_file = html_file[0] if html_file else None
        if not html_file:
            self.utils.report.error(self.book["name"] +
                                    ": Klarte ikke å finne HTML-fila i OPFen.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return False

        html_file = os.path.join(os.path.dirname(opf_path), html_file)
        if not os.path.isfile(html_file):
            self.utils.report.error(self.book["name"] +
                                    ": Klarte ikke å finne HTML-fila.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return False

        temp_html_obj = tempfile.NamedTemporaryFile()
        temp_html = temp_html_obj.name

        self.utils.report.info(
            "Fjerner elementer som ikke skal være med i lydboka...")
        self.utils.report.debug("ta-vekk-innhold.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(NlbpubToNarrationEpub.xslt_dir,
                                            NlbpubToNarrationEpub.uid,
                                            "ta-vekk-innhold.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Fikser Webarch-oppmerking")
        self.utils.report.debug("webarch-fixup.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir,
                                            NlbpubToNarrationEpub.uid,
                                            "webarch-fixup.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Fikser dikt-oppmerking")
        self.utils.report.debug("unwrap-poem-chapters.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir,
                                            NlbpubToNarrationEpub.uid,
                                            "unwrap-poem-chapters.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Lager usynlige overskrifter der det trengs...")
        self.utils.report.debug("create-hidden-headlines.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, PrepareForEbook.uid,
                                            "create-hidden-headlines.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Tilpasser innhold for innlesing...")
        self.utils.report.debug("prepare-for-narration.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(NlbpubToNarrationEpub.xslt_dir,
                                            NlbpubToNarrationEpub.uid,
                                            "prepare-for-narration.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Lager synkroniseringspunkter...")
        self.utils.report.debug("lag-synkroniseringspunkter.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(NlbpubToNarrationEpub.xslt_dir,
                                            NlbpubToNarrationEpub.uid,
                                            "lag-synkroniseringspunkter.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        self.utils.report.info("Gjør HTMLen litt penere...")
        self.utils.report.debug("pretty-print.xsl")
        self.utils.report.debug("    source = " + html_file)
        self.utils.report.debug("    target = " + temp_html)
        xslt = Xslt(self,
                    stylesheet=os.path.join(Xslt.xslt_dir, Epub.uid,
                                            "pretty-print.xsl"),
                    source=html_file,
                    target=temp_html)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False
        shutil.copy(temp_html, html_file)

        # ---------- erstatt metadata i OPF med metadata fra HTML ----------

        temp_opf_obj = tempfile.NamedTemporaryFile()
        temp_opf = temp_opf_obj.name

        xslt = Epub.html_to_opf(self, opf_path, temp_opf)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False

        shutil.copy(temp_opf, opf_path)

        # ---------- hent nytt filnavn fra OPF (det endrer seg basert på boknummer) ----------
        try:
            xml = ElementTree.parse(opf_path).getroot()
            new_html_file = xml.xpath(
                "/*/*[local-name()='manifest']/*[@id = /*/*[local-name()='spine']/*[1]/@idref]/@href"
            )
            new_html_file = os.path.join(
                os.path.dirname(opf_path),
                new_html_file[0]) if new_html_file else None
        except Exception:
            self.utils.report.info(traceback.format_exc(), preformatted=True)
            self.utils.report.error(self.book["name"] +
                                    ": Klarte ikke å finne HTML-fila i OPFen.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return False

        if html_file != new_html_file:
            shutil.copy(html_file, new_html_file)
            os.remove(html_file)
            html_file = new_html_file

        # ---------- lag nav.xhtml på nytt ----------

        nav_path = nlbpub.nav_path()
        if not nav_path:
            self.utils.report.error(
                self.book["name"] +
                ": Klarte ikke å finne navigasjonsfila i OPFen.")
            self.utils.report.title = self.title + ": " + self.book[
                "name"] + " feilet 😭👎" + epubTitle
            return False
        nav_path = os.path.join(narration_epubdir, nav_path)

        xslt = Epub.html_to_nav(self, html_file, nav_path)
        if not xslt.success:
            self.utils.report.title = self.title + ": " + epub.identifier(
            ) + " feilet 😭👎" + epubTitle
            return False

        # ---------- legg til logo ----------
        library = nlbpub.meta("schema:library")
        library = library.upper() if library else library
        logo = os.path.join(Xslt.xslt_dir, PrepareForEbook.uid,
                            "{}_logo.png".format(library))

        if os.path.isfile(logo) and library == "STATPED":
            shutil.copy(
                logo,
                os.path.join(os.path.dirname(html_file),
                             os.path.basename(logo)))

        # ---------- save EPUB ----------

        self.utils.report.info(
            "Boken ble konvertert. Kopierer til innlesingsklart EPUB-arkiv.")

        archived_path, stored = self.utils.filesystem.storeBook(
            nlbpub.asFile(),
            nlbpub.identifier(),
            file_extension="epub",
            move=True)
        self.utils.report.attachment(None, archived_path, "DEBUG")
        self.utils.report.title = self.title + ": " + epub.identifier(
        ) + " ble konvertert 👍😄" + epubTitle
        return True