VirtualBox

Changeset 99064 in vbox for trunk/doc


Ignore:
Timestamp:
Mar 20, 2023 12:01:53 PM (23 months ago)
Author:
vboxsync
Message:

manual/Makefile.kmk: Cleaning up html and qhelp outputting. The latter doesn't need an extra copy of the Docbook version of the images, since DITA-OT copies the necessary images to qhelp/topics/images/. bugref:10348 bugref:10302

Location:
trunk/doc/manual
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/Makefile.kmk

    r99060 r99064  
    581581 #################################################################################################################################
    582582
    583 
    584  ##########################################################################################
    585  #
    586  #  DITA stuff common to pdf, qhelp, and html outputs.
    587  #  - copy DITA-OT library (binaries etc) since at each run several run-time config
    588  #     files are updated.
    589  #      - create dita/topic folder and copy all user manual dita files under that.
    590  #  - copy all images under dita/topics/images and UserManual.ditamap under dita folder
    591  #  - copy all man_V*.xml docbook files under dita/topic folder.
    592  #  - flatten refsect1/refsect2 hierarchy in man_V*.xml docbook files by
    593  #    using refsect2_to_refsect1.py.
    594  #  - convert man_V*.xml files into dita files
    595  #  - mark external link in the man_V*.dita files
    596  #  - correct all reference targets by calling correct_references.py.
    597  #
    598  #  Note! INSTALL_STAGING is likely to hardlink the files, thus we must use +| below
    599  #        when copying files as much won't change timestamp.  It would in fact be a _lot_
    600  #        better to copy the files individually.
    601  #
    602  ##########################################################################################
    603 
    604583 #
    605584 # 1. We copy/hardlink all the files under <lang>/dita/* to the corresponding
     
    761740
    762741
    763 
    764  ##########################################################################################
    765  #
    766  #  UserManual.html
    767  #
    768  ##########################################################################################
    769 
    770  $(VBOX_PATH_MANUAL_OUTBASE)/en_US/UserManual.zip: \
    771                 $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html
    772         $(call MSG_L1,Packing documentation $@)
    773         $(QUIET)$(RM) -f $@
    774         $(QUIET)$(REDIRECT) -C $(VBOX_PATH_MANUAL_OUTBASE)/en_US/ -- $(VBOX_ZIP) \
    775                 -9 -r $@ html-chunks
    776 
    777  $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html: \
    778                 $(VBOX_USER_MANUAL_DITA_STAGED_FILES_en_US) \
    779                 $(VBOX_USER_MANUAL_CONVERTED_REFENTRY_DITA_FILES_en_US)
    780         $(call MSG_L1,Building html chunks $@)
    781         $(QUIET)$(RM) -Rf -- "$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita-ot-html-chunks/"
    782         $(QUIET)$(call VBOX_DITA_RUN_DOST,$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita-ot-html-chunks) \
    783                 "/i:$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita/UserManual.ditamap" \
    784                 "/transtype:xhtml" \
    785                 "/outdir:$(@D)" \
    786                 "/tempdir:$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita/temp_xhtml" "/debug"
    787 
    788  # disable for now
    789  ## bird: Remove @chunk attrib from Glossary.dita topicref and add chunk="to-content" to bootmap for single html experiments.
    790  ##       See https://docs.oasis-open.org/dita/v1.2/os/spec/archSpec/chunking.html
    791  ##       and https://www.oxygenxml.com/forum/post25114.html?hilit=dita%20xhtml%20chunk#p25114
    792  ##       for further clues.
    793  #html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-single/UserManual.html
    794 
    795  html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html
    796  qhelp:: $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/en_US/qhelp/, $(VBOX_QHELP_OUTPUT_FILES))
    797  html-zip:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/UserManual.zip
    798 
    799  #
    800  # A few things which are shared between htmlhelp and qhelp docs.
    801  # TODO: This is Docbook related work.  Left here in case we can reuse some of
    802  #       the ideas from it for DITA-OT.
    803  #
    804 
    805  VBOX_DOCBOOK_HTMLHELP_FORMATCFG = \
    806         $(VBOX_PATH_MANUAL_SRC)/docbook-htmlhelp-formatcfg.xsl \
    807         $(VBOX_PATH_MANUAL_SRC)/common-formatcfg.xsl \
    808         $(VBOX_PATH_MANUAL_SRC)/common-html-formatcfg.xsl
    809 
    810  # Prepare the XSL file for our title page, htmlhelp and qhelp variant.
    811  $(VBOX_PATH_MANUAL_OUTBASE)/titlepage-htmlhelp.xsl: \
    812                 $(VBOX_PATH_MANUAL_SRC)/titlepage-htmlhelp.xml $(MAKEFILE_CURRENT) | $$(dir $$@)
    813         $(call MSG_L1,xsltproc $<)
    814         $(QUIET)$(RM) -f [email protected] $@
    815         $(QUIET)$(VBOX_XSLTPROC) --xinclude --nonet -o [email protected] $(VBOX_PATH_DOCBOOK)/template/titlepage.xsl $<
    816         $(QUIET)$(MV) -f [email protected] $@
    817 
    818 
    819  ##########################################################################################
    820  #
    821  #  Use DITA-OT to create pdf/hhp out of UserManual.ditamap. See usermanual.pdf under
    822  #  DITA-OT-xxxxx/doc folder for details.
    823  #
    824  ##########################################################################################
    825 
    826 
    827  # Note! The /tempdir is deleted, recreated, used and deleted again for each run. So, be careful where you point it.
     742 #
     743 # 3a. UserManual.pdf - Run dost.jar from DITA-OT to produce the PDF version.
     744 #
     745 # Note! The /tempdir is deleted, recreated, used and deleted again for each
     746 #       run. So, be careful where you point it.
    828747 # Note! This crappy utility may fail to find files (or fail to parse the
    829748 #       command line) and still return a successfully (0) exit code.
     749 #
    830750 define def_ditamap_to_pdf
    831751  $$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/UserManual.pdf \
     
    852772 usermanual UserManual.pdf:: $(PATH_STAGE_BIN)/UserManual.pdf
    853773
     774
     775 #
     776 # 3b. UserManual.html - Run dost.jar from DITA-OT to produce the HTML versions.
     777 #
     778 # We produce both chunked and singled paged HTML versions of the en_US manual
     779 # mainly for uploading to virtualbox.org.  The docs build box produces a zip
     780 # including these.
     781 #
     782
     783 $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html: \
     784                $(VBOX_USER_MANUAL_DITA_STAGED_FILES_en_US) \
     785                $(VBOX_USER_MANUAL_CONVERTED_REFENTRY_DITA_FILES_en_US)
     786        $(call MSG_L1,Building html chunks $@)
     787        $(QUIET)$(RM) -Rf -- "$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita-ot-html-chunks/"
     788        $(QUIET)$(call VBOX_DITA_RUN_DOST,$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita-ot-html-chunks) \
     789                "/i:$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita/UserManual.ditamap" \
     790                "/transtype:xhtml" \
     791                "/outdir:$(@D)" \
     792                "/tempdir:$(VBOX_PATH_MANUAL_OUTBASE)/en_US/dita/temp_xhtml" # "/debug"
     793
     794 # disable for now
     795 ## bird: Remove @chunk attrib from Glossary.dita topicref and add chunk="to-content" to bootmap for single html experiments.
     796 ##       See https://docs.oasis-open.org/dita/v1.2/os/spec/archSpec/chunking.html
     797 ##       and https://www.oxygenxml.com/forum/post25114.html?hilit=dita%20xhtml%20chunk#p25114
     798 ##       for further clues.
     799 #html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-single/UserManual.html
     800
     801 $(VBOX_PATH_MANUAL_OUTBASE)/en_US/UserManual.zip: \
     802                $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html
     803        $(call MSG_L1,Packing documentation $@)
     804        $(QUIET)$(RM) -f $@
     805        $(QUIET)$(REDIRECT) -C $(VBOX_PATH_MANUAL_OUTBASE)/en_US/ -- $(VBOX_ZIP) \
     806                -9 -r $@ html-chunks
     807
     808 html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/html-chunks/index.html
     809 html-zip:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/UserManual.zip
     810
     811
     812 #
     813 # A few things which are shared between htmlhelp and qhelp docs.
     814 # TODO: This is Docbook related work.  Left here in case we can reuse some of
     815 #       the ideas from it for DITA-OT.
     816 #
     817
     818 VBOX_DOCBOOK_HTMLHELP_FORMATCFG = \
     819        $(VBOX_PATH_MANUAL_SRC)/docbook-htmlhelp-formatcfg.xsl \
     820        $(VBOX_PATH_MANUAL_SRC)/common-formatcfg.xsl \
     821        $(VBOX_PATH_MANUAL_SRC)/common-html-formatcfg.xsl
     822
     823 # Prepare the XSL file for our title page, htmlhelp and qhelp variant.
     824 $(VBOX_PATH_MANUAL_OUTBASE)/titlepage-htmlhelp.xsl: \
     825                $(VBOX_PATH_MANUAL_SRC)/titlepage-htmlhelp.xml $(MAKEFILE_CURRENT) | $$(dir $$@)
     826        $(call MSG_L1,xsltproc $<)
     827        $(QUIET)$(RM) -f [email protected] $@
     828        $(QUIET)$(VBOX_XSLTPROC) --xinclude --nonet -o [email protected] $(VBOX_PATH_DOCBOOK)/template/titlepage.xsl $<
     829        $(QUIET)$(MV) -f [email protected] $@
     830
     831 # end old stuff.
     832
     833 if defined(VBOX_WITH_DOCS_QHELP) && !defined(VBOX_ONLY_SDK)
     834  #
     835  # 3c. VirtualBox.qch + VirtualBox.qhc - Qt compressed help and collection file.
     836  #
     837  # See usermanual.pdf under DITA-OT-xxxxx/doc folder for details.
     838  #
     839
     840  # Enable Qt and locate the Qt help generator.
     841  ifdef VBOX_WITH_QT6
     842   USES += qt6
     843   VBOX_QHELPGENERATOR = $(PATH_TOOL_QT6_LIBEXEC)/qhelpgenerator
     844  else
     845   USES += qt5
     846   VBOX_QHELPGENERATOR_VERSION_MINOR = $(shell $(REDIRECT) -E QT_QPA_PLATFORM_PLUGIN_PATH=$(PATH_SDK_QT5)/plugins -- $(PATH_TOOL_QT5_BIN)/qhelpgenerator -v 2>/dev/null | $(SED) -ne 's/.*(Qt [1-9][0-9]*\.\([1-9][0-9]*\)\.[1-9][0-9]*).*$$/\1/p')
     847   VBOX_QHELPGENERATOR = $(PATH_TOOL_QT5_BIN)/$(if-expr $(VBOX_QHELPGENERATOR_VERSION_MINOR) >= 12,qhelpgenerator,qcollectiongenerator)
     848  endif
     849
     850  ## Build QHelp version of manual for given language.
     851  # @param 1   Language
     852  # @param 2    The language specific qhelp output directory.
     853  define def_vbox_usermanual_as_qhelp
     854
     855   # 1. Generate UserManual.hpp using DITA-OT.
     856   #
     857   # Setting HHCDIR here so that it fails to locate hcc.exe and always skips the
     858   # compilation step that produces the .chm-file, since we don't need it and it
     859   # mangles the path so it always fails anyway.
     860   $(2)/UserManual.hhp: \
     861                $(VBOX_USER_MANUAL_DITA_STAGED_FILES_$(1)) \
     862                $(VBOX_USER_MANUAL_CONVERTED_REFENTRY_DITA_FILES_$(1))
     863        $$(QUIET)$(RM) -Rf -- "$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita-ot-qhelp/"
     864        $$(QUIET)$$(call VBOX_DITA_RUN_DOST,$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita-ot-qhelp, -EHHCDIR="$$(@D)") \
     865                "/i:$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita/UserManual.ditamap" \
     866                "/transtype:htmlhelp" \
     867                "/outdir:$(2)" \
     868                "/tempdir:$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita/temp_qhelp"
     869
     870   ditamap-to-htmlhelp: $(2)/UserManual.hhp
     871
     872   # 2. Generate a Qt Help Project file (QHP) using htmlhelp-qthelp.py.
     873   $(2)/UserManual.qhp: \
     874                $(2)/UserManual.hhp \
     875                $$(VBOX_PATH_MANUAL_SRC)/htmlhelp-qthelp.py \
     876                | $$$$(dir $$$$@)
     877        $$(call MSG_L1,htmlhelp-qthelp.py $$<,=> $$@)
     878        $$(QUIET)$$(RM) -f -- "$$@"
     879        $$(QUIET)$$(VBOX_BLD_PYTHON) $$(VBOX_PATH_MANUAL_SRC)/htmlhelp-qthelp.py \
     880                -d "$$(<D)" -o "$$@" -f UserManual.hhp -t UserManual.hhc
     881
     882   # 3. Copy the Qt help configuration file from source to the output dir.
     883   $(2)/UserManual.qhcp: $$(VBOX_PATH_MANUAL_SRC)/UserManual.qhcp | $$$$(dir $$$$@)
     884        $$(QUIET)$$(INSTALL_STAGING) -m0644 -- '$$<' '$$(@D)'
     885
     886   # 4. Run the Qt help generator to produce the .qhp and .qch files.
     887   $(2)/UserManual.qch \
     888   + $(2)/UserManual.qhc: \
     889                $(2)/UserManual.qhcp \
     890                $(2)/UserManual.qhp \
     891                | $$$$(dir $$$$@)
     892        $$(call MSG_L1,$$(notdir $$(VBOX_QHELPGENERATOR)) $$<,=> $$@)
     893        $$(QUIET)$$(RM) -f $$@
     894   ifdef VBOX_WITH_QT6
     895        $$(QUIET)$$(REDIRECT) -- $$(VBOX_QHELPGENERATOR) $$<
     896   else
     897        $$(QUIET)$$(REDIRECT) -E QT_QPA_PLATFORM_PLUGIN_PATH=$$(PATH_SDK_QT5)/plugins -- $$(VBOX_QHELPGENERATOR) $$<
     898   endif
     899        $$(call MSG_L1,Fresh QCH is now at $$@)
     900
     901  endef # def_vbox_usermanual_as_qhelp
     902
     903  $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES) \
     904        ,$(evalcall2 def_vbox_usermanual_as_qhelp,$(lang),$(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/qhelp))
     905
     906  qhelp:: $(addprefix $(VBOX_PATH_MANUAL_OUTBASE)/en_US/qhelp/, $(VBOX_QHELP_OUTPUT_FILES))
     907
     908 endif # VBOX_WITH_DOCS_QHELP && !VBOX_ONLY_SDK
     909
     910
     911 #################################################################################################################################
     912 #      Miscellaneous                                                                                                            #
     913 #################################################################################################################################
     914
    854915 #
    855916 # ChangeLog.html
     
    870931
    871932 cl-html:: $(VBOX_PATH_MANUAL_OUTBASE)/en_US/ChangeLog.html
    872 
    873933
    874934
     
    925985
    926986
    927  if defined(VBOX_WITH_DOCS_QHELP) && !defined(VBOX_ONLY_SDK)
    928   #
    929   # VirtualBox.qch/VirtualBox.qhc
    930   #
    931   # We first generate a .hhp help source file from the preprocessed
    932   # DocBook XML files, as defined above, then feed that into a converter
    933   # creating the suitable input for creating a QHelp collection file.
    934   #
    935 
    936   # Enable Qt and locate the Qt help generator.
    937   ifdef VBOX_WITH_QT6
    938    USES += qt6
    939    VBOX_QHELPGENERATOR = $(PATH_TOOL_QT6_LIBEXEC)/qhelpgenerator
    940   else
    941    USES += qt5
    942    VBOX_QHELPGENERATOR_VERSION_MINOR = $(shell $(REDIRECT) -E QT_QPA_PLATFORM_PLUGIN_PATH=$(PATH_SDK_QT5)/plugins -- $(PATH_TOOL_QT5_BIN)/qhelpgenerator -v 2>/dev/null | $(SED) -ne 's/.*(Qt [1-9][0-9]*\.\([1-9][0-9]*\)\.[1-9][0-9]*).*$$/\1/p')
    943    VBOX_QHELPGENERATOR = $(PATH_TOOL_QT5_BIN)/$(if-expr $(VBOX_QHELPGENERATOR_VERSION_MINOR) >= 12,qhelpgenerator,qcollectiongenerator)
    944   endif
    945 
    946   # Generate QCH from QHelp source
    947   # Note: out_dir referenced with double $$ to delay expansion to the eval step when out_dir has been defined.
    948   define def_vbox_usermanual_qhp_to_qch
    949    local out_dir := $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)
    950    $$(out_dir)/qhelp/UserManual.qch \
    951    + $$(out_dir)/qhelp/UserManual.qhc: \
    952                 $$(out_dir)/qhelp/UserManual.qhcp \
    953                 $$(out_dir)/qhelp/UserManual.qhp \
    954                 $$(addprefix $$(out_dir)/qhelp/,$$(VBOX_MANUAL_PNG_FILES_$(lang))) \
    955                 | $$$$(dir $$$$@)
    956         $$(call MSG_L1,$$(notdir $$(VBOX_QHELPGENERATOR)) $$<,=> $$@)
    957         $$(QUIET)$$(RM) -f $$@
    958         $$(QUIET)$$(REDIRECT) -E QT_QPA_PLATFORM_PLUGIN_PATH=$$(PATH_SDK_QT5)/plugins -- $$(VBOX_QHELPGENERATOR) $$<
    959         $$(call MSG_L1,Fresh QCH is now at $$@)
    960   endef
    961   $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES),$(evalcall2 def_vbox_usermanual_qhp_to_qch))
    962 
    963   # Generate QHP from HHP for QHelp
    964   # Note: out_dir referenced with double $$ to delay expansion to the eval step when out_dir has been defined.
    965   define def_vbox_usermanual_hhp_qhelp_to_qhp
    966    local out_dir := $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)
    967    $$(out_dir)/qhelp/UserManual.qhp: \
    968                 $$(out_dir)/qhelp/UserManual.hhp \
    969                 $$(addprefix $$(out_dir)/qhelp/,$$(VBOX_MANUAL_PNG_FILES_$(lang))) \
    970                 | $$$$(dir $$$$@)
    971         $$(call MSG_L1,htmlhelp-qthelp.py $$<,=> $$@)
    972         $$(QUIET)$$(RM) -f $$@
    973         $$(QUIET)$$(VBOX_BLD_PYTHON) $$(VBOX_PATH_MANUAL_SRC)/htmlhelp-qthelp.py -d $$(<D) -o $$@ -f UserManual.hhp -t UserManual.hhc
    974   endef
    975   $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES),$(evalcall2 def_vbox_usermanual_hhp_qhelp_to_qhp))
    976 
    977   # Setting HHCDIR here so that it fails to locate hcc.exe and always skips the
    978   # compilation step that produces the .chm-file, since we don't need it and it
    979   # mangles the path so it always fails anyway.
    980   define def_ditamap_to_htmlhelp
    981    ditamap-to-htmlhelp: $$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/qhelp/UserManual.hhp
    982    $$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/qhelp/UserManual.hhp: \
    983                 $(VBOX_USER_MANUAL_DITA_STAGED_FILES_$(1)) \
    984                 $(VBOX_USER_MANUAL_CONVERTED_REFENTRY_DITA_FILES_$(1))
    985         $$(QUIET)$(RM) -Rf -- "$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita-ot-qhelp/"
    986         $$(QUIET)$$(call VBOX_DITA_RUN_DOST,$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita-ot-qhelp, -EHHCDIR="$$(@D)") \
    987                 "/i:$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita/UserManual.ditamap" \
    988                 "/transtype:htmlhelp" \
    989                 "/outdir:$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/qhelp" \
    990                 "/tempdir:$$(VBOX_PATH_MANUAL_OUTBASE)/$(1)/dita/temp_htmlhelp"
    991 
    992   endef
    993   $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES),$(evalcall2 def_ditamap_to_htmlhelp,$(lang)))
    994 
    995   # copy the qhcp file.
    996   define def_vbox_cp_qhcp
    997    local out_dir := $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/qhelp
    998    $$(out_dir)/UserManual.qhcp: \
    999                 $$(out_dir)/% : $(VBOX_PATH_MANUAL_SRC)/% | $$$$(dir $$$$@)
    1000         $$(QUIET)$$(INSTALL_STAGING) -m0644 -- '$$<' '$$(@D)'
    1001   endef
    1002   $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES),$(eval $(def_vbox_cp_qhcp)))
    1003 
    1004   # copy the PNG files.
    1005   # Note: out_dir referenced with double $$ to delay expansion to the eval step when out_dir has been defined.
    1006   define def_vbox_cp_images_qhelp
    1007    local out_dir := $(VBOX_PATH_MANUAL_OUTBASE)/$(lang)/qhelp
    1008    $(addprefix $$(out_dir)/,$(VBOX_MANUAL_PNG_FILES_$(lang))): \
    1009                 $$(out_dir)/% : $(VBOX_PATH_MANUAL_SRC)/$(lang)/% | $$$$(dir $$$$@)
    1010         $$(call MSG_L1,Copying temporary $$< => $$@)
    1011         $$(QUIET)$$(INSTALL_STAGING) -m0644 -- '$$<' '$$(@D)'
    1012   endef
    1013   $(foreach lang,$(VBOX_MANUAL_ALL_LANGUAGES),$(eval $(def_vbox_cp_images_qhelp)))
    1014 
    1015  endif # VBOX_WITH_DOCS_QHELP && !VBOX_ONLY_SDK
    1016 
    1017 
    1018987 #
    1019988 # Packing the docs into a zip file (part of the packing pass on the docs build box).
  • trunk/doc/manual/htmlhelp-qthelp.py

    r98950 r99064  
    11#!/usr/bin/python3
    2 
     2# -*- coding: utf-8 -*-
    33# $Id$
    4 ## @file
    5 # A python script to create a .qhp file out of a given htmlhelp
    6 # folder. Lots of things about the said folder is assumed. Please
    7 # see the code and inlined comments.
    8 
    9 import sys, getopt
    10 import os.path
    11 import re
    12 import logging
    13 
    14 if sys.version_info >= (3, 0):
    15     from html.parser import HTMLParser
    16 else:
    17     from HTMLParser import HTMLParser
    18 
    19 
     4
     5"""
     6A python script to create a .qhp file out of a given htmlhelp
     7folder. Lots of things about the said folder is assumed. Please
     8see the code and inlined comments.
     9"""
    2010
    2111__copyright__ = \
     
    4232"""
    4333
     34import getopt
     35import logging
     36import os.path
     37import re
     38import sys
     39
     40if sys.version_info[0] >= 3:
     41    from html.parser import HTMLParser
     42else:
     43    from HTMLParser import HTMLParser
     44
    4445# number of opened and not yet closed section tags of toc section
    4546open_section_tags = 0
     
    4748html_files = []
    4849
    49 # use html_parser stuff to collect <a name tags
    5050def create_keywords_section(folder):
     51    """
     52    use html_parser stuff to collect <a name ...> tags
     53    """
    5154    keywords_section_lines = ['<keywords>']
    5255    for html_file_name in html_files:
     
    5558
    5659        class html_parser(HTMLParser):
    57           def __init__(self):
    58             HTMLParser.__init__(self)
    59             self.a_tag=[]
    60           def handle_starttag(self, tag, attributes):
    61             if tag != 'div' and tag != 'a':
    62               return
    63             if tag == 'a':
    64               for a in attributes:
    65                 if a[0] == 'name':
    66                   self.a_tag.append(a[1])
     60            def __init__(self):
     61                HTMLParser.__init__(self)
     62                self.a_tag = []
     63            def handle_starttag(self, tag, attrs):
     64                if tag != 'div' and tag != 'a':
     65                    return
     66                if tag == 'a':
     67                    for a in attrs:
     68                        if a[0] == 'name':
     69                            self.a_tag.append(a[1])
    6770
    6871        parser = html_parser()
     
    7073        for k in parser.a_tag:
    7174            line = '<keyword name="' + k + '" id="' + k + '" ref="' + html_file_name + '#' + k + '"/>'
    72             keywords_section_lines.append(line);
     75            keywords_section_lines.append(line)
    7376    keywords_section_lines.append('</keywords>')
    7477    return keywords_section_lines
    7578
    76 # find the png files under /images folder and create a part of the
    77 # qhelp project file with <file> tags
    7879def create_image_list(folder):
    79     image_folder_name = 'images'
    80     image_files_list = []
    81     # Look for 'images' sub folder
    82     subdirs = [x[0] for x in os.walk(folder)]
    83     full_folder_path = os.path.join(folder, image_folder_name)
    84     if full_folder_path not in subdirs:
    85         logging.error('Image subfolder "%s" is not found under "%s".', image_folder_name, folder)
    86         return image_files_list;
    87     png_files = []
    88     for f in os.listdir(full_folder_path):
    89         png_files.append(image_folder_name + '/' + f)
    90         image_files_list.append('<file>images/' + f + '</file>')
    91     return image_files_list
    92 
    93 # open files list and read the list of html files from there
     80    """
     81    find the png files under topics/images folder and create a part of the
     82    qhelp project file with <file> tags
     83    """
     84    sFullImageFolderPath = os.path.join(folder, 'topics', 'images');
     85    if not os.path.isdir(sFullImageFolderPath):
     86        logging.error('Image subfolder "topics/images" is not found under "%s"!', folder)
     87        sys.exit(1);
     88    return ['<file>topics/images/%s</file>' % sFile for sFile in os.listdir(sFullImageFolderPath)];
     89
    9490def create_html_list(folder, list_file):
     91    """
     92    open files list and read the list of html files from there
     93    """
    9594    global html_files
    9695    html_file_lines = []
     
    9998        return html_file_lines
    10099    full_path = os.path.join(folder, list_file)
    101     file = open(full_path, encoding='utf-8')
    102 
    103     lines = file.readlines()
    104     file.close()
     100    with open(full_path, encoding='utf-8') as file:
     101        lines = file.readlines()
     102
    105103    # first search for the [FILES] marker then collect .html lines
    106104    marker_found = 0
     
    126124def parse_param_tag(line):
    127125    label = 'value="'
    128     start = line.find(label);
     126    start = line.find(label)
    129127    if start == -1:
    130128        return ''
    131     start +=  len(label)
     129    start += len(label)
    132130    end = line.find('"', start)
    133131    if end == -1:
    134         return '';
     132        return ''
    135133    return line[start:end]
    136134
    137 # look at next two lines. they are supposed to look like the following
    138 #      <param name="Name" value="Oracle VM VirtualBox">
    139 #      <param name="Local" value="index.html">
    140 # parse out value fields and return
    141 # title="Oracle VM VirtualBox" ref="index.html
    142135def parse_object_tag(lines, index):
    143     result=''
     136    """
     137    look at next two lines. they are supposed to look like the following
     138         <param name="Name" value="Oracle VM VirtualBox">
     139         <param name="Local" value="index.html">
     140    parse out value fields and return
     141    title="Oracle VM VirtualBox" ref="index.html
     142    """
     143    result = ''
    144144    if index + 2 > len(lines):
    145         logging.warning('Not enough tags after this one "%s"',lines[index])
     145        logging.warning('Not enough tags after this one "%s"', lines[index])
    146146        return result
    147     if not re.match(r'^\s*<param', lines[index + 1], re.IGNORECASE) or \
    148        not re.match(r'^\s*<param', lines[index + 2], re.IGNORECASE):
    149         logging.warning('Skipping the line "%s" since next two tags are supposed to be param tags',  lines[index])
     147    if    not re.match(r'^\s*<param', lines[index + 1], re.IGNORECASE) \
     148       or not re.match(r'^\s*<param', lines[index + 2], re.IGNORECASE):
     149        logging.warning('Skipping the line "%s" since next two tags are supposed to be param tags', lines[index])
    150150        return result
    151151    title = parse_param_tag(lines[index + 1])
     
    159159    return result
    160160
    161 # parse any string other than staring with <OBJECT
    162 # decide if <session tag should be closed
    163161def parse_non_object_tag(lines, index):
     162    """
     163    parse any string other than staring with <OBJECT
     164    decide if <section> tag should be closed
     165    """
     166
    164167    if index + 1 > len(lines):
    165168        return ''
     
    178181
    179182def parse_line(lines, index):
    180     result=''
     183    result = ''
    181184
    182185    # if the line starts with <OBJECT
     
    187190    return result
    188191
    189 # parse TOC file. assuming all the relevant information
    190 # is stored in tags and attributes. whatever is outside of
    191 # <... > pairs is filtered out. we also assume < ..> are not nested
    192 # and each < matches to a >
    193192def create_toc(folder, toc_file):
     193    """
     194    parse TOC file. assuming all the relevant information
     195    is stored in tags and attributes. whatever is outside of
     196    <... > pairs is filtered out. we also assume < ..> are not nested
     197    and each < matches to a >
     198    """
    194199    toc_string_list = []
    195200    content = [x[2] for x in os.walk(folder)]
     
    198203        return toc_string_list
    199204    full_path = os.path.join(folder, toc_file)
    200     file = open(full_path, encoding='utf-8')
    201     content = file.read()
    202     file.close()
     205    with open(full_path, encoding='utf-8') as file:
     206        content = file.read()
     207
    203208    # convert the file string into a list of tags there by eliminating whatever
    204209    # char reside outside of tags.
     
    219224    # lines = content.split('\n')
    220225    toc_string_list.append('<toc>')
    221     index = 0
    222     for tag in tag_list:
     226    for index, _ in enumerate(tag_list):
    223227        str = parse_line(tag_list, index)
    224228        if str:
    225229            toc_string_list.append(str)
    226         index += 1
    227230    toc_string_list.append('</toc>')
    228231    toc_string = '\n'.join(toc_string_list)
     
    230233    return toc_string_list
    231234
    232 def usage(arg):
     235def usage(iExitCode):
    233236    print('htmlhelp-qthelp.py -d <helphtmlfolder> -o <outputfilename>')
    234     sys.exit()
     237    return iExitCode
    235238
    236239def main(argv):
     240    # Parse arguments.
    237241    helphtmlfolder = ''
    238242    output_filename = ''
     
    240244    toc_file = ''
    241245    try:
    242         opts, args = getopt.getopt(sys.argv[1:],"hd:o:f:t:")
     246        opts, _ = getopt.getopt(argv[1:], "hd:o:f:t:")
    243247    except getopt.GetoptError as err:
    244         print(err)
    245         usage(2)
     248        logging.error(str(err))
     249        return usage(2)
    246250    for opt, arg in opts:
    247251        if opt == '-h':
    248             usage(0)
    249         elif opt in ("-d"):
     252            return usage(0)
     253        if opt == "-d":
    250254            helphtmlfolder = arg
    251255            print(helphtmlfolder)
    252         elif opt in ("-f"):
     256        elif opt == "-f":
    253257            list_file = arg
    254         elif opt in ("-t"):
     258        elif opt == "-t":
    255259            toc_file = arg
    256260            print(toc_file)
    257         elif opt in ("-o"):
    258              output_filename = arg
     261        elif opt == "-o":
     262            output_filename = arg
    259263    # check supplied helphtml folder argument
    260264    if not helphtmlfolder:
    261265        logging.error('No helphtml folder is provided. Exiting')
    262         usage(2)
     266        return usage(2)
    263267    if not os.path.exists(helphtmlfolder):
    264268        logging.error('folder "%s" does not exist. Exiting', helphtmlfolder)
    265         usage(2)
     269        return usage(2)
    266270    helphtmlfolder = os.path.normpath(helphtmlfolder)
    267271
     
    269273    if not output_filename:
    270274        logging.error('No filename for output is given. Exiting')
    271         usage(2)
    272 
    273     out_xml_lines = ['<?xml version="1.0" encoding="UTF-8"?>', \
    274                      '<QtHelpProject version="1.0">' , \
    275                      '<namespace>org.virtualbox</namespace>', \
    276                      '<virtualFolder>doc</virtualFolder>', \
     275        return usage(2)
     276
     277    out_xml_lines = ['<?xml version="1.0" encoding="UTF-8"?>',
     278                     '<QtHelpProject version="1.0">',
     279                     '<namespace>org.virtualbox</namespace>',
     280                     '<virtualFolder>doc</virtualFolder>',
    277281                     '<filterSection>']
    278     out_xml_lines += create_toc(helphtmlfolder, toc_file) + create_files_section(helphtmlfolder, list_file)
     282    out_xml_lines += create_toc(helphtmlfolder, toc_file)
     283    out_xml_lines += create_files_section(helphtmlfolder, list_file)
    279284    out_xml_lines += create_keywords_section(helphtmlfolder)
    280285    out_xml_lines += ['</filterSection>', '</QtHelpProject>']
    281286
    282     out_file = open(output_filename, 'wb')
    283     out_file.write('\n'.join(out_xml_lines).encode('utf8'))
    284     out_file.close()
     287    with open(output_filename, 'wb') as out_file:
     288        out_file.write('\n'.join(out_xml_lines).encode('utf8'))
     289    return 0
    285290
    286291if __name__ == '__main__':
    287     main(sys.argv[1:])
     292    sys.exit(main(sys.argv))
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette