Skip to content

Commit 656d356

Browse files
author
Steve Canny
committed
style: extract BabelFish
1 parent 7e5471e commit 656d356

File tree

3 files changed

+64
-51
lines changed

3 files changed

+64
-51
lines changed

docx/styles/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# encoding: utf-8
2+
3+
"""
4+
Sub-package module for docx.styles sub-package.
5+
"""
6+
7+
from __future__ import (
8+
absolute_import, division, print_function, unicode_literals
9+
)
10+
11+
12+
class BabelFish(object):
13+
"""
14+
Translates special-case style names from UI name (e.g. Heading 1) to
15+
internal/styles.xml name (e.g. heading 1) and back.
16+
"""
17+
18+
style_aliases = (
19+
('Caption', 'caption'),
20+
('Heading 1', 'heading 1'),
21+
('Heading 2', 'heading 2'),
22+
('Heading 3', 'heading 3'),
23+
('Heading 4', 'heading 4'),
24+
('Heading 5', 'heading 5'),
25+
('Heading 6', 'heading 6'),
26+
('Heading 7', 'heading 7'),
27+
('Heading 8', 'heading 8'),
28+
('Heading 9', 'heading 9'),
29+
)
30+
31+
internal_style_names = dict(style_aliases)
32+
ui_style_names = dict((item[1], item[0]) for item in style_aliases)
33+
34+
@classmethod
35+
def ui2internal(cls, ui_style_name):
36+
"""
37+
Return the internal style name corresponding to *ui_style_name*, such
38+
as 'heading 1' for 'Heading 1'.
39+
"""
40+
return cls.internal_style_names.get(ui_style_name, ui_style_name)
41+
42+
@classmethod
43+
def internal2ui(cls, internal_style_name):
44+
"""
45+
Return the user interface style name corresponding to
46+
*internal_style_name*, such as 'Heading 1' for 'heading 1'.
47+
"""
48+
return cls.ui_style_names.get(
49+
internal_style_name, internal_style_name
50+
)

docx/styles/style.py

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
absolute_import, division, print_function, unicode_literals
99
)
1010

11+
from . import BabelFish
1112
from ..enum.style import WD_STYLE_TYPE
1213
from ..shared import ElementProxy
1314
from ..text.paragraph import ParagraphFormat
@@ -94,9 +95,9 @@ def name(self):
9495
The UI name of this style.
9596
"""
9697
name = self._element.name_val
97-
if name is not None:
98-
return self._translate_special_case_names(name)
99-
return name
98+
if name is None:
99+
return None
100+
return BabelFish.internal2ui(name)
100101

101102
@name.setter
102103
def name(self, value):
@@ -166,26 +167,6 @@ def unhide_when_used(self):
166167
def unhide_when_used(self, value):
167168
self._element.unhideWhenUsed_val = value
168169

169-
@staticmethod
170-
def _translate_special_case_names(name):
171-
"""
172-
Translate special-case style names to their English UI counterparts.
173-
Some style names are stored differently than they appear in the UI,
174-
with a leading lowercase letter, perhaps for legacy reasons.
175-
"""
176-
return {
177-
'caption': 'Caption',
178-
'heading 1': 'Heading 1',
179-
'heading 2': 'Heading 2',
180-
'heading 3': 'Heading 3',
181-
'heading 4': 'Heading 4',
182-
'heading 5': 'Heading 5',
183-
'heading 6': 'Heading 6',
184-
'heading 7': 'Heading 7',
185-
'heading 8': 'Heading 8',
186-
'heading 9': 'Heading 9',
187-
}.get(name, name)
188-
189170

190171
class _CharacterStyle(BaseStyle):
191172
"""

docx/styles/styles.py

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
absolute_import, division, print_function, unicode_literals
99
)
1010

11+
from . import BabelFish
1112
from .latent import LatentStyles
1213
from ..shared import ElementProxy
1314
from .style import BaseStyle, StyleFactory
@@ -26,19 +27,19 @@ def __contains__(self, name):
2627
"""
2728
Enables `in` operator on style name.
2829
"""
29-
name = self._translate_special_case_names(name)
30+
internal_name = BabelFish.ui2internal(name)
3031
for style in self._element.style_lst:
31-
if style.name_val == name:
32+
if style.name_val == internal_name:
3233
return True
3334
return False
3435

3536
def __getitem__(self, key):
3637
"""
3738
Enables dictionary-style access by style id or UI name.
3839
"""
39-
key = self._translate_special_case_names(key)
40+
style_name = BabelFish.ui2internal(key)
4041
for get in (self._element.get_by_id, self._element.get_by_name):
41-
style_elm = get(key)
42+
style_elm = get(style_name)
4243
if style_elm is not None:
4344
return StyleFactory(style_elm)
4445
raise KeyError("no style with id or name '%s'" % key)
@@ -55,10 +56,12 @@ def add_style(self, name, style_type, builtin=False):
5556
by *name*. A builtin style can be defined by passing True for the
5657
optional *builtin* argument.
5758
"""
58-
name = self._translate_special_case_names(name)
59-
if name in self:
59+
style_name = BabelFish.ui2internal(name)
60+
if style_name in self:
6061
raise ValueError("document already contains style '%s'" % name)
61-
style = self._element.add_style_of_type(name, style_type, builtin)
62+
style = self._element.add_style_of_type(
63+
style_name, style_type, builtin
64+
)
6265
return StyleFactory(style)
6366

6467
def default(self, style_type):
@@ -140,24 +143,3 @@ def _get_style_id_from_style(self, style, style_type):
140143
if style == self.default(style_type):
141144
return None
142145
return style.style_id
143-
144-
@staticmethod
145-
def _translate_special_case_names(name):
146-
"""
147-
Translate special-case style names from their English UI
148-
counterparts. Some style names are stored differently than they
149-
appear in the UI, with a leading lowercase letter, perhaps for legacy
150-
reasons.
151-
"""
152-
return {
153-
'Caption': 'caption',
154-
'Heading 1': 'heading 1',
155-
'Heading 2': 'heading 2',
156-
'Heading 3': 'heading 3',
157-
'Heading 4': 'heading 4',
158-
'Heading 5': 'heading 5',
159-
'Heading 6': 'heading 6',
160-
'Heading 7': 'heading 7',
161-
'Heading 8': 'heading 8',
162-
'Heading 9': 'heading 9',
163-
}.get(name, name)

0 commit comments

Comments
 (0)