Skip to content

Commit 7e609a6

Browse files
committed
udpate
1 parent 24e7696 commit 7e609a6

6 files changed

Lines changed: 158 additions & 98 deletions

File tree

docs/conf.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@
8686
autoclass_content = 'init'
8787
autodoc_typehints = 'description'
8888

89-
extensions.append('sphinx.ext.intersphinx')
90-
intersphinx_mapping = {
91-
'python': ('https://docs.python.org/3', None),
92-
'sphinx': ('https://www.sphinx-doc.org/en/master', None),
93-
'jinja': ('https://jinja.palletsprojects.com/en/latest/', None),
94-
}
89+
# extensions.append('sphinx.ext.intersphinx')
90+
# intersphinx_mapping = {
91+
# 'python': ('https://docs.python.org/3', None),
92+
# 'sphinx': ('https://www.sphinx-doc.org/en/master', None),
93+
# 'jinja': ('https://jinja.palletsprojects.com/en/latest/', None),
94+
# }
9595

9696
extensions.append('sphinx_sitemap')
9797
sitemap_filename = "sitemap.xml"

docs/index.rst

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -5,84 +5,31 @@
55
sphinxnotes-data
66
================
77

8-
.. |docs| image:: https://img.shields.io/github/deployments/sphinx-notes/data/github-pages?label=docs
9-
:target: https://sphinx.silverrainz.me/data
10-
:alt: Documentation Status
11-
.. |license| image:: https://img.shields.io/github/license/sphinx-notes/data
12-
:target: https://github.com/sphinx-notes/data/blob/master/LICENSE
13-
:alt: Open Source License
14-
.. |pypi| image:: https://img.shields.io/pypi/v/sphinxnotes-data.svg
15-
:target: https://pypistats.org/packages/sphinxnotes-data
16-
:alt: PyPI Package
17-
.. |download| image:: https://img.shields.io/pypi/dm/sphinxnotes-data
18-
:target: https://pypi.python.org/pypi/sphinxnotes-data
19-
:alt: PyPI Package Downloads
20-
.. |github| image:: https://img.shields.io/badge/GitHub-181717?style=flat&logo=github&logoColor=white/
21-
:target: https://github.com/sphinx-notes/data
22-
:alt: GitHub Repository
8+
.. data:tmpl::
9+
:on: parsed
10+
:debug:
2311

24-
|docs| |license| |pypi| |download| |github|
12+
Name: {{ name }}
2513

26-
Introduction
27-
============
14+
{% for k, v in attrs.items() %}
15+
:{{ k }}: {{ v }}
16+
{%- endfor %}
2817

29-
.. INTRODUCTION START
18+
Content::
3019

31-
.. INTRODUCTION END
20+
{{ content }}
3221

33-
Getting Started
34-
===============
22+
.. data:schema:: int
23+
:color: bool, required
24+
:size: int, required
3525

36-
.. note::
26+
lines of int
3727

38-
We assume you already have a Sphinx documentation,
39-
if not, see `Getting Started with Sphinx`_.
28+
1
29+
=
4030

31+
.. data:def::
32+
:color:
33+
:size: 1
4134

42-
First, downloading extension from PyPI:
43-
44-
.. code-block:: console
45-
46-
$ pip install sphinxnotes-data
47-
48-
49-
Then, add the extension name to ``extensions`` configuration item in your
50-
:parsed_literal:`conf.py_`:
51-
52-
.. code-block:: python
53-
54-
extensions = [
55-
#
56-
'sphinxnotes.data',
57-
#
58-
]
59-
60-
.. _Getting Started with Sphinx: https://www.sphinx-doc.org/en/master/usage/quickstart.html
61-
.. _conf.py: https://www.sphinx-doc.org/en/master/usage/configuration.html
62-
63-
.. ADDITIONAL CONTENT START
64-
65-
.. ADDITIONAL CONTENT END
66-
67-
Contents
68-
========
69-
70-
.. toctree::
71-
:caption: Contents
72-
73-
changelog
74-
75-
The Sphinx Notes Project
76-
========================
77-
78-
The project is developed by `Shengyu Zhang`__,
79-
as part of **The Sphinx Notes Project**.
80-
81-
.. toctree::
82-
:caption: The Sphinx Notes Project
83-
84-
Home <https://sphinx.silverrainz.me/>
85-
Blog <https://silverrainz.me/blog/category/sphinx.html>
86-
PyPI <https://pypi.org/search/?q=sphinxnotes>
87-
88-
__ https://github.com/SilverRainZ
35+
Section Body

src/sphinxnotes/data/__init__.py

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
"""
88

99
from __future__ import annotations
10+
from os import wait
1011
from typing import Any
1112

1213
from docutils import nodes
1314
from docutils.parsers.rst import directives
14-
15+
from docutils.statemachine import StringList
1516
from sphinx.util import logging
1617
from sphinx.util.docutils import SphinxDirective, SphinxRole
1718
from sphinx.application import Sphinx
@@ -21,7 +22,7 @@
2122
from .freestyle import FreeStyleDirective, FreeStyleOptionSpec
2223
from .data import Data, Field, Schema, Raw
2324
from .render import Template, Phase, render, JinjaEnv
24-
from .utils import find_current_document, find_current_section, TempData
25+
from .utils import find_current_document, find_current_section, TempData, find_first_child
2526
from .context_proxy import proxy
2627

2728
logger = logging.getLogger(__name__)
@@ -126,8 +127,56 @@ def sphinx_context(v: SphinxDirective | SphinxRole | SphinxTransform) -> dict[st
126127
ctx['_config'] = proxy(v.config)
127128
return ctx
128129

130+
class BaseDefineDirective():
131+
def extract_raw_data(self) -> Raw:
132+
return Raw(
133+
self.arguments[0] if self.arguments else None,
134+
self.options.copy(),
135+
'\n'.join(self.content) if self.has_content else None,
136+
)
129137

130-
class DataDefineDirective(FreeStyleDirective):
138+
class AutoDirective(BaseDefineDirective):
139+
def _lookup_titular_node(self, node: nodes.Element | None) -> nodes.Node | None:
140+
if node is None:
141+
logger.warning('none')
142+
return None
143+
if isinstance(node, (nodes.section, nodes.sidebar)):
144+
logger.warning('section')
145+
if title := find_first_child(node, nodes.title):
146+
logger.warning('title')
147+
return title
148+
if isinstance(node, nodes.definition_list_item):
149+
logger.warning('definition_list_item')
150+
if term := find_first_child(node, nodes.term):
151+
logger.warning('definition_list_item')
152+
return term
153+
if isinstance(node, nodes.field):
154+
logger.warning('field')
155+
if field := find_first_child(node, nodes.field_name):
156+
logger.warning('field_name')
157+
return field
158+
if isinstance(node, nodes.list_item):
159+
logger.warning('listitem')
160+
if para := find_first_child(node, nodes.paragraph):
161+
logger.warning('paragraph')
162+
return para
163+
return self._lookup_titular_node(node.parent)
164+
165+
166+
def extract_raw_data(self) -> Raw:
167+
raw = super().extract_raw_data()
168+
if not raw.name:
169+
logger.warning('>>>>>>>>>>>>>>>>>>>>>>>>')
170+
if title := self._lookup_titular_node(self.state.parent):
171+
raw.name = title.astext()
172+
logger.warning(f'{raw.name}')
173+
logger.warning('<<<<<<<<<<<<<<<<<<<<<<<<')
174+
if not raw.content:
175+
raw.content_missing = True
176+
return raw
177+
178+
179+
class DefineDirective(FreeStyleDirective, AutoDirective):
131180
optional_arguments = 1
132181
has_content = True
133182

@@ -137,7 +186,7 @@ def run(self) -> list[nodes.Node]:
137186
return []
138187

139188
schema = SchemaStore.get(self.state.document)
140-
rawdata = self._raw_data()
189+
rawdata = self.extract_raw_data()
141190

142191
if tmpl.phase != Phase.Parsing:
143192
n = pending_node()
@@ -164,23 +213,22 @@ def run(self) -> list[nodes.Node]:
164213

165214
return [n]
166215

167-
def _raw_data(self) -> Raw:
168-
return Raw(
169-
self.arguments[0] if self.arguments else None,
170-
self.options.copy(),
171-
'\n'.join(self.content),
172-
)
173-
174-
175216
class ParsedHookDirective(SphinxDirective):
176217
def run(self) -> list[nodes.Node]:
177218
for pending in self.state.document.findall(pending_node):
178219
tmpl = TemplateStore.get(pending)
179220
schema = SchemaStore.get(pending)
180221
rawdata = RawDataStore.get(pending)
181222

182-
assert tmpl
183-
assert rawdata
223+
assert tmpl and rawdata
224+
225+
if rawdata.content_missing:
226+
contnodes = []
227+
for i, child in enumerate(pending.parent):
228+
if child == pending:
229+
contnodes = pending.parent[i:]
230+
rawdata.content = '\n\n'.join([n.astext() for n in contnodes])
231+
rawdata.content_missing = False
184232

185233
if schema:
186234
try:
@@ -200,7 +248,6 @@ def run(self) -> list[nodes.Node]:
200248

201249
return [] # nothing to return
202250

203-
204251
def on_source_read(app, docname, content):
205252
# NOTE: content is a single element list, representing the content of the
206253
# source file.
@@ -239,7 +286,7 @@ def setup(app: Sphinx):
239286
app.add_directive('data:tmpl', TemplateDirective, False)
240287
app.add_directive('data:schema', DataSchemaDirective, False)
241288
# app.add_directive('data:use-tmpl', DataTemplateDirective, False)
242-
app.add_directive('data:def', DataDefineDirective, False)
289+
app.add_directive('data:def', DefineDirective, False)
243290
app.add_directive('data:parsed-hook', ParsedHookDirective, False)
244291

245292
app.connect('source-read', on_source_read)

src/sphinxnotes/data/auto.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
from typing import Any
3+
4+
from docutils import nodes
5+
from docutils.statemachine import StringList
6+
from sphinx.util import logging
7+
from sphinx.util.docutils import SphinxDirective
8+
9+
from .utils import find_first_child
10+
11+
12+
logger = logging.getLogger(__name__)
13+
14+
class AutoDirective(SphinxDirective):
15+
_arguments: list[str] = []
16+
_content: StringList
17+
18+
@property
19+
def arguments(self) -> list[str]:
20+
if not self._arguments:
21+
return self._arguments
22+
23+
if title := self.lookup_titular_node(self.state.parent):
24+
return [title.astext()]
25+
26+
return []
27+
28+
@arguments.setter
29+
def arguments(self, value: list[str]) -> None: # type: ignore
30+
if len(value) != 0:
31+
self._arguments = value
32+
33+
@property
34+
def content(self) -> StringList:
35+
if self._content:
36+
return self._content
37+
return self._content
38+
39+
@content.setter
40+
def content(self, _: StringList) -> None:... # type: ignore
41+
42+
def lookup_titular_node(self, node: nodes.Element | None) -> nodes.Node | None:
43+
if node is None:
44+
return None
45+
if isinstance(node, (nodes.section, nodes.sidebar)):
46+
if title := find_first_child(node, nodes.Titular):
47+
return title
48+
if isinstance(node, nodes.definition_list_item):
49+
if term := find_first_child(node, nodes.term):
50+
return term
51+
if isinstance(node, nodes.field):
52+
if term := find_first_child(node, nodes.field_name):
53+
return term
54+
if isinstance(node, nodes.list_item):
55+
if term := find_first_child(node, nodes.paragraph):
56+
return term
57+
return self.lookup_titular_node(node.parent)

src/sphinxnotes/data/data.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
type Value = None | int | float | str | bool | list[Value]
88

99

10-
@dataclasses.dataclass(frozen=True)
10+
@dataclasses.dataclass()
1111
class Raw(object):
1212
name: str | None
1313
attrs: dict[str, str]
14-
content: str
14+
content: str | None
15+
content_missing: bool = False
1516

1617

1718
@dataclasses.dataclass(frozen=True)

src/sphinxnotes/data/utils.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from docutils.frontend import get_default_settings
66
from docutils.parsers.rst import Parser
77
from docutils.utils import new_document
8+
from sphinx.util import logging
89

910
from dacite import from_dict
1011

12+
logger = logging.getLogger(__name__)
1113

1214
def parse_text_to_nodes(text: str) -> list[nodes.Node]:
1315
"""
@@ -20,10 +22,10 @@ def parse_text_to_nodes(text: str) -> list[nodes.Node]:
2022
return document.children
2123

2224

23-
_Element = TypeVar('_Element', bound=nodes.Element)
25+
_Node = TypeVar('_Element', bound=nodes.Node)
2426

2527

26-
def find_parent(node: nodes.Element | None, typ: type[_Element]) -> _Element | None:
28+
def find_parent(node: nodes.Element | None, typ: type[_Node]) -> _Node | None:
2729
if node is None or isinstance(node, typ):
2830
return node
2931
return find_parent(node.parent, typ)
@@ -37,6 +39,12 @@ def find_current_document(node: nodes.Element | None) -> nodes.document | None:
3739
return find_parent(node, nodes.document)
3840

3941

42+
def find_first_child(node: nodes.Element, cls: type[_Node]) -> _Node | None:
43+
if (index := node.first_child_matching_class(cls)) is None:
44+
return None
45+
return node[index] # type: ignore
46+
47+
4048
DataT = TypeVar('DataT')
4149

4250

0 commit comments

Comments
 (0)