diff --git a/doorstop/core/item.py b/doorstop/core/item.py index 4b978f5a..849cd1f6 100644 --- a/doorstop/core/item.py +++ b/doorstop/core/item.py @@ -573,6 +573,34 @@ def header(self, value): if settings.ENABLE_HEADERS: self._data["header"] = Text(value) + def title(self): + """Get the item's title. + + Read from either the header or the first line of the text field. + + """ + if self.header: + return self.header + lines = self.text.splitlines() + if lines: + return lines[0] + return "" + + def description(self): + """Get the item's description. + + Read from the text field, omitting the first line if it would be + included in the item's title. + + """ + if self.header: + # Header is specified, so no need to omit the first line + return self.text + lines = self.text.splitlines() + if lines: + return lines[1:] + return "" + @property # type: ignore @auto_load def ref(self): diff --git a/doorstop/core/publishers/html.py b/doorstop/core/publishers/html.py index ee5b2073..c279300e 100644 --- a/doorstop/core/publishers/html.py +++ b/doorstop/core/publishers/html.py @@ -355,17 +355,18 @@ def table_of_contents(self, linkify=None, obj=None): for item in iter_items(toc_doc): # Check if item has the attribute heading. if item.heading: - lines = item.text.splitlines() - heading = lines[0] if lines else "" + heading = item.title() elif item.header: heading = "{h}".format(h=item.header) else: heading = item.uid + if settings.PUBLISH_HEADING_LEVELS: level = format_level(item.level) lbl = "{lev} {h}".format(lev=level, h=heading) else: lbl = heading + if linkify: uid = item.uid else: diff --git a/doorstop/core/publishers/latex.py b/doorstop/core/publishers/latex.py index b6be649d..118f5730 100644 --- a/doorstop/core/publishers/latex.py +++ b/doorstop/core/publishers/latex.py @@ -98,25 +98,23 @@ def lines(self, obj, **kwargs): heading_level = "\\" + "sub" * (item.depth - 1) + "section{" if item.heading: - text_lines = item.text.splitlines() - if item.header: - text_lines.insert(0, item.header) + title = item.title() # Level and Text if settings.PUBLISH_HEADING_LEVELS: standard = "{h}{t}{he}".format( h=heading_level, - t=_latex_convert(text_lines[0]) if text_lines else "", + t=_latex_convert(title) if title else "", he="}", ) else: standard = "{h}{t}{he}".format( h=heading, - t=_latex_convert(text_lines[0]) if text_lines else "", + t=_latex_convert(title) if title else "", he="}", ) attr_list = self.format_attr_list(item, True) yield standard + attr_list - yield from self._format_latex_text(text_lines[1:]) + yield from self._format_latex_text(item.text.splitlines()) else: uid = item.uid if settings.ENABLE_HEADERS: diff --git a/doorstop/core/publishers/markdown.py b/doorstop/core/publishers/markdown.py index 3642158c..ef2089e0 100644 --- a/doorstop/core/publishers/markdown.py +++ b/doorstop/core/publishers/markdown.py @@ -168,8 +168,7 @@ def table_of_contents(self, linkify=None, obj=None): # Check if item has the attribute heading. if item.heading: - lines = item.text.splitlines() - heading = lines[0] if lines else "" + heading = item.title() elif item.header: heading = "{h}".format(h=item.header) else: @@ -214,17 +213,14 @@ def _generate_heading_from_item(self, item, to_html=False): heading = "#" * item.depth level = format_level(item.level) if item.heading: - text_lines = item.text.splitlines() - if item.header: - text_lines.insert(0, item.header) # Level and Text if settings.PUBLISH_HEADING_LEVELS: standard = "{h} {lev} {t}".format( - h=heading, lev=level, t=text_lines[0] if text_lines else "" + h=heading, lev=level, t=item.title() ) else: standard = "{h} {t}".format( - h=heading, t=text_lines[0] if text_lines else "" + h=heading, t=item.title() ) attr_list = self.format_attr_list(item, True) result = standard + attr_list