@entropicwarrior/sdoc 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/package.json +1 -1
- package/src/sdoc.js +25 -2
package/README.md
CHANGED
|
@@ -74,7 +74,17 @@ Key resources for agents:
|
|
|
74
74
|
| [`docs/reference/sdoc-authoring.sdoc`](https://raw.githubusercontent.com/entropicwarrior/sdoc/main/docs/reference/sdoc-authoring.sdoc) | Skill document — drop into context to read/write SDOC immediately |
|
|
75
75
|
| [`lexica/specification.sdoc`](https://raw.githubusercontent.com/entropicwarrior/sdoc/main/lexica/specification.sdoc) | Formal spec with EBNF grammar |
|
|
76
76
|
|
|
77
|
-
All `.sdoc` files are designed for progressive disclosure
|
|
77
|
+
All `.sdoc` files are designed for progressive disclosure. The JavaScript API provides three functions that let agents navigate without loading entire files:
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
const { extractAbout, listSections, extractSection } = require("@entropicwarrior/sdoc");
|
|
81
|
+
|
|
82
|
+
extractAbout(text); // ~50 tokens — what is this file about?
|
|
83
|
+
listSections(text); // ~50-100 tokens — what sections does it have?
|
|
84
|
+
extractSection(text, "error-handling"); // ~200-1000 tokens — give me just this section
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Total cost for a precise answer: ~750 tokens. The same lookup in Markdown requires loading the full file (5,000-50,000 tokens).
|
|
78
88
|
|
|
79
89
|
## Format at a Glance
|
|
80
90
|
|
|
@@ -159,7 +169,7 @@ Markdown-style images with optional width and alignment:
|
|
|
159
169
|
|
|
160
170
|
### Tables
|
|
161
171
|
|
|
162
|
-
Pipe-delimited tables with optional flags for appearance (`borderless`, `headerless`), width (`auto`, `60%`, `400px`), and alignment (`left`, `center`, `right`). All flags compose freely.
|
|
172
|
+
Pipe-delimited tables with optional flags for appearance (`borderless`, `headerless`), width (`auto`, `60%`, `400px`), and alignment (`left`, `center`, `right`). All flags compose freely. Cells starting with `=` are evaluated as formulas (`=SUM`, `=AVG`, `=COUNT`, arithmetic with A1 cell references).
|
|
163
173
|
|
|
164
174
|
### Lists
|
|
165
175
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@entropicwarrior/sdoc",
|
|
3
3
|
"displayName": "SDOC",
|
|
4
4
|
"description": "A plain-text documentation format with explicit brace scoping — deterministic parsing, AI-agent efficiency, and 10-50x token savings vs Markdown.",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.7",
|
|
6
6
|
"publisher": "entropicwarrior",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
package/src/sdoc.js
CHANGED
|
@@ -2781,8 +2781,31 @@ function firstParagraphPreview(nodes, maxLen) {
|
|
|
2781
2781
|
return "";
|
|
2782
2782
|
}
|
|
2783
2783
|
|
|
2784
|
+
/**
|
|
2785
|
+
* Recursively collect all tagged (has @id) scope nodes from the content tree.
|
|
2786
|
+
* Skips @meta and @about. Used for deep section discovery — lets MCP clients
|
|
2787
|
+
* find sections nested inside top-level scopes (e.g. @pass-terminology inside
|
|
2788
|
+
* @pedantic-review inside @writing).
|
|
2789
|
+
*/
|
|
2790
|
+
function getAllTaggedScopes(nodes) {
|
|
2791
|
+
const result = [];
|
|
2792
|
+
function walk(nodeList) {
|
|
2793
|
+
for (const node of nodeList) {
|
|
2794
|
+
if (node.type === "scope") {
|
|
2795
|
+
if (node.id && node.id.toLowerCase() !== "meta" && node.id.toLowerCase() !== "about") {
|
|
2796
|
+
result.push(node);
|
|
2797
|
+
}
|
|
2798
|
+
if (node.children) walk(node.children);
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
const doc = getDocumentScope(nodes);
|
|
2803
|
+
walk(doc ? doc.children : nodes);
|
|
2804
|
+
return result;
|
|
2805
|
+
}
|
|
2806
|
+
|
|
2784
2807
|
function listSections(nodes) {
|
|
2785
|
-
return
|
|
2808
|
+
return getAllTaggedScopes(nodes).map((node) => ({
|
|
2786
2809
|
id: node.id || null,
|
|
2787
2810
|
derivedId: slugify(node.title),
|
|
2788
2811
|
title: node.title,
|
|
@@ -2802,7 +2825,7 @@ function collectDataBlocks(children) {
|
|
|
2802
2825
|
}
|
|
2803
2826
|
|
|
2804
2827
|
function extractSection(nodes, sectionId) {
|
|
2805
|
-
const scopes =
|
|
2828
|
+
const scopes = getAllTaggedScopes(nodes);
|
|
2806
2829
|
|
|
2807
2830
|
function buildResult(node) {
|
|
2808
2831
|
const data = collectDataBlocks(node.children || []);
|