Skip to content

Commit 446c4cb

Browse files
committed
feat: Support inline rendering
1 parent 0b6ea52 commit 446c4cb

9 files changed

Lines changed: 471 additions & 371 deletions

File tree

src/sphinxnotes/data/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727
from .render import (
2828
Caller,
2929
pending_node,
30-
RenderedNode,
3130
rendered_node,
32-
rendered_inline_node,
3331
BaseDataDefiner,
3432
BaseDataDefineRole,
3533
BaseDataDefineDirective,
@@ -59,9 +57,8 @@
5957
'Template',
6058
'Caller',
6159
'pending_node',
62-
'RenderedNode',
6360
'rendered_node',
64-
'rendered_inline_node',
61+
'rendered_node',
6562
'BaseDataDefiner',
6663
'BaseDataDefineRole',
6764
'BaseDataDefineDirective',
@@ -86,6 +83,7 @@ def extractx(cls) -> ExtraContextRegistry:
8683

8784
REGISTRY = Registry()
8885

86+
8987
def setup(app: Sphinx):
9088
meta.pre_setup(app)
9189

src/sphinxnotes/data/adhoc.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"""
1414

1515
from __future__ import annotations
16-
from typing import TYPE_CHECKING, cast, override
16+
from typing import TYPE_CHECKING, override
17+
18+
from typing import cast
1719

1820
from docutils import nodes
1921
from docutils.parsers.rst import directives
@@ -67,6 +69,10 @@ def run(self) -> list[nodes.Node]:
6769
return []
6870

6971

72+
if TYPE_CHECKING:
73+
...
74+
75+
7076
class FreeDataDefineDirective(BaseDataDefineDirective, FreeStyleDirective):
7177
optional_arguments = 1
7278
has_content = True

src/sphinxnotes/data/data.py

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
"""
1010

1111
from __future__ import annotations
12-
from typing import TYPE_CHECKING, override
12+
from typing import TYPE_CHECKING
1313
import re
1414
from dataclasses import dataclass, asdict, field as dataclass_field
1515
from ast import literal_eval
16-
from abc import ABC, abstractmethod
16+
17+
from .utils import Unpicklable
1718

1819
if TYPE_CHECKING:
1920
from typing import Any, Callable, Generator, Self, Literal
@@ -210,25 +211,29 @@ def add_by_option(
210211
# ======================
211212

212213

213-
class Data(ABC):
214-
@abstractmethod
215-
def as_context(self) -> dict[str, Any]: ...
216-
217-
218214
@dataclass
219215
class RawData:
220216
name: str | None
221217
attrs: dict[str, str]
222218
content: str | None
223219

224220

221+
@dataclass
222+
class PendingData(Unpicklable):
223+
raw: RawData
224+
schema: Schema
225+
226+
def parse(self) -> ParsedData:
227+
return self.schema.parse(self.raw)
228+
229+
225230
@dataclass
226231
class ParsedData:
227232
name: Value
228233
attrs: dict[str, Value]
229234
content: Value
230235

231-
def as_context(self) -> dict[str, Any]:
236+
def asdict(self) -> dict[str, Any]:
232237
"""
233238
Convert Data to a dict for usage of Jinja2 context.
234239
@@ -247,23 +252,6 @@ def as_context(self) -> dict[str, Any]:
247252
return ctx
248253

249254

250-
@dataclass
251-
class PendingData(Data):
252-
raw: RawData
253-
schema: Schema
254-
_data: ParsedData | None = dataclass_field(init=False, default=None)
255-
256-
def parse(self) -> ParsedData:
257-
if self._data:
258-
return self._data
259-
self._data = self.schema.parse(self.raw)
260-
return self._data
261-
262-
@override
263-
def as_context(self) -> dict[str, Any]:
264-
return self.parse().as_context()
265-
266-
267255
@dataclass
268256
class Field:
269257
#: Type of element.

src/sphinxnotes/data/extractx.py

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
11
from __future__ import annotations
22
from typing import TYPE_CHECKING, override
3+
from dataclasses import dataclass
34

5+
from docutils import nodes
46
from sphinx.util.docutils import SphinxDirective, SphinxRole
57
from sphinx.transforms import SphinxTransform
68

7-
from .utils import find_current_document, find_current_section
9+
from .utils import find_current_section
810
from .utils.ctxproxy import proxy
9-
from .render import EXTRACTX_REGISTRY, ParsePhaseContextGenerator, FullPhaseContextGenerator, ParseCaller, Caller, pending_node
10-
from .template import Context
11+
from .renderer import Host, ParseHost
12+
from .render import (
13+
EXTRACTX_REGISTRY,
14+
ParsePhaseContextGenerator,
15+
RenderPhaseContextGenerator,
16+
)
17+
18+
if TYPE_CHECKING:
19+
from typing import Any
20+
21+
@dataclass
22+
class _Host:
23+
v: Host
24+
25+
@property
26+
def doctree(self) -> nodes.document:
27+
if isinstance(self.v, SphinxDirective):
28+
return self.v.state.document
29+
elif isinstance(self.v, SphinxRole):
30+
return self.v.inliner.document
31+
elif isinstance(self.v, SphinxTransform):
32+
return self.v.document
33+
else:
34+
raise NotImplementedError
35+
36+
@property
37+
def parent(self) -> nodes.Element | None:
38+
if isinstance(self.v, SphinxDirective):
39+
return self.v.state.parent
40+
elif isinstance(self.v, SphinxRole):
41+
return self.v.inliner.parent
42+
else:
43+
return None
1144

1245

1346
class MarkupContextGenerator(ParsePhaseContextGenerator):
1447
@override
15-
def generate(self, caller: ParseCaller, n: pending_node) -> Context:
48+
def generate(self, caller: ParseHost) -> Any:
1649
isdir = isinstance(caller, SphinxDirective)
1750
return {
1851
'type': 'directive' if isdir else 'role',
@@ -21,44 +54,34 @@ def generate(self, caller: ParseCaller, n: pending_node) -> Context:
2154
'rawtext': caller.block_text if isdir else caller.rawtext,
2255
}
2356

24-
class DocContextGenerator(FullPhaseContextGenerator):
57+
58+
class DocContextGenerator(RenderPhaseContextGenerator):
2559
@override
26-
def generate(self, caller: Caller, n: pending_node) -> Context:
27-
if isinstance(caller, SphinxDirective):
28-
return proxy(caller.state.document)
29-
elif isinstance(caller, SphinxRole):
30-
return proxy(caller.inliner.document)
31-
elif isinstance(caller, SphinxTransform):
32-
return proxy(caller.document)
33-
else:
34-
assert False
60+
def generate(self, caller: Host) -> Any:
61+
return proxy(_Host(caller).doctree)
3562

3663

37-
class SectionContextGenerator(FullPhaseContextGenerator):
64+
class SectionContextGenerator(ParsePhaseContextGenerator):
3865
@override
39-
def generate(self, caller: Caller, n: pending_node) -> Context:
40-
if n.parent:
41-
return proxy(find_current_section(n.parent))
42-
elif isinstance(caller, SphinxDirective):
43-
return proxy(find_current_section(caller.state.parent))
44-
elif isinstance(caller, SphinxRole):
45-
return proxy(caller.inliner.parent)
46-
else:
47-
assert False
66+
def generate(self, caller: ParseHost) -> Any:
67+
parent = _Host(caller).parent
68+
return proxy(find_current_section(parent))
4869

4970

50-
class SphinxEnvContextGenerator(FullPhaseContextGenerator):
71+
class SphinxEnvContextGenerator(RenderPhaseContextGenerator):
5172
@override
52-
def generate(self, caller: Caller, n: pending_node) -> Context:
73+
def generate(self, caller: Host) -> Any:
5374
return proxy(caller.env)
5475

55-
class SphinxConfigContextGenerator(FullPhaseContextGenerator):
76+
77+
class SphinxConfigContextGenerator(RenderPhaseContextGenerator):
5678
@override
57-
def generate(self, caller: Caller, n: pending_node) -> Context:
79+
def generate(self, caller: Host) -> Any:
5880
return proxy(caller.config)
5981

60-
EXTRACTX_REGISTRY.add_parsing_phase_context('markup', MarkupContextGenerator())
61-
EXTRACTX_REGISTRY.add_full_phase_context('doc', DocContextGenerator())
62-
EXTRACTX_REGISTRY.add_full_phase_context('section',SectionContextGenerator())
63-
EXTRACTX_REGISTRY.add_full_phase_context('env', SphinxEnvContextGenerator())
64-
EXTRACTX_REGISTRY.add_full_phase_context('config', SphinxConfigContextGenerator())
82+
83+
EXTRACTX_REGISTRY.add_parsing('markup', MarkupContextGenerator())
84+
EXTRACTX_REGISTRY.add_parsing('section', SectionContextGenerator())
85+
EXTRACTX_REGISTRY.add_render('doc', DocContextGenerator())
86+
EXTRACTX_REGISTRY.add_render('env', SphinxEnvContextGenerator())
87+
EXTRACTX_REGISTRY.add_render('config', SphinxConfigContextGenerator())

0 commit comments

Comments
 (0)