|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2014 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the HTML5 to JavaScript converter. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import os |
|
13 import re |
|
14 import datetime |
|
15 import getpass |
|
16 |
|
17 from PyQt5.QtCore import QObject |
|
18 from PyQt5.QtWidgets import QDialog |
|
19 |
|
20 from .Html5ToJsConverterParameterDialog import \ |
|
21 Html5ToJsConverterParameterDialog |
|
22 |
|
23 |
|
24 class Html5ToJsConverter(QObject): |
|
25 """ |
|
26 Class implementing the HTML5 to JavaScript converter. |
|
27 """ |
|
28 JsTemplate8 = "{0}{1}{2}{3}{4}{5}{6}{7}" |
|
29 TagsToIgnore = ('head', 'meta', 'noscript', 'script', 'style', 'link', |
|
30 'no-js', 'title', 'object', 'col', 'colgroup', 'option', |
|
31 'param', 'audio', 'basefont', 'isindex', 'svg', 'area', |
|
32 'embed', 'br') |
|
33 |
|
34 def __init__(self, html, parent=None): |
|
35 """ |
|
36 Constructor |
|
37 |
|
38 @param html HTML text to be converted (string) |
|
39 @param parent reference to the parent object (QObject) |
|
40 """ |
|
41 super(Html5ToJsConverter, self).__init__(parent) |
|
42 |
|
43 self.__html = html |
|
44 |
|
45 def getJavaScript(self): |
|
46 """ |
|
47 Public method to get the converted JavaScript text. |
|
48 |
|
49 @return JavaScript text (string) |
|
50 """ |
|
51 dlg = Html5ToJsConverterParameterDialog() |
|
52 if dlg.exec_() == QDialog.Accepted: |
|
53 indentation, scriptTags = dlg.getData() |
|
54 |
|
55 self.__createSoup() |
|
56 |
|
57 alreadyDone = list(self.TagsToIgnore) |
|
58 |
|
59 js = "<script>{0}".format(os.linesep) if scriptTags else "" |
|
60 js += "// {0} by {1}{2}".format( |
|
61 datetime.datetime.now().isoformat().split(".")[0], |
|
62 getpass.getuser(), |
|
63 os.linesep |
|
64 ) |
|
65 js += "$(document).ready(function(){" + os.linesep |
|
66 |
|
67 # step 1: IDs |
|
68 js += "/*{0}*/{1}".format( |
|
69 "-" * 75, |
|
70 os.linesep |
|
71 ) |
|
72 for id_ in self.__getIds(): |
|
73 if id_ not in alreadyDone: |
|
74 js += "{0}// {1}{2}".format( |
|
75 indentation, |
|
76 "#".join(id_).lower(), |
|
77 os.linesep |
|
78 ) |
|
79 js += self.JsTemplate8.format( |
|
80 indentation, |
|
81 "var ", |
|
82 re.sub("[^a-z0-9]", "", |
|
83 id_[1].lower() if len(id_[1]) < 11 else |
|
84 re.sub("[aeiou]", "", id_[1].lower())), |
|
85 " = ", |
|
86 '$("#{0}").length'.format(id_[1]), |
|
87 ";", |
|
88 os.linesep, |
|
89 os.linesep |
|
90 ) |
|
91 alreadyDone.append(id_) |
|
92 |
|
93 # step 2: classes |
|
94 js += "/*{0}*/{1}".format( |
|
95 "-" * 75, |
|
96 os.linesep |
|
97 ) |
|
98 for class_ in self.__getClasses(): |
|
99 if class_ not in alreadyDone: |
|
100 js += "{0}// {1}{2}".format( |
|
101 indentation, |
|
102 ".".join(class_).lower(), |
|
103 os.linesep |
|
104 ) |
|
105 js += self.JsTemplate8.format( |
|
106 indentation, |
|
107 "var ", |
|
108 re.sub("[^a-z0-9]", "", |
|
109 class_[1].lower() if len(class_[1]) < 11 else |
|
110 re.sub("[aeiou]", "", class_[1].lower())), |
|
111 " = ", |
|
112 '$(".{0}").length'.format(class_[1]), |
|
113 ";", |
|
114 os.linesep, |
|
115 os.linesep |
|
116 ) |
|
117 alreadyDone.append(class_) |
|
118 |
|
119 js += "})" |
|
120 js += "{0}</script>".format(os.linesep) if scriptTags else "" |
|
121 else: |
|
122 js = "" |
|
123 return js.strip() |
|
124 |
|
125 def __createSoup(self): |
|
126 """ |
|
127 Private method to get a BeaitifulSoup object with our HTML text. |
|
128 """ |
|
129 from bs4 import BeautifulSoup |
|
130 self.__soup = BeautifulSoup(BeautifulSoup(self.__html).prettify()) |
|
131 |
|
132 def __getClasses(self): |
|
133 """ |
|
134 Private method to extract all classes of the HTML text. |
|
135 |
|
136 @return list of tuples containing the tag name and its classes |
|
137 as a blank separated string (list of tuples of two strings) |
|
138 """ |
|
139 classes = [(t.name, " ".join(t["class"])) for t in |
|
140 self.__soup.find_all(True, {"class": True})] |
|
141 return sorted(list(set(classes))) |
|
142 |
|
143 def __getIds(self): |
|
144 """ |
|
145 Private method to extract all IDs of the HTML text. |
|
146 |
|
147 @return list of tuples containing the tag name and its ID |
|
148 (list of tuples of two strings) |
|
149 """ |
|
150 ids = [(t.name, t["id"]) for t in |
|
151 self.__soup.find_all(True, {"id": True})] |
|
152 return sorted(list(set(ids))) |