Skip to content

Commit 1311586

Browse files
committed
Added support for Bootstrap
1 parent 5225760 commit 1311586

6 files changed

Lines changed: 196 additions & 13 deletions

File tree

bootstrapCsskrt.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
from bs4 import Tag
2+
from csskrt import Csskrt
3+
4+
5+
class BootstrapCsskrt(Csskrt):
6+
def __init__(self, fileName):
7+
tag_styles = {
8+
'input': 'form-control',
9+
'select': 'custom-select',
10+
'button': 'btn btn-primary',
11+
'checkbox': 'form-check-input',
12+
}
13+
super().__init__(fileName, tag_styles)
14+
15+
def version(self):
16+
return "v4.1"
17+
18+
def get_starter_tags(self):
19+
charset_meta = self.soup.new_tag(
20+
'meta', charset='utf-8'
21+
)
22+
23+
# hack since 'name' is reserve
24+
viewport_meta = Tag(
25+
builder=self.soup.builder,
26+
name='meta',
27+
attrs={'name': "viewport", 'content': 'width=device-width, initial-scale=1, shrink-to-fit=no'}
28+
)
29+
30+
stylesheet = self.soup.new_tag(
31+
'link',
32+
rel='stylesheet',
33+
href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css',
34+
integrity='sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO',
35+
crossorigin='anonymous'
36+
)
37+
return [charset_meta, viewport_meta, stylesheet]
38+
39+
def get_wrapper_tag(self):
40+
div = self.soup.new_tag(
41+
'div', **{'class': 'container'}
42+
)
43+
return div
44+
45+
def get_table_styles(self):
46+
return {
47+
'table': 'table',
48+
'thead': 'thead-light',
49+
}
50+
51+
def get_list_styles(self):
52+
return {
53+
'ol': 'list-group',
54+
'ul': 'list-group',
55+
'li': 'list-group-item'
56+
}
57+
58+
def add_form_classes(self, tag_dict: dict):
59+
"""
60+
Applies form classes, only difference between this and parent implementation is the addition of adding
61+
the "input group wrapper" class
62+
:return:
63+
"""
64+
for form in self.soup.find_all('form'):
65+
spotted_label = None
66+
for elem in form.children:
67+
if elem.name == 'label':
68+
spotted_label = elem
69+
if 'label' in tag_dict:
70+
self.add_class_to_element(elem, tag_dict['label'])
71+
elif elem.name == 'input':
72+
self.add_class_to_element(elem, tag_dict['input'])
73+
if elem.get('type') == 'radio':
74+
if 'radio' in tag_dict:
75+
self.add_class_to_element(elem, tag_dict['radio'])
76+
elif elem.get('type') == 'checkbox':
77+
if 'checkbox' in tag_dict:
78+
self.add_class_to_element(elem, tag_dict['checkbox'])
79+
80+
# Add overall wrapper
81+
if not spotted_label:
82+
# add wrapper
83+
field_div = self.soup.new_tag('div', **{'class': 'form-group'})
84+
elem.wrap(field_div)
85+
else:
86+
# the input has a preceding label
87+
field_div = self.soup.new_tag('div', **{'class': 'form-group'})
88+
spotted_label.wrap(field_div)
89+
field_div.append(elem)
90+
spotted_label = None
91+
92+
# Add input wrapper
93+
control_div = self.soup.new_tag('div', **{'class': 'control'})
94+
elem.wrap(control_div)
95+
elif type(elem) == Tag: # ignore NavigableStrings like /n
96+
spotted_label = None
97+
if (tag_dict.get(elem.name)):
98+
self.add_class_to_element(elem, tag_dict[elem.name])

bulmaCsskrt.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ def __init__(self, fileName):
1515
}
1616
super().__init__(fileName, tag_styles)
1717

18+
def version(self):
19+
return "v0.7.1"
20+
1821
def get_starter_tags(self):
1922
# hack since 'name' is reserved
2023
meta = Tag(builder=self.soup.builder,
@@ -42,13 +45,23 @@ def get_table_styles(self):
4245
'td': 'td'
4346
}
4447

48+
def get_list_styles(self):
49+
return {} # no list styles
50+
4551
def add_form_classes(self, tag_dict: dict):
52+
"""
53+
The only difference between this and parent implementation is the addition of adding
54+
the 'input group' class
55+
:param tag_dict:
56+
:return:
57+
"""
4658
for form in self.soup.find_all('form'):
4759
spotted_label = None
4860
for elem in form.children:
4961
if elem.name == 'label':
5062
spotted_label = elem
51-
self.add_class_to_element(elem, tag_dict['label'])
63+
if 'label' in tag_dict:
64+
self.add_class_to_element(elem, tag_dict['label'])
5265
elif elem.name == 'input':
5366
self.add_class_to_element(elem, tag_dict['input'])
5467
if elem.get('type') == 'radio':
@@ -73,6 +86,7 @@ def add_form_classes(self, tag_dict: dict):
7386
# Add input wrapper
7487
control_div = self.soup.new_tag('div', **{'class': 'control'})
7588
elem.wrap(control_div)
89+
7690
elif type(elem) == Tag: # ignore NavigableStrings like /n
7791
spotted_label = None
7892
if (tag_dict.get(elem.name)):

bulmaCsskrt.pyc

3.23 KB
Binary file not shown.

csskrt.py

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ def get_table_styles(self) -> Dict:
3939
:return:
4040
"""
4141

42+
@abstractmethod
43+
def version(self) -> str:
44+
"""
45+
:return: The version number
46+
"""
47+
48+
@abstractmethod
49+
def get_list_styles(self) -> Dict:
50+
"""
51+
:return:
52+
"""
53+
4254
def add_class_to_element(self, elem, css_class):
4355
if not elem.get('class'):
4456
elem['class'] = css_class
@@ -80,7 +92,8 @@ def add_form_classes(self, tag_dict: dict) -> NoReturn:
8092
for form in self.soup.find_all('form'):
8193
for elem in form.children:
8294
if elem.name == 'label':
83-
self.add_class_to_element(elem, tag_dict['label'])
95+
if 'label' in tag_dict:
96+
self.add_class_to_element(elem, tag_dict['label'])
8497

8598
elif elem.name == 'input':
8699
self.add_class_to_element(elem, tag_dict['input'])
@@ -92,8 +105,8 @@ def add_form_classes(self, tag_dict: dict) -> NoReturn:
92105
if 'checkbox' in tag_dict:
93106
self.add_class_to_element(elem, tag_dict['checkbox'])
94107

95-
elif type(elem) == Tag: # ignore NavigableStrings like /n
96-
if (tag_dict.get(elem.name)):
108+
elif type(elem) == Tag: # ignore NavigableStrings like /n
109+
if tag_dict.get(elem.name):
97110
self.add_class_to_element(elem, tag_dict[elem.name])
98111

99112
def add_table_classes(self, table_tag_dict: dict) -> NoReturn:
@@ -117,6 +130,24 @@ def add_table_classes(self, table_tag_dict: dict) -> NoReturn:
117130
for elem in all_table_elems:
118131
self.add_class_to_element(elem, table_tag_dict[tk])
119132

133+
def add_list_classes(self, list_tags: dict) -> NoReturn:
134+
"""
135+
Supports the following tags:
136+
('ul', 'ol', 'li')
137+
:param list_tags:
138+
:return:
139+
"""
140+
for list in self.soup.find_all(['ol', 'ul']):
141+
if list.name == 'ul' and list_tags.get('ul'):
142+
self.add_class_to_element(list, list_tags['ul'])
143+
elif list.name == 'ol' and list_tags.get('ol'):
144+
self.add_class_to_element(list, list_tags['ol'])
145+
146+
if list_tags.get('li'):
147+
for li in list.find_all('li', recursive=False):
148+
# recursive=False to prevent double modifying for nested lists
149+
self.add_class_to_element(li, list_tags['li'])
150+
120151
def output(self) -> NoReturn:
121152
"""
122153
Outputs a new file.
@@ -137,13 +168,15 @@ def freshify(self) -> NoReturn:
137168
"""
138169
starter_tags = self.get_starter_tags()
139170
wrapper_tag = self.get_wrapper_tag()
140-
table_tags = self.get_table_styles()
171+
table_styles = self.get_table_styles()
172+
list_styles = self.get_list_styles()
141173

142174
self.initialize_framework(self.soup.head, starter_tags)
143175
if wrapper_tag:
144176
self.add_wrapper_tag(wrapper_tag)
145177
self.add_form_classes(self.tag_styles)
146-
self.add_table_classes(table_tags)
178+
self.add_list_classes(list_styles)
179+
self.add_table_classes(table_styles)
147180
self.output()
148181

149182
# print(btn.get('class', []))

main.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import click
22
from bulmaCsskrt import BulmaCsskrt
3+
from bootstrapCsskrt import BootstrapCsskrt
34

45

56
@click.command()
@@ -9,11 +10,14 @@ def freshify(filename, framework):
910
csskrter = None
1011

1112
if framework == 'bootstrap':
12-
raise NotImplementedError
13+
csskrter = BootstrapCsskrt(filename)
1314
elif framework == 'bulma':
1415
csskrter = BulmaCsskrt(filename)
16+
else:
17+
raise Exception("Invalid framework")
1518

16-
csskrter.freshify()
19+
csskrter.freshify()
20+
print("Done !")
1721

1822

1923
if __name__ == '__main__':

test/test1.html

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,27 @@
77

88
<body>
99
<div>
10-
<p> Hello World </p>
10+
<h1> Hello World </h1>
1111
<p class="testclass"> Bonjour !</p>
1212
<button> Click Me !</button>
13-
<button class="my-button-test"> Click Me !</button>
1413

1514
<form>
16-
<label for="someText"> </label>
15+
<label for="someText"> Here is an input field </label>
1716
<input id="someText" type="text">
18-
<input type="radio">
1917

20-
<button type="submit" onclick="alert('submitted')"> Click me</button>
18+
<div>
19+
<label> Option 1
20+
<input type="radio" name="my-radio">
21+
</label>
22+
<label> Option 2
23+
<input type="radio" name="my-radio">
24+
</label>
25+
<label> Option 3
26+
<input type="radio" name="my-radio">
27+
</label>
28+
</div>
29+
30+
<button class="my-button-test" type="submit" onclick="alert('submitted')"> Click me</button>
2131
</form>
2232

2333
<table id="test">
@@ -31,7 +41,31 @@
3141
<td>Smith</td>
3242
<td>21</td>
3343
</tr>
44+
<tr>
45+
<td>Susan</td>
46+
<td>Johnson</td>
47+
<td>66</td>
48+
</tr>
3449
</table>
50+
51+
<div>
52+
<h1> Car Brands</h1>
53+
<ul>
54+
<li>
55+
BMW
56+
<ul>
57+
<li> Mini</li>
58+
<li> Rolls Royce</li>
59+
</ul>
60+
</li>
61+
<li> Honda
62+
<ul>
63+
<li> Acura</li>
64+
</ul>
65+
</li>
66+
<li> Toyota</li>
67+
</ul>
68+
</div>
3569
</div>
3670
</body>
3771
</html>

0 commit comments

Comments
 (0)