Skip to content

Commit

Permalink
fix: respect indentation in multiline Python comments (#37)
Browse files Browse the repository at this point in the history
Fixes cases when the docstring parser parses:

```
Args:
    first_param: has a multiline comment with a colon in the
        wrong: place
```

as `{ first_param: "has a multiline comment with a colon in the", wrong:
"place" }`.
  • Loading branch information
barjin authored Jan 8, 2025
1 parent 08610c3 commit dcad749
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 11 deletions.
2 changes: 1 addition & 1 deletion packages/plugin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@apify/docusaurus-plugin-typedoc-api",
"version": "4.3.5",
"version": "4.3.6",
"description": "Docusaurus plugin that provides source code API documentation powered by TypeDoc. ",
"keywords": [
"docusaurus",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ def check_docstring_format(self, docstring: str) -> bool:
def process(self, modules: t.List[docspec.Module], resolver: t.Optional[Resolver]) -> None:
docspec.visit(modules, self._process)

def get_indent_size(self, line: str) -> int:
return len(line) - len(line.lstrip())

def _process(self, node: docspec.ApiObject):
if not node.docstring:
return
Expand All @@ -131,6 +134,7 @@ def _process(self, node: docspec.ApiObject):
in_codeblock = False
keyword = None
multiline_argument_offset = -1
state = { 'param_indent': None }

def _commit():
if keyword:
Expand All @@ -139,6 +143,13 @@ def _commit():
lines.extend(current_lines)
current_lines.clear()

def is_continuation(line: str) -> bool:
if state.get('param_indent') is None:
state['param_indent'] = self.get_indent_size(line)
return False

return self.get_indent_size(line) > state.get('param_indent')

for line in node.docstring.content.split("\n"):
multiline_argument_offset += 1
if line.lstrip().startswith("```"):
Expand All @@ -152,29 +163,29 @@ def _commit():
current_lines.append(line)
continue

line = line.strip()
if line in self._keywords_map:
stripped = line.strip()
if stripped in self._keywords_map:
_commit()
keyword = self._keywords_map[line]
keyword = self._keywords_map[stripped]
continue

if keyword is None:
lines.append(line)
lines.append(stripped)
continue

for param_re in self._param_res:
param_match = param_re.match(line)
if param_match:
param_match = param_re.match(stripped)
if param_match and not is_continuation(line):
current_lines.append(param_match.groupdict())
multiline_argument_offset = 0
break

if not param_match:
if multiline_argument_offset == 1:
current_lines[-1]["desc"] += "\n" + line
current_lines[-1]["desc"] += "\n" + stripped
multiline_argument_offset = 0
else:
current_lines.append(line)
current_lines.append(stripped)

_commit()
node.docstring.content = json.dumps({
Expand Down
22 changes: 20 additions & 2 deletions playground/python/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,29 @@ def __init__(self):
"""
print("Bar")

def foo(self) -> Foo:
def foo(self, count: int) -> Foo:
"""
The foo method of the bar class, prints "foo".
Args:
count: The number of times to print "foo".
This comment is multiline, and contains
some urls too, look: https://apify.com
"""
print("foo " * count)

def foo2(self, count: int, second_arg: str) -> Foo:
"""
The foo2 method of the bar class, prints "foo2".
Args:
count: The number of times to print "foo2".
This comment is multiline, and contains some urls too,
look: https://apify.com
second_arg: The second argument. This shouldn't be a part of the previous argument's
description: even with a colon.
"""
print("foo")
print("foo2 " * count)

@docs_group('Classes')
class BarBar(Bar):
Expand Down

0 comments on commit dcad749

Please sign in to comment.