Wed, 21 Sep 2022 15:36:01 +0200
Reformatted source code with 'Black'.
--- a/.hgignore Thu Dec 30 12:22:34 2021 +0100 +++ b/.hgignore Wed Sep 21 15:36:01 2022 +0200 @@ -1,6 +1,7 @@ glob:.eric6project glob:.eric7project glob:.ropeproject +glob:.jedi glob:.directory glob:**.pyc glob:**.pyo
--- a/PluginProjectWeb.py Thu Dec 30 12:22:34 2021 +0100 +++ b/PluginProjectWeb.py Wed Sep 21 15:36:01 2022 +0200 @@ -18,7 +18,8 @@ import Preferences try: - from bs4 import BeautifulSoup # __IGNORE_EXCEPTION__ + from bs4 import BeautifulSoup # __IGNORE_EXCEPTION__ + BeautifulSoupAvailable = True except ImportError: BeautifulSoup = None @@ -43,62 +44,66 @@ # End-Of-Header error = "" - + class ProjectWebPlugin(QObject): """ Class implementing the Web project plugin. """ + def __init__(self, ui): """ Constructor - + @param ui reference to the user interface object @type UserInterface """ super().__init__(ui) self.__ui = ui self.__initialize() - + self.__translator = None self.__loadTranslator() - + self.__initMenu() - + def __initialize(self): """ Private slot to (re)initialize the plugin. """ self.__ericProject = ericApp().getObject("Project") - + self.__editors = {} self.__mainActions = [] - + def activate(self): """ Public method to activate this plugin. - + @return tuple of None and activation status @rtype tuple of (None, bool) """ global error - error = "" # clear previous error - + error = "" # clear previous error + # it is not registered for a specific programming language self.__ericProject.registerProjectType( - "Web", self.tr("Web"), - self.fileTypesCallback) - + "Web", self.tr("Web"), self.fileTypesCallback + ) + from Project.ProjectBrowser import ( - SourcesBrowserFlag, FormsBrowserFlag, OthersBrowserFlag + SourcesBrowserFlag, + FormsBrowserFlag, + OthersBrowserFlag, ) + Preferences.setProjectBrowserFlagsDefault( "Web", SourcesBrowserFlag | FormsBrowserFlag | OthersBrowserFlag, ) - + self.__ui.showMenu.connect(self.__populateMenu) - + menu = self.__ui.getMenu("plugin_tools") if menu is not None: if not menu.isEmpty(): @@ -106,25 +111,23 @@ self.__mainActions.append(act) act = menu.addMenu(self.__menu) self.__mainActions.append(act) - - ericApp().getObject("ViewManager").editorOpenedEd.connect( - self.__editorOpened) - ericApp().getObject("ViewManager").editorClosedEd.connect( - self.__editorClosed) - + + ericApp().getObject("ViewManager").editorOpenedEd.connect(self.__editorOpened) + ericApp().getObject("ViewManager").editorClosedEd.connect(self.__editorClosed) + for editor in ericApp().getObject("ViewManager").getOpenEditors(): self.__editorOpened(editor) - + return None, True - + def deactivate(self): """ Public method to deactivate this plugin. """ self.__ericProject.unregisterProjectType("Web") - + self.__ui.showMenu.disconnect(self.__populateMenu) - + menu = self.__ui.getMenu("plugin_tools") if menu is not None: for act in self.__mainActions: @@ -132,19 +135,21 @@ self.__mainActions = [] ericApp().getObject("ViewManager").editorOpenedEd.disconnect( - self.__editorOpened) + self.__editorOpened + ) ericApp().getObject("ViewManager").editorClosedEd.disconnect( - self.__editorClosed) - + self.__editorClosed + ) + for editor, acts in self.__editors.items(): editor.showMenu.disconnect(self.__editorShowMenu) menu = editor.getMenu("Tools") if menu is not None: for act in acts: menu.removeAction(act) - + self.__initialize() - + def __loadTranslator(self): """ Private method to load the translation file. @@ -153,7 +158,8 @@ loc = self.__ui.getLocale() if loc and loc != "C": locale_dir = os.path.join( - os.path.dirname(__file__), "ProjectWeb", "i18n") + os.path.dirname(__file__), "ProjectWeb", "i18n" + ) translation = "web_{0}".format(loc) translator = QTranslator(None) loaded = translator.load(translation, locale_dir) @@ -161,14 +167,16 @@ self.__translator = translator ericApp().installTranslator(self.__translator) else: - print("Warning: translation file '{0}' could not be" - " loaded.".format(translation)) + print( + "Warning: translation file '{0}' could not be" + " loaded.".format(translation) + ) print("Using default.") - + def fileTypesCallback(self): """ Public method to get the filetype associations of the Web project type. - + @return dictionary with file type associations @rtype dict """ @@ -180,43 +188,46 @@ } else: return {} - + def __initMenu(self): """ Private method to initialize the web tools menu. """ self.__menu = QMenu(self.tr("Web")) - - self.__html5ToCss3Act = self.__menu.addAction(self.tr( - "HTML5 to CSS3"), self.__html5ToCss3) - self.__html5ToJsAct = self.__menu.addAction(self.tr( - "HTML5 to JavaScript"), self.__html5ToJs) + + self.__html5ToCss3Act = self.__menu.addAction( + self.tr("HTML5 to CSS3"), self.__html5ToCss3 + ) + self.__html5ToJsAct = self.__menu.addAction( + self.tr("HTML5 to JavaScript"), self.__html5ToJs + ) self.__menu.addSeparator() - self.__html5PrettifyAct = self.__menu.addAction(self.tr( - "Prettify HTML"), self.__html5Prettify) - + self.__html5PrettifyAct = self.__menu.addAction( + self.tr("Prettify HTML"), self.__html5Prettify + ) + self.__menu.aboutToShow.connect(self.__menuAboutToShow) - + def __menuAboutToShow(self): """ Private slot to prepare the menu before it is shown. """ editor = ericApp().getObject("ViewManager").activeWindow() selectionAvailable = bool(editor and editor.selectedText() != "") - isHtml = bool(editor and - editor.getLanguage().lower().startswith("html")) - + isHtml = bool(editor and editor.getLanguage().lower().startswith("html")) + self.__html5ToCss3Act.setEnabled( - selectionAvailable and BeautifulSoupAvailable and isHtml) + selectionAvailable and BeautifulSoupAvailable and isHtml + ) self.__html5ToJsAct.setEnabled( - selectionAvailable and BeautifulSoupAvailable and isHtml) - self.__html5PrettifyAct.setEnabled( - BeautifulSoupAvailable and isHtml) - + selectionAvailable and BeautifulSoupAvailable and isHtml + ) + self.__html5PrettifyAct.setEnabled(BeautifulSoupAvailable and isHtml) + def __populateMenu(self, name, menu): """ Private slot to populate the tools menu with our entries. - + @param name name of the menu @type str @param menu reference to the menu to be populated @@ -224,16 +235,16 @@ """ if name not in ["Tools", "PluginTools"]: return - + if name == "Tools": if not menu.isEmpty(): menu.addSeparator() menu.addMenu(self.__menu) - + def __editorOpened(self, editor): """ Private slot called, when a new editor was opened. - + @param editor reference to the new editor @type Editor """ @@ -246,22 +257,22 @@ act = menu.addMenu(self.__menu) self.__editors[editor].append(act) editor.showMenu.connect(self.__editorShowMenu) - + def __editorClosed(self, editor): """ Private slot called, when an editor was closed. - + @param editor reference to the editor @type Editor """ with contextlib.suppress(KeyError): del self.__editors[editor] - + def __editorShowMenu(self, menuName, menu, editor): """ Private slot called, when the the editor context menu or a submenu is about to be shown. - + @param menuName name of the menu to be shown @type str @param menu reference to the menu @@ -269,10 +280,7 @@ @param editor reference to the editor @type Editor """ - if ( - menuName == "Tools" and - self.__menu.menuAction() not in menu.actions() - ): + if menuName == "Tools" and self.__menu.menuAction() not in menu.actions(): # Re-add our menu self.__editors[editor] = [] if not menu.isEmpty(): @@ -280,76 +288,80 @@ self.__editors[editor].append(act) act = menu.addMenu(self.__menu) self.__editors[editor].append(act) - + def __html5ToCss3(self): """ Private slot handling the HTML5 to CSS3 conversion. """ from ProjectWeb.Html5ToCss3Converter import Html5ToCss3Converter + vm = ericApp().getObject("ViewManager") editor = vm.activeWindow() html = editor.selectedText() - + converter = Html5ToCss3Converter(html) css3 = converter.getCss3() - + if css3: vm.newEditor() newEditor = vm.activeWindow() newEditor.setText(css3) newEditor.setLanguage("dummy.css") - + def __html5ToJs(self): """ Private slot handling the HTML5 to JavaScript conversion. """ from ProjectWeb.Html5ToJsConverter import Html5ToJsConverter + vm = ericApp().getObject("ViewManager") editor = vm.activeWindow() html = editor.selectedText() - + converter = Html5ToJsConverter(html) js = converter.getJavaScript() - + if js: vm.newEditor() newEditor = vm.activeWindow() newEditor.setText(js) newEditor.setLanguage("dummy.js") - + def __html5Prettify(self): """ Private slot handling the Prettify HTML action. """ from ProjectWeb.Html5Prettifier import Html5Prettifier + editor = ericApp().getObject("ViewManager").activeWindow() html = editor.text() - + prettifier = Html5Prettifier(html) newHtml = prettifier.getPrettifiedHtml() - + if newHtml and newHtml != html: cursorLine, cursorIndex = editor.getCursorPosition() - + editor.beginUndoAction() editor.selectAll() editor.replaceSelectedText(newHtml) editor.endUndoAction() - + editor.setCursorPosition(cursorLine, cursorIndex) def installDependencies(pipInstall): """ Function to install dependencies of this plug-in. - + @param pipInstall function to be called with a list of package names. @type function """ try: - import bs4 # __IGNORE_WARNING__ + import bs4 # __IGNORE_WARNING__ except ImportError: pipInstall(["beautifulsoup4"]) + # # eflag: noqa = M801
--- a/PluginWeb.epj Thu Dec 30 12:22:34 2021 +0100 +++ b/PluginWeb.epj Wed Sep 21 15:36:01 2022 +0200 @@ -1,19 +1,21 @@ { "header": { "comment": "eric project file for project PluginWeb", - "copyright": "Copyright (C) 2021 Detlev Offenbach, detlev@die-offenbachs.de" + "copyright": "Copyright (C) 2022 Detlev Offenbach, detlev@die-offenbachs.de" }, "project": { "AUTHOR": "Detlev Offenbach", "CHECKERSPARMS": { "Pep8Checker": { "AnnotationsChecker": { + "AllowStarArgAny": false, "AllowUntypedDefs": false, "AllowUntypedNested": false, "DispatchDecorators": [ "singledispatch", "singledispatchmethod" ], + "ForceFutureAnnotations": false, "MaximumComplexity": 3, "MaximumLength": 7, "MinimumCoverage": 75, @@ -59,20 +61,25 @@ }, "CopyrightAuthor": "", "CopyrightMinFileSize": 0, - "DocstringType": "eric", + "DocstringType": "eric_black", "EnabledCheckerCategories": "C, D, E, M, N, S, Y, W", "ExcludeFiles": "*/Ui_*.py, */*_rc.py,", - "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W504,Y119,Y401,Y402", + "ExcludeMessages": "C101,E265,E266,E305,E402,M201,M301,M302,M303,M304,M305,M306,M307,M308,M311,M312,M313,M314,M315,M321,M701,M702,M811,M834,N802,N803,N807,N808,N821,W293,W503,Y119,Y401,Y402", "FixCodes": "", "FixIssues": false, "FutureChecker": "", "HangClosing": false, + "ImportsChecker": { + "ApplicationPackageNames": [], + "BanRelativeImports": "", + "BannedModules": [] + }, "IncludeMessages": "", "LineComplexity": 25, "LineComplexityScore": 10, "MaxCodeComplexity": 10, - "MaxDocLineLength": 79, - "MaxLineLength": 79, + "MaxDocLineLength": 88, + "MaxLineLength": 88, "NoFixCodes": "E501", "RepeatMessages": true, "SecurityChecker": { @@ -129,6 +136,7 @@ } }, "EMAIL": "detlev@die-offenbachs.de", + "EMBEDDED_VENV": false, "EOL": 1, "FILETYPES": { "*.e4p": "OTHERS", @@ -163,6 +171,7 @@ }, "INTERFACES": [], "LEXERASSOCS": {}, + "LICENSE": "GNU General Public License v3 or later (GPLv3+)", "MAINSCRIPT": "PluginProjectWeb.py", "MAKEPARAMS": { "MakeEnabled": false, @@ -178,11 +187,28 @@ "ChangeLog", "PKGLIST", "PluginProjectWeb.zip", + "PluginWeb.epj", "ProjectWeb/Documentation/LICENSE.GPL3", - "ProjectWeb/Documentation/source", - "PluginWeb.epj" + "ProjectWeb/Documentation/source" ], - "OTHERTOOLSPARMS": {}, + "OTHERTOOLSPARMS": { + "Black": { + "exclude": "/(\\.direnv|\\.eggs|\\.git|\\.hg|\\.mypy_cache|\\.nox|\\.tox|\\.venv|venv|\\.svn|_build|buck-out|build|dist|__pypackages__)/", + "extend-exclude": "", + "force-exclude": "", + "line-length": 88, + "skip-magic-trailing-comma": false, + "skip-string-normalization": false, + "source": "project", + "target-version": [ + "py311", + "py310", + "py39", + "py38", + "py37" + ] + } + }, "PACKAGERSPARMS": {}, "PROGLANGUAGE": "Python3", "PROJECTTYPE": "E7Plugin", @@ -203,13 +229,12 @@ "ProjectWeb/Html5ToJsConverter.py", "ProjectWeb/Html5ToJsConverterParameterDialog.py", "ProjectWeb/__init__.py", - "__init__.py", - "ProjectWeb/Ui_Html5ToCss3ConverterParameterDialog.py", - "ProjectWeb/Ui_Html5ToJsConverterParameterDialog.py" + "__init__.py" ], "SPELLEXCLUDES": "", "SPELLLANGUAGE": "en_US", "SPELLWORDS": "", + "TESTING_FRAMEWORK": "", "TRANSLATIONEXCEPTIONS": [], "TRANSLATIONPATTERN": "ProjectWeb/i18n/web_%language%.ts", "TRANSLATIONS": [
--- a/ProjectWeb/Html5Prettifier.py Thu Dec 30 12:22:34 2021 +0100 +++ b/ProjectWeb/Html5Prettifier.py Wed Sep 21 15:36:01 2022 +0200 @@ -18,56 +18,63 @@ """ Class implementing the HTML5 prettifier. """ + def __init__(self, html, parent=None): """ Constructor - + @param html HTML text to be prettified @type str @param parent reference to the parent object @type QObject """ super().__init__(parent) - + self.__html = html self.__indentWidth = Preferences.getEditor("IndentWidth") - + def getPrettifiedHtml(self): """ Public method to prettify the HTML code. - + @return prettified HTML code @rtype str """ from bs4 import BeautifulSoup + soup = BeautifulSoup(self.__html, "html.parser") prettyHtml = soup.prettify(formatter=self.tagPrettify) # prettify comments - prettyHtml = re.sub("<!--(.*?)-->", self.commentPrettify, prettyHtml, - flags=re.DOTALL) + prettyHtml = re.sub( + "<!--(.*?)-->", self.commentPrettify, prettyHtml, flags=re.DOTALL + ) # indent all HTML - prettyHtml = re.sub("^( *)(.*)$", - r"{0}\2".format(r"\1" * self.__indentWidth), - prettyHtml, flags=re.MULTILINE) - + prettyHtml = re.sub( + "^( *)(.*)$", + r"{0}\2".format(r"\1" * self.__indentWidth), + prettyHtml, + flags=re.MULTILINE, + ) + return prettyHtml - + def tagPrettify(self, tag): """ Public method to prettify HTML tags. - + @param tag tag to be prettified @type str @return prettified tag @rtype str """ - return re.sub(" {{1,{0}}}".format(self.__indentWidth), " ", tag, - flags=re.MULTILINE) - + return re.sub( + " {{1,{0}}}".format(self.__indentWidth), " ", tag, flags=re.MULTILINE + ) + def commentPrettify(self, matchobj): """ Public method to prettify HTML comments. - + @param matchobj reference to the match object @type re.MatchObject @return prettified comment
--- a/ProjectWeb/Html5ToCss3Converter.py Thu Dec 30 12:22:34 2021 +0100 +++ b/ProjectWeb/Html5ToCss3Converter.py Wed Sep 21 15:36:01 2022 +0200 @@ -15,61 +15,88 @@ from PyQt6.QtCore import QObject from PyQt6.QtWidgets import QDialog -from .Html5ToCss3ConverterParameterDialog import ( - Html5ToCss3ConverterParameterDialog -) +from .Html5ToCss3ConverterParameterDialog import Html5ToCss3ConverterParameterDialog class Html5ToCss3Converter(QObject): """ Class implementing the HTML5 to CSS3 converter. """ + CssTemplate7 = "{0}{1}{2}{3}{4}{5}{6}" CssTemplate8 = "{0}{1}{2}{3}{4}{5}{6}{7}" - Placeholders = ('margin:0', 'padding:0', 'border:0', 'font-size:100%', - 'font:inherit', 'vertical-align:baseline', 'line-height:1', - 'outline:0', 'font-weight:inherit', 'font-style:inherit', - 'font-family:inherit', 'vertical-align:baseline') - TagsToIgnore = ('head', 'meta', 'noscript', 'script', 'style', 'link', - 'no-js', 'title', 'object', 'col', 'colgroup', 'option', - 'param', 'audio', 'basefont', 'isindex', 'svg', 'area', - 'embed', 'br') - + Placeholders = ( + "margin:0", + "padding:0", + "border:0", + "font-size:100%", + "font:inherit", + "vertical-align:baseline", + "line-height:1", + "outline:0", + "font-weight:inherit", + "font-style:inherit", + "font-family:inherit", + "vertical-align:baseline", + ) + TagsToIgnore = ( + "head", + "meta", + "noscript", + "script", + "style", + "link", + "no-js", + "title", + "object", + "col", + "colgroup", + "option", + "param", + "audio", + "basefont", + "isindex", + "svg", + "area", + "embed", + "br", + ) + def __init__(self, html, parent=None): """ Constructor - + @param html HTML text to be converted @type str @param parent reference to the parent object @type QObject """ super().__init__(parent) - + self.__html = html - + def getCss3(self): """ Public method to get the converted CSS3 text. - + @return CSS3 text @rtype str """ dlg = Html5ToCss3ConverterParameterDialog() if dlg.exec() == QDialog.DialogCode.Accepted: indentation, placeholders = dlg.getData() - + self.__createSoup() - + alreadyDone = list(self.TagsToIgnore) - + css = '@charset "utf-8";{0}'.format(os.linesep) css += "/* {0} by {1}*/{2}".format( datetime.datetime.now().isoformat().split(".")[0], getpass.getuser(), - 2 * os.linesep + 2 * os.linesep, ) - + # step 1: tags for tag in self.__getTags(): if tag not in alreadyDone: @@ -78,100 +105,93 @@ "{", os.linesep, indentation, - random.choice(self.Placeholders) + os.linesep # secok - if placeholders else os.linesep, + random.choice(self.Placeholders) + os.linesep # secok + if placeholders + else os.linesep, "}", - os.linesep + os.linesep, ) alreadyDone.append(tag) - css += "/*{0}*/{1}".format( - "-" * 75, - os.linesep - ) - + css += "/*{0}*/{1}".format("-" * 75, os.linesep) + # step 2: IDs for id_ in self.__getIds(): if id_ not in alreadyDone: - css += "/* {0} */{1}".format( - "_".join(id_).lower(), - os.linesep - ) + css += "/* {0} */{1}".format("_".join(id_).lower(), os.linesep) css += self.CssTemplate8.format( "#", id_[1], "{", os.linesep, indentation, - random.choice(self.Placeholders) + os.linesep # secok - if placeholders else os.linesep, + random.choice(self.Placeholders) + os.linesep # secok + if placeholders + else os.linesep, "}", - os.linesep + os.linesep, ) alreadyDone.append(id_) - css += "/*{0}*/{1}".format( - "-" * 75, - os.linesep - ) - + css += "/*{0}*/{1}".format("-" * 75, os.linesep) + # step 3: classes for class_ in self.__getClasses(): if class_ not in alreadyDone: - css += "/* {0} */{1}".format( - "_".join(class_).lower(), - os.linesep - ) + css += "/* {0} */{1}".format("_".join(class_).lower(), os.linesep) css += self.CssTemplate8.format( ".", ", .".join(class_[1].split()), "{", os.linesep, indentation, - random.choice(self.Placeholders) + os.linesep # secok - if placeholders else os.linesep, + random.choice(self.Placeholders) + os.linesep # secok + if placeholders + else os.linesep, "}", - os.linesep + os.linesep, ) alreadyDone.append(class_) else: css = "" return css.strip() - + def __createSoup(self): """ Private method to get a BeaitifulSoup object with our HTML text. """ from bs4 import BeautifulSoup + self.__soup = BeautifulSoup(BeautifulSoup(self.__html).prettify()) - + def __getTags(self): """ Private method to extract all tags of the HTML text. - + @return list of all tags @rtype list of str """ tags = [t.name for t in self.__soup.find_all(True)] return list(set(tags)) - + def __getClasses(self): """ Private method to extract all classes of the HTML text. - + @return list of tuples containing the tag name and its classes as a blank separated string @rtype list of tuples of (str, str) """ - classes = [(t.name, " ".join(t["class"])) for t in - self.__soup.find_all(True, {"class": True})] + classes = [ + (t.name, " ".join(t["class"])) + for t in self.__soup.find_all(True, {"class": True}) + ] return sorted(set(classes)) - + def __getIds(self): """ Private method to extract all IDs of the HTML text. - + @return list of tuples containing the tag name and its ID @rtype list of tuples of (str, str) """ - ids = [(t.name, t["id"]) for t in - self.__soup.find_all(True, {"id": True})] + ids = [(t.name, t["id"]) for t in self.__soup.find_all(True, {"id": True})] return sorted(set(ids))
--- a/ProjectWeb/Html5ToCss3ConverterParameterDialog.py Thu Dec 30 12:22:34 2021 +0100 +++ b/ProjectWeb/Html5ToCss3ConverterParameterDialog.py Wed Sep 21 15:36:01 2022 +0200 @@ -10,32 +10,34 @@ from PyQt6.QtWidgets import QDialog from .Ui_Html5ToCss3ConverterParameterDialog import ( - Ui_Html5ToCss3ConverterParameterDialog + Ui_Html5ToCss3ConverterParameterDialog, ) class Html5ToCss3ConverterParameterDialog( - QDialog, Ui_Html5ToCss3ConverterParameterDialog): + QDialog, Ui_Html5ToCss3ConverterParameterDialog +): """ Class implementing a dialog to enter the CSS conversion parameters. """ + def __init__(self, parent=None): """ Constructor - + @param parent reference to the parent widget @type QWidget """ super().__init__(parent) self.setupUi(self) - + msh = self.minimumSizeHint() self.resize(max(self.width(), msh.width()), msh.height()) - + def getData(self): """ Public method to get the entered data. - + @return tuple of indentation string and a flag indicating to use CSS placeholders @rtype tuple of (str, bool)
--- a/ProjectWeb/Html5ToJsConverter.py Thu Dec 30 12:22:34 2021 +0100 +++ b/ProjectWeb/Html5ToJsConverter.py Wed Sep 21 15:36:01 2022 +0200 @@ -15,141 +15,158 @@ from PyQt6.QtCore import QObject from PyQt6.QtWidgets import QDialog -from .Html5ToJsConverterParameterDialog import ( - Html5ToJsConverterParameterDialog -) +from .Html5ToJsConverterParameterDialog import Html5ToJsConverterParameterDialog class Html5ToJsConverter(QObject): """ Class implementing the HTML5 to JavaScript converter. """ + JsTemplate8 = "{0}{1}{2}{3}{4}{5}{6}{7}" - TagsToIgnore = ('head', 'meta', 'noscript', 'script', 'style', 'link', - 'no-js', 'title', 'object', 'col', 'colgroup', 'option', - 'param', 'audio', 'basefont', 'isindex', 'svg', 'area', - 'embed', 'br') - + TagsToIgnore = ( + "head", + "meta", + "noscript", + "script", + "style", + "link", + "no-js", + "title", + "object", + "col", + "colgroup", + "option", + "param", + "audio", + "basefont", + "isindex", + "svg", + "area", + "embed", + "br", + ) + def __init__(self, html, parent=None): """ Constructor - + @param html HTML text to be converted @type str @param parent reference to the parent object @type QObject """ super().__init__(parent) - + self.__html = html - + def getJavaScript(self): """ Public method to get the converted JavaScript text. - + @return JavaScript text @rtype str """ dlg = Html5ToJsConverterParameterDialog() if dlg.exec() == QDialog.DialogCode.Accepted: indentation, scriptTags = dlg.getData() - + self.__createSoup() - + alreadyDone = list(self.TagsToIgnore) - + js = "<script>{0}".format(os.linesep) if scriptTags else "" js += "// {0} by {1}{2}".format( datetime.datetime.now().isoformat().split(".")[0], getpass.getuser(), - os.linesep + os.linesep, ) js += "$(document).ready(function(){" + os.linesep - + # step 1: IDs - js += "/*{0}*/{1}".format( - "-" * 75, - os.linesep - ) + js += "/*{0}*/{1}".format("-" * 75, os.linesep) for id_ in self.__getIds(): if id_ not in alreadyDone: js += "{0}// {1}{2}".format( - indentation, - "#".join(id_).lower(), - os.linesep + indentation, "#".join(id_).lower(), os.linesep ) js += self.JsTemplate8.format( indentation, "var ", - re.sub("[^a-z0-9]", "", - id_[1].lower() if len(id_[1]) < 11 else - re.sub("[aeiou]", "", id_[1].lower())), + re.sub( + "[^a-z0-9]", + "", + id_[1].lower() + if len(id_[1]) < 11 + else re.sub("[aeiou]", "", id_[1].lower()), + ), " = ", '$("#{0}").length'.format(id_[1]), ";", os.linesep, - os.linesep + os.linesep, ) alreadyDone.append(id_) - + # step 2: classes - js += "/*{0}*/{1}".format( - "-" * 75, - os.linesep - ) + js += "/*{0}*/{1}".format("-" * 75, os.linesep) for class_ in self.__getClasses(): if class_ not in alreadyDone: js += "{0}// {1}{2}".format( - indentation, - ".".join(class_).lower(), - os.linesep + indentation, ".".join(class_).lower(), os.linesep ) js += self.JsTemplate8.format( indentation, "var ", - re.sub("[^a-z0-9]", "", - class_[1].lower() if len(class_[1]) < 11 else - re.sub("[aeiou]", "", class_[1].lower())), + re.sub( + "[^a-z0-9]", + "", + class_[1].lower() + if len(class_[1]) < 11 + else re.sub("[aeiou]", "", class_[1].lower()), + ), " = ", '$(".{0}").length'.format(class_[1]), ";", os.linesep, - os.linesep + os.linesep, ) alreadyDone.append(class_) - + js += "})" js += "{0}</script>".format(os.linesep) if scriptTags else "" else: js = "" return js.strip() - + def __createSoup(self): """ Private method to get a BeaitifulSoup object with our HTML text. """ from bs4 import BeautifulSoup + self.__soup = BeautifulSoup(BeautifulSoup(self.__html).prettify()) - + def __getClasses(self): """ Private method to extract all classes of the HTML text. - + @return list of tuples containing the tag name and its classes as a blank separated string @rtype list of tuples of (str, str) """ - classes = [(t.name, " ".join(t["class"])) for t in - self.__soup.find_all(True, {"class": True})] + classes = [ + (t.name, " ".join(t["class"])) + for t in self.__soup.find_all(True, {"class": True}) + ] return sorted(set(classes)) - + def __getIds(self): """ Private method to extract all IDs of the HTML text. - + @return list of tuples containing the tag name and its ID @rtype list of tuples of (str, str) """ - ids = [(t.name, t["id"]) for t in - self.__soup.find_all(True, {"id": True})] + ids = [(t.name, t["id"]) for t in self.__soup.find_all(True, {"id": True})] return sorted(set(ids))
--- a/ProjectWeb/Html5ToJsConverterParameterDialog.py Thu Dec 30 12:22:34 2021 +0100 +++ b/ProjectWeb/Html5ToJsConverterParameterDialog.py Wed Sep 21 15:36:01 2022 +0200 @@ -9,36 +9,33 @@ from PyQt6.QtWidgets import QDialog -from .Ui_Html5ToJsConverterParameterDialog import ( - Ui_Html5ToJsConverterParameterDialog -) +from .Ui_Html5ToJsConverterParameterDialog import Ui_Html5ToJsConverterParameterDialog -class Html5ToJsConverterParameterDialog( - QDialog, Ui_Html5ToJsConverterParameterDialog): +class Html5ToJsConverterParameterDialog(QDialog, Ui_Html5ToJsConverterParameterDialog): """ Class implementing a dialog to enter the JavaScript conversion parameters. """ + def __init__(self, parent=None): """ Constructor - + @param parent reference to the parent widget @type QWidget """ super().__init__(parent) self.setupUi(self) - + msh = self.minimumSizeHint() self.resize(max(self.width(), msh.width()), msh.height()) - + def getData(self): """ Public method to get the entered data. - + @return tuple of indentation string and a flag indicating to enclose the code by 'script' tags @rtype tuple of (str, bool) """ - return (" " * self.indentationSpinBox.value(), - self.scriptCheckBox.isChecked()) + return (" " * self.indentationSpinBox.value(), self.scriptCheckBox.isChecked())