File: //home/arjun/projects/env/lib/python3.10/site-packages/docx/oxml/text/font.py
"""Custom element classes related to run properties (font)."""
from __future__ import annotations
from typing import TYPE_CHECKING, Callable
from docx.enum.dml import MSO_THEME_COLOR
from docx.enum.text import WD_COLOR_INDEX, WD_UNDERLINE
from docx.oxml.ns import nsdecls
from docx.oxml.parser import parse_xml
from docx.oxml.simpletypes import (
ST_HexColor,
ST_HpsMeasure,
ST_String,
ST_VerticalAlignRun,
)
from docx.oxml.xmlchemy import (
BaseOxmlElement,
OptionalAttribute,
RequiredAttribute,
ZeroOrOne,
)
if TYPE_CHECKING:
from docx.oxml.shared import CT_OnOff, CT_String
from docx.shared import Length
class CT_Color(BaseOxmlElement):
"""`w:color` element, specifying the color of a font and perhaps other objects."""
val = RequiredAttribute("w:val", ST_HexColor)
themeColor = OptionalAttribute("w:themeColor", MSO_THEME_COLOR)
class CT_Fonts(BaseOxmlElement):
"""`<w:rFonts>` element.
Specifies typeface name for the various language types.
"""
ascii: str | None = OptionalAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:ascii", ST_String
)
hAnsi: str | None = OptionalAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:hAnsi", ST_String
)
class CT_Highlight(BaseOxmlElement):
"""`w:highlight` element, specifying font highlighting/background color."""
val: WD_COLOR_INDEX = RequiredAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:val", WD_COLOR_INDEX
)
class CT_HpsMeasure(BaseOxmlElement):
"""Used for `<w:sz>` element and others, specifying font size in half-points."""
val: Length = RequiredAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:val", ST_HpsMeasure
)
class CT_RPr(BaseOxmlElement):
"""`<w:rPr>` element, containing the properties for a run."""
get_or_add_highlight: Callable[[], CT_Highlight]
get_or_add_rFonts: Callable[[], CT_Fonts]
get_or_add_sz: Callable[[], CT_HpsMeasure]
get_or_add_vertAlign: Callable[[], CT_VerticalAlignRun]
_add_rStyle: Callable[..., CT_String]
_add_u: Callable[[], CT_Underline]
_remove_highlight: Callable[[], None]
_remove_rFonts: Callable[[], None]
_remove_rStyle: Callable[[], None]
_remove_sz: Callable[[], None]
_remove_u: Callable[[], None]
_remove_vertAlign: Callable[[], None]
_tag_seq = (
"w:rStyle",
"w:rFonts",
"w:b",
"w:bCs",
"w:i",
"w:iCs",
"w:caps",
"w:smallCaps",
"w:strike",
"w:dstrike",
"w:outline",
"w:shadow",
"w:emboss",
"w:imprint",
"w:noProof",
"w:snapToGrid",
"w:vanish",
"w:webHidden",
"w:color",
"w:spacing",
"w:w",
"w:kern",
"w:position",
"w:sz",
"w:szCs",
"w:highlight",
"w:u",
"w:effect",
"w:bdr",
"w:shd",
"w:fitText",
"w:vertAlign",
"w:rtl",
"w:cs",
"w:em",
"w:lang",
"w:eastAsianLayout",
"w:specVanish",
"w:oMath",
)
rStyle: CT_String | None = ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:rStyle", successors=_tag_seq[1:]
)
rFonts: CT_Fonts | None = ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:rFonts", successors=_tag_seq[2:]
)
b: CT_OnOff | None = ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:b", successors=_tag_seq[3:]
)
bCs = ZeroOrOne("w:bCs", successors=_tag_seq[4:])
i = ZeroOrOne("w:i", successors=_tag_seq[5:])
iCs = ZeroOrOne("w:iCs", successors=_tag_seq[6:])
caps = ZeroOrOne("w:caps", successors=_tag_seq[7:])
smallCaps = ZeroOrOne("w:smallCaps", successors=_tag_seq[8:])
strike = ZeroOrOne("w:strike", successors=_tag_seq[9:])
dstrike = ZeroOrOne("w:dstrike", successors=_tag_seq[10:])
outline = ZeroOrOne("w:outline", successors=_tag_seq[11:])
shadow = ZeroOrOne("w:shadow", successors=_tag_seq[12:])
emboss = ZeroOrOne("w:emboss", successors=_tag_seq[13:])
imprint = ZeroOrOne("w:imprint", successors=_tag_seq[14:])
noProof = ZeroOrOne("w:noProof", successors=_tag_seq[15:])
snapToGrid = ZeroOrOne("w:snapToGrid", successors=_tag_seq[16:])
vanish = ZeroOrOne("w:vanish", successors=_tag_seq[17:])
webHidden = ZeroOrOne("w:webHidden", successors=_tag_seq[18:])
color = ZeroOrOne("w:color", successors=_tag_seq[19:])
sz: CT_HpsMeasure | None = ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:sz", successors=_tag_seq[24:]
)
highlight: CT_Highlight | None = (
ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:highlight", successors=_tag_seq[26:]
)
)
u: CT_Underline | None = ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:u", successors=_tag_seq[27:]
)
vertAlign: CT_VerticalAlignRun | None = (
ZeroOrOne( # pyright: ignore[reportGeneralTypeIssues]
"w:vertAlign", successors=_tag_seq[32:]
)
)
rtl = ZeroOrOne("w:rtl", successors=_tag_seq[33:])
cs = ZeroOrOne("w:cs", successors=_tag_seq[34:])
specVanish = ZeroOrOne("w:specVanish", successors=_tag_seq[38:])
oMath = ZeroOrOne("w:oMath", successors=_tag_seq[39:])
del _tag_seq
def _new_color(self):
"""Override metaclass method to set `w:color/@val` to RGB black on create."""
return parse_xml('<w:color %s w:val="000000"/>' % nsdecls("w"))
@property
def highlight_val(self) -> WD_COLOR_INDEX | None:
"""Value of `./w:highlight/@val`.
Specifies font's highlight color, or `None` if the text is not highlighted.
"""
highlight = self.highlight
if highlight is None:
return None
return highlight.val
@highlight_val.setter
def highlight_val(self, value: WD_COLOR_INDEX | None) -> None:
if value is None:
self._remove_highlight()
return
highlight = self.get_or_add_highlight()
highlight.val = value
@property
def rFonts_ascii(self) -> str | None:
"""The value of `w:rFonts/@w:ascii` or |None| if not present.
Represents the assigned typeface name. The rFonts element also specifies other
special-case typeface names; this method handles the case where just the common
name is required.
"""
rFonts = self.rFonts
if rFonts is None:
return None
return rFonts.ascii
@rFonts_ascii.setter
def rFonts_ascii(self, value: str | None) -> None:
if value is None:
self._remove_rFonts()
return
rFonts = self.get_or_add_rFonts()
rFonts.ascii = value
@property
def rFonts_hAnsi(self) -> str | None:
"""The value of `w:rFonts/@w:hAnsi` or |None| if not present."""
rFonts = self.rFonts
if rFonts is None:
return None
return rFonts.hAnsi
@rFonts_hAnsi.setter
def rFonts_hAnsi(self, value: str | None):
if value is None and self.rFonts is None:
return
rFonts = self.get_or_add_rFonts()
rFonts.hAnsi = value
@property
def style(self) -> str | None:
"""String in `./w:rStyle/@val`, or None if `w:rStyle` is not present."""
rStyle = self.rStyle
if rStyle is None:
return None
return rStyle.val
@style.setter
def style(self, style: str | None) -> None:
"""Set `./w:rStyle/@val` to `style`, adding the `w:rStyle` element if necessary.
If `style` is |None|, remove `w:rStyle` element if present.
"""
if style is None:
self._remove_rStyle()
elif self.rStyle is None:
self._add_rStyle(val=style)
else:
self.rStyle.val = style
@property
def subscript(self) -> bool | None:
"""|True| if `./w:vertAlign/@w:val` is "subscript".
|False| if `w:vertAlign/@w:val` contains any other value. |None| if
`w:vertAlign` is not present.
"""
vertAlign = self.vertAlign
if vertAlign is None:
return None
if vertAlign.val == ST_VerticalAlignRun.SUBSCRIPT:
return True
return False
@subscript.setter
def subscript(self, value: bool | None) -> None:
if value is None:
self._remove_vertAlign()
elif bool(value) is True:
self.get_or_add_vertAlign().val = ST_VerticalAlignRun.SUBSCRIPT
# -- assert bool(value) is False --
elif (
self.vertAlign is not None
and self.vertAlign.val == ST_VerticalAlignRun.SUBSCRIPT
):
self._remove_vertAlign()
@property
def superscript(self) -> bool | None:
"""|True| if `w:vertAlign/@w:val` is 'superscript'.
|False| if `w:vertAlign/@w:val` contains any other value. |None| if
`w:vertAlign` is not present.
"""
vertAlign = self.vertAlign
if vertAlign is None:
return None
if vertAlign.val == ST_VerticalAlignRun.SUPERSCRIPT:
return True
return False
@superscript.setter
def superscript(self, value: bool | None):
if value is None:
self._remove_vertAlign()
elif bool(value) is True:
self.get_or_add_vertAlign().val = ST_VerticalAlignRun.SUPERSCRIPT
# -- assert bool(value) is False --
elif (
self.vertAlign is not None
and self.vertAlign.val == ST_VerticalAlignRun.SUPERSCRIPT
):
self._remove_vertAlign()
@property
def sz_val(self) -> Length | None:
"""The value of `w:sz/@w:val` or |None| if not present."""
sz = self.sz
if sz is None:
return None
return sz.val
@sz_val.setter
def sz_val(self, value: Length | None):
if value is None:
self._remove_sz()
return
sz = self.get_or_add_sz()
sz.val = value
@property
def u_val(self) -> WD_UNDERLINE | None:
"""Value of `w:u/@val`, or None if not present.
Values `WD_UNDERLINE.SINGLE` and `WD_UNDERLINE.NONE` are mapped to `True` and
`False` respectively.
"""
u = self.u
if u is None:
return None
return u.val
@u_val.setter
def u_val(self, value: WD_UNDERLINE | None):
self._remove_u()
if value is not None:
self._add_u().val = value
def _get_bool_val(self, name: str) -> bool | None:
"""Value of boolean child with `name`, e.g. "w:b", "w:i", and "w:smallCaps"."""
element = getattr(self, name)
if element is None:
return None
return element.val
def _set_bool_val(self, name: str, value: bool | None):
if value is None:
getattr(self, "_remove_%s" % name)()
return
element = getattr(self, "get_or_add_%s" % name)()
element.val = value
class CT_Underline(BaseOxmlElement):
"""`<w:u>` element, specifying the underlining style for a run."""
val: WD_UNDERLINE | None = (
OptionalAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:val", WD_UNDERLINE
)
)
class CT_VerticalAlignRun(BaseOxmlElement):
"""`<w:vertAlign>` element, specifying subscript or superscript."""
val: str = RequiredAttribute( # pyright: ignore[reportGeneralTypeIssues]
"w:val", ST_VerticalAlignRun
)