drakongen 1.2.0 → 1.4.2
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/.vscode/launch.json +2 -2
- package/README.md +80 -4
- package/browser/drakongen.js +113 -36
- package/browsertest.html +4 -2
- package/buildexamples.js +1 -1
- package/buildprojectexample +1 -0
- package/exampleproject/class Point.graf +24 -0
- package/exampleproject/foo.drakon +51 -0
- package/exampleproject/foo.proj +4 -0
- package/exampleproject/foo.txt +45 -0
- package/exampleproject/math/approximately equal.drakon +42 -0
- package/exampleproject/start.txt +3 -0
- package/examples/00.Empty.txt +2 -1
- package/examples/01. /320/221/320/265/320/273/321/213/320/271.txt" +2 -1
- package/examples/02. /320/247/321/221/321/200/320/275/321/213/320/271.txt" +1 -3
- package/examples/03. /320/241/320/265/321/200/321/213/320/271.txt" +2 -1
- package/examples/04. /320/221/321/203/321/200/321/213/320/271.txt" +1 -1
- package/examples/05. /320/226/321/221/320/273/321/202/321/213/320/271.txt" +1 -1
- package/examples/06. /320/221/320/260/320/263/321/200/320/276/320/262/321/213/320/271.txt" +1 -2
- package/examples/07. /320/244/320/270/320/276/320/273/320/265/321/202/320/276/320/262/321/213/320/271.txt" +1 -3
- package/examples/08. /320/221/320/270/321/200/321/216/320/267/320/276/320/262/321/213/320/271.txt" +2 -1
- package/examples/09. /320/236/321/200/320/260/320/275/320/266/320/265/320/262/321/213/320/271.txt" +1 -2
- package/examples/10. /320/240/320/276/320/267/320/276/320/262/321/213/320/271.txt" +1 -4
- package/examples/11. /320/227/320/260/321/211/320/270/321/202/320/275/321/213/320/271.txt" +1 -2
- package/examples/12. /320/221/320/276/320/273/320/276/321/202/320/275/321/213/320/271.txt" +1 -2
- package/examples/13. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +1 -4
- package/examples/14. /320/227/320/276/320/273/320/276/321/202/320/276/320/271.txt" +1 -6
- package/examples/15. /320/241/320/270/320/275/320/270/320/271.txt" +1 -7
- package/examples/16. /320/223/320/276/320/273/321/203/320/261/320/276/320/271.txt" +1 -3
- package/examples/17. /320/241/320/260/320/273/320/260/321/202/320/276/320/262/321/213/320/271.txt" +1 -1
- package/examples/18. /320/241/321/202/320/260/320/273/321/214/320/275/320/276/320/271.txt" +1 -5
- package/examples/19. Lilla.txt +1 -1
- package/examples/Adaptive design.txt +3 -19
- package/examples/And test.txt +1 -2
- package/examples/Arrow - double exit.txt +1 -2
- package/examples/Comments.drakon +81 -0
- package/examples/Comments.txt +19 -0
- package/examples/Complex arrow.txt +1 -9
- package/examples/DoubleArrow.txt +1 -2
- package/examples/Find pointing nodes.txt +1 -6
- package/examples/How to tune PID on a quadcopter.txt +12 -38
- package/examples/Mind one.graf +69 -0
- package/examples/Mind one.txt +18 -0
- package/examples/Or test.txt +1 -2
- package/examples/Silhouette test 1.drakon +35 -5
- package/examples/Silhouette test 1.txt +14 -7
- package/examples/Work out action-check.txt +2 -2
- package/examples/Workout foreach.txt +2 -4
- package/examples/ar01.txt +2 -1
- package/examples/ar02.txt +1 -1
- package/examples/ar03.txt +2 -1
- package/examples/ar04.txt +1 -1
- package/examples/ar05.txt +1 -1
- package/examples/ar06.txt +3 -3
- package/examples/ar07.txt +3 -3
- package/examples/ar08.txt +4 -4
- package/examples/ar09.txt +3 -4
- package/examples/ar10.txt +3 -4
- package/examples/ar11.txt +3 -3
- package/examples/ar12.txt +1 -1
- package/examples/getToken.txt +4 -14
- package/examples/hello.txt +4 -0
- package/examples/sil2.drakon +74 -0
- package/examples/sil2.txt +27 -0
- package/examples/tmp.txt +3 -8
- package/package.json +1 -1
- package/prompts/project/generateProject.drakon +87 -0
- package/prompts/project/options.txt +3 -0
- package/prompts/project/process file.drakon +30 -0
- package/prompts/project/process folder.drakon +53 -0
- package/prompts/project/project.proj +5 -0
- package/prompts/project/project.txt +80 -0
- package/prompts/project/start.txt +4 -0
- package/src/browserTools.js +0 -4
- package/src/drakonToPromptStruct.js +81 -8
- package/src/drakonToStruct.js +4 -3
- package/src/drakongen.js +7 -1
- package/src/index.js +9 -3
- package/src/main.js +66 -11
- package/src/nodeTools.js +0 -4
- package/src/printPseudo.js +14 -17
- package/src/tools.js +5 -1
- package/src/treeTools.js +2 -2
package/.vscode/launch.json
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# drakongen
|
|
2
2
|
|
|
3
|
-
**drakongen** generates pseudocode from drakon flowcharts built with [DrakonWidget](https://github.com/stepan-mitkin/drakonwidget) or [DrakonHub](https://github.com/stepan-mitkin/drakonhub_desktop).
|
|
3
|
+
**drakongen** generates pseudocode from drakon flowcharts and mind-maps built with [DrakonWidget](https://github.com/stepan-mitkin/drakonwidget) or [DrakonHub](https://github.com/stepan-mitkin/drakonhub_desktop).
|
|
4
4
|
|
|
5
|
-
One can use the output pseudocode as a prompt for AI applications like ChatGPT or
|
|
5
|
+
One can use the output pseudocode as a prompt for AI applications like ChatGPT, Grok, or Gemini.
|
|
6
6
|
|
|
7
7
|
**drakongen** can also generate a generic AST from drakon flowcharts to generate source code in programming languages, for example, JavaScript.
|
|
8
8
|
**drakongen** turns a drakon flowchart into a tree in the JSON format that one can trivially transform into code in any programming language.
|
|
@@ -15,17 +15,21 @@ Include the `drakongen.js` script on the web page.
|
|
|
15
15
|
<script src="browser/drakongen.js"></script>
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Call `drakongen.toPseudocode` or `drakongen.toTree` functions.
|
|
18
|
+
Call `drakongen.toPseudocode`, `drakongen.toMindTree`, or `drakongen.toTree` functions.
|
|
19
19
|
|
|
20
20
|
```html
|
|
21
21
|
<script>
|
|
22
22
|
var drakon = ... // Get the drakon chart from DrakonWidget
|
|
23
|
+
var mindJson = ... // Graf mind-map as json
|
|
23
24
|
var name = "Diagram one"
|
|
24
25
|
var filename = "Diagram one.drakon"
|
|
25
26
|
|
|
26
27
|
var pseudo = drakongen.toPseudocode(drakon, name, filename, "en")
|
|
27
28
|
console.log(pseudo)
|
|
28
29
|
|
|
30
|
+
var mind = drakongen.toMindTree(mindJson, name, filename)
|
|
31
|
+
console.log(mind)
|
|
32
|
+
|
|
29
33
|
var tree = drakongen.toTree(drakon, name, filename, "en")
|
|
30
34
|
console.log(tree)
|
|
31
35
|
|
|
@@ -47,18 +51,22 @@ npm i drakongen
|
|
|
47
51
|
```
|
|
48
52
|
|
|
49
53
|
- Require the **drakongen** module.
|
|
50
|
-
- Call `toPseudocode` or `toTree` functions.
|
|
54
|
+
- Call `toPseudocode`, `toMindTree`, or `toTree` functions.
|
|
51
55
|
|
|
52
56
|
```javascript
|
|
53
57
|
const {toTree, toPseudocode} = require("drakongen")
|
|
54
58
|
|
|
55
59
|
var drakon = ... // Get the drakon chart from DrakonWidget
|
|
60
|
+
var mindJson = ... // Graf mind-map as json
|
|
56
61
|
var name = "Diagram one"
|
|
57
62
|
var filename = "Diagram one.drakon"
|
|
58
63
|
|
|
59
64
|
var pseudo = toPseudocode(drakon, name, filename, "en")
|
|
60
65
|
console.log(pseudo)
|
|
61
66
|
|
|
67
|
+
var mind = toMindTree(mindJson, name, filename)
|
|
68
|
+
console.log(mind)
|
|
69
|
+
|
|
62
70
|
var tree = toTree(drakon, name, filename, "en")
|
|
63
71
|
console.log(tree)
|
|
64
72
|
```
|
|
@@ -73,8 +81,76 @@ npm i --global drakongen
|
|
|
73
81
|
|
|
74
82
|
Run the **drakongen** utility.
|
|
75
83
|
|
|
84
|
+
### Generate from one file
|
|
85
|
+
|
|
86
|
+
A .drakon flowchart will be converted to pseudocode.
|
|
87
|
+
|
|
88
|
+
A .graf mind-map will be converted to tree-like text.
|
|
89
|
+
|
|
76
90
|
In this example, the language is Norwegian, the path to the output folder is **out**, the input file is **Hello.drakon**:
|
|
77
91
|
|
|
78
92
|
```
|
|
79
93
|
drakongen --language no --output out Hello.drakon
|
|
80
94
|
```
|
|
95
|
+
|
|
96
|
+
## Project mode
|
|
97
|
+
|
|
98
|
+
Drakongen in project mode generates a single prompt file by processing and concatenating multiple input files, including flowcharts, mind-maps, text files, and directories. It reads a project file specifying the input files, processes them in the defined order, and outputs a consolidated prompt file suitable for AI-driven code generation.
|
|
99
|
+
|
|
100
|
+
### Features
|
|
101
|
+
|
|
102
|
+
- **Processes multiple file types**:
|
|
103
|
+
- Plain text files (e.g., `.txt`) are included as-is.
|
|
104
|
+
- Mind-map files (e.g., `.graf`) are converted to indented text.
|
|
105
|
+
- Flowchart files (e.g., `.drakon`) are converted to pseudocode.
|
|
106
|
+
- Directories are recursively processed, including all files within.
|
|
107
|
+
- **Preserves file order**: Files are processed and concatenated in the exact order specified in the project file, which is critical for AI tools relying on sequential context.
|
|
108
|
+
- **Flexible project file format**: A simple text-based project file lists files and directories to process.
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### Usage
|
|
112
|
+
|
|
113
|
+
Run the tool with the following command:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
drakongen --project <project_file> --output <output_directory>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- `--project`: Path to the project file (e.g., `exampleproject/foo.proj`).
|
|
120
|
+
- `--output`: Directory where the output prompt file will be saved (e.g., `exampleproject`).
|
|
121
|
+
|
|
122
|
+
### Example
|
|
123
|
+
|
|
124
|
+
Given a project file `exampleproject/foo.proj` with the following content:
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
start.txt
|
|
129
|
+
math
|
|
130
|
+
class Point.graf
|
|
131
|
+
foo.drakon
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Run:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
drakongen --project exampleproject/foo.proj --output exampleproject
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This will:
|
|
141
|
+
|
|
142
|
+
1. Include `start.txt` as-is.
|
|
143
|
+
2. Process all files in the `math` directory recursively.
|
|
144
|
+
3. Convert `class Point.graf` (mind-map) to indented text.
|
|
145
|
+
4. Convert `foo.drakon` (flowchart) to pseudocode.
|
|
146
|
+
5. Concatenate all processed content into `exampleproject/foo.txt`.
|
|
147
|
+
|
|
148
|
+
The output file `foo.txt` will contain the concatenated text in the exact order specified in `foo.proj`.
|
|
149
|
+
|
|
150
|
+
### Project File Format
|
|
151
|
+
|
|
152
|
+
The project file (e.g., `foo.proj`) is a plain text file where each line specifies:
|
|
153
|
+
|
|
154
|
+
- A file path (relative to the project file) for a text, mind-map, or flowchart file.
|
|
155
|
+
- A directory path to process all files within it recursively.
|
|
156
|
+
|
package/browser/drakongen.js
CHANGED
|
@@ -16,21 +16,17 @@ function htmlToString(html) {
|
|
|
16
16
|
if (node.tagName === 'P') {
|
|
17
17
|
output.push(node.textContent.trim());
|
|
18
18
|
} else if (node.tagName === 'UL') {
|
|
19
|
-
output.push('');
|
|
20
19
|
node.childNodes.forEach((item) => {
|
|
21
20
|
if (item.tagName === 'LI') {
|
|
22
21
|
output.push(`- ${item.textContent.trim()}`);
|
|
23
22
|
}
|
|
24
23
|
});
|
|
25
|
-
output.push('');
|
|
26
24
|
} else if (node.tagName === 'OL') {
|
|
27
|
-
output.push('');
|
|
28
25
|
node.childNodes.forEach((item, index) => {
|
|
29
26
|
if (item.tagName === 'LI') {
|
|
30
27
|
output.push(`${index + 1}. ${item.textContent.trim()}`);
|
|
31
28
|
}
|
|
32
29
|
});
|
|
33
|
-
output.push('');
|
|
34
30
|
}
|
|
35
31
|
});
|
|
36
32
|
|
|
@@ -40,18 +36,17 @@ function htmlToString(html) {
|
|
|
40
36
|
module.exports = {htmlToString}
|
|
41
37
|
},{}],2:[function(require,module,exports){
|
|
42
38
|
const {drakonToStruct} = require("./drakonToStruct");
|
|
43
|
-
const {printPseudo} = require('./printPseudo');
|
|
44
|
-
const {addRange} = require("./tools")
|
|
39
|
+
const {printPseudo, printWithIndent, makeIndent} = require('./printPseudo');
|
|
40
|
+
const {addRange, sortByProperty} = require("./tools")
|
|
45
41
|
|
|
46
|
-
function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate) {
|
|
42
|
+
function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate) {
|
|
47
43
|
var diagram = drakonToStruct(drakonJson, name, filename, translate)
|
|
48
44
|
var lines = []
|
|
45
|
+
|
|
46
|
+
lines.push("## " + translate("Procedure") + " \"" + diagram.name + "\"")
|
|
49
47
|
if (diagram.params) {
|
|
50
48
|
addRange(lines, htmlToString(diagram.params))
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
lines.push(translate("Procedure") + " \"" + diagram.name + "\"")
|
|
49
|
+
}
|
|
55
50
|
lines.push("")
|
|
56
51
|
lines.push(translate("Algorithm") + ":")
|
|
57
52
|
|
|
@@ -70,6 +65,7 @@ function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate)
|
|
|
70
65
|
lines.push(translate("End of subroutine"))
|
|
71
66
|
})
|
|
72
67
|
}
|
|
68
|
+
lines.push("")
|
|
73
69
|
lines.push(translate("End of procedure"))
|
|
74
70
|
if (diagram.description) {
|
|
75
71
|
lines.push("")
|
|
@@ -82,10 +78,83 @@ function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate)
|
|
|
82
78
|
return {text:text,json:str}
|
|
83
79
|
}
|
|
84
80
|
|
|
85
|
-
|
|
81
|
+
|
|
82
|
+
function mindToTree(drakonJson, name, filename, htmlToString) {
|
|
83
|
+
let drakonGraph;
|
|
84
|
+
try {
|
|
85
|
+
drakonJson = drakonJson || ""
|
|
86
|
+
drakonJson = drakonJson.trim()
|
|
87
|
+
drakonJson = drakonJson || "{}"
|
|
88
|
+
drakonGraph = JSON.parse(drakonJson);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
var message = translate("Error parsing JSON") + ": " + error.message
|
|
91
|
+
throw createError(message, filename)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const nodes = drakonGraph.items || {};
|
|
95
|
+
var root = createMindNode("## " + name)
|
|
96
|
+
nodes["root"] = root
|
|
97
|
+
connectMindNodesToParent(nodes)
|
|
98
|
+
sortMindChildren(nodes)
|
|
99
|
+
var lines = []
|
|
100
|
+
printMindNode(root, 0, lines, htmlToString, true)
|
|
101
|
+
lines.push("")
|
|
102
|
+
var text = lines.join("\n")
|
|
103
|
+
return {text:text}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function connectMindNodesToParent(nodes) {
|
|
107
|
+
for (var id in nodes) {
|
|
108
|
+
var node = nodes[id]
|
|
109
|
+
if (node.parent) {
|
|
110
|
+
var parent = nodes[node.parent]
|
|
111
|
+
if (!parent.children) {
|
|
112
|
+
parent.children = []
|
|
113
|
+
}
|
|
114
|
+
parent.children.push(node)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function sortMindChildren(nodes) {
|
|
120
|
+
for (var id in nodes) {
|
|
121
|
+
var node = nodes[id]
|
|
122
|
+
if (node.children) {
|
|
123
|
+
sortByProperty(node.children, "ordinal")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function printMindNode(node, depth, lines, htmlToString, first) {
|
|
129
|
+
var printed = htmlToString(node.content)
|
|
130
|
+
const indent = makeIndent(depth)
|
|
131
|
+
printWithIndent(printed, indent, lines)
|
|
132
|
+
var childDepth = depth + 1
|
|
133
|
+
if (first) {
|
|
134
|
+
lines.push("")
|
|
135
|
+
childDepth = 0
|
|
136
|
+
}
|
|
137
|
+
if (node.children) {
|
|
138
|
+
for (var child of node.children) {
|
|
139
|
+
printMindNode(child, childDepth, lines, htmlToString, false)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function createMindNode(name) {
|
|
145
|
+
return {
|
|
146
|
+
"type": "idea",
|
|
147
|
+
"content": "<p>" + name + "</p>",
|
|
148
|
+
"parent": undefined,
|
|
149
|
+
"treeType": "treeview",
|
|
150
|
+
"ordinal": 0
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = { drakonToPseudocode, mindToTree };
|
|
86
155
|
},{"./drakonToStruct":3,"./printPseudo":5,"./tools":8}],3:[function(require,module,exports){
|
|
87
156
|
const { structFlow, redirectNode } = require("./structFlow");
|
|
88
|
-
const { createError } = require("./tools");
|
|
157
|
+
const { createError, remove } = require("./tools");
|
|
89
158
|
|
|
90
159
|
var translate
|
|
91
160
|
|
|
@@ -122,9 +191,7 @@ function drakonToStruct(drakonJson, name, filename, translateFunction) {
|
|
|
122
191
|
branches.forEach(branch => checkBranchIsReferenced(branch, firstNodeId, filename))
|
|
123
192
|
rewireShortcircuit(nodes, filename)
|
|
124
193
|
branches.forEach(branch => cutOffBranch(nodes, branch))
|
|
125
|
-
|
|
126
194
|
var branchTrees = structFlow(nodes, branches, filename, translate)
|
|
127
|
-
|
|
128
195
|
return {
|
|
129
196
|
name: name,
|
|
130
197
|
params: drakonGraph.params || "",
|
|
@@ -237,8 +304,11 @@ function addFakeEnd(nodes, prev, node, end, addresses) {
|
|
|
237
304
|
nodes[address.id] = address
|
|
238
305
|
end.prev.push(address.id)
|
|
239
306
|
addresses.push(address)
|
|
307
|
+
node.prev.push(address.id)
|
|
240
308
|
}
|
|
241
309
|
redirectNode(nodes, prev, node.id, address.id)
|
|
310
|
+
address.prev.push(prev.id)
|
|
311
|
+
node.prev = remove(node.prev, prev.id)
|
|
242
312
|
}
|
|
243
313
|
|
|
244
314
|
function buildTwoWayConnections(nodes, firstNodeId) {
|
|
@@ -501,7 +571,7 @@ function markLoopBody(nodes, start, filename) {
|
|
|
501
571
|
|
|
502
572
|
module.exports = { drakonToStruct, drakonToGraph };
|
|
503
573
|
},{"./structFlow":6,"./tools":8}],4:[function(require,module,exports){
|
|
504
|
-
const { drakonToPseudocode } = require('./drakonToPromptStruct');
|
|
574
|
+
const { drakonToPseudocode, mindToTree } = require('./drakonToPromptStruct');
|
|
505
575
|
const { htmlToString } = require("./browserTools")
|
|
506
576
|
const { setUpLanguage, translate } = require("./translate")
|
|
507
577
|
const { drakonToStruct } = require("./drakonToStruct");
|
|
@@ -513,6 +583,12 @@ window.drakongen = {
|
|
|
513
583
|
return drakonToPseudocode(drakonJson, name, filename, htmlToString, translate).text
|
|
514
584
|
},
|
|
515
585
|
|
|
586
|
+
toMindTree: function (mindJson, name, filename, language) {
|
|
587
|
+
setUpLanguage(language)
|
|
588
|
+
var result = mindToTree(mindJson, name, filename, htmlToString)
|
|
589
|
+
return result.text
|
|
590
|
+
},
|
|
591
|
+
|
|
516
592
|
toTree: function (drakonJson, name, filename, language) {
|
|
517
593
|
setUpLanguage(language)
|
|
518
594
|
var result = drakonToStruct(drakonJson, name, filename, translate)
|
|
@@ -522,19 +598,20 @@ window.drakongen = {
|
|
|
522
598
|
},{"./browserTools":1,"./drakonToPromptStruct":2,"./drakonToStruct":3,"./translate":9}],5:[function(require,module,exports){
|
|
523
599
|
var {addRange} = require("./tools")
|
|
524
600
|
|
|
525
|
-
function
|
|
526
|
-
|
|
601
|
+
function makeIndent(depth) {
|
|
602
|
+
return " ".repeat(depth * 4);
|
|
603
|
+
}
|
|
527
604
|
|
|
605
|
+
function printWithIndent(lines, indent, output) {
|
|
606
|
+
lines.forEach(line => output.push(indent + line))
|
|
607
|
+
}
|
|
528
608
|
|
|
609
|
+
function printPseudo(algorithm, translate, output, htmlToString) {
|
|
529
610
|
function printStructuredContent(content, indent, output) {
|
|
530
611
|
var lines = printStructuredContentNoIdent(content)
|
|
531
612
|
printWithIndent(lines, indent, output)
|
|
532
613
|
}
|
|
533
614
|
|
|
534
|
-
function printWithIndent(lines, indent, output) {
|
|
535
|
-
lines.forEach(line => output.push(indent + line))
|
|
536
|
-
}
|
|
537
|
-
|
|
538
615
|
function printStructuredContentNoIdent(content) {
|
|
539
616
|
var lines = []
|
|
540
617
|
|
|
@@ -581,14 +658,10 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
581
658
|
return lines
|
|
582
659
|
}
|
|
583
660
|
|
|
584
|
-
function makeIndent(depth) {
|
|
585
|
-
return " ".repeat(depth * 4);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
661
|
function printSteps(steps, depth, output) {
|
|
589
662
|
const indent = makeIndent(depth)
|
|
590
663
|
for (var step of steps) {
|
|
591
|
-
if (step.type === "end" || step.type === "branch"
|
|
664
|
+
if (step.type === "end" || step.type === "branch") { continue }
|
|
592
665
|
if (step.type === "question") {
|
|
593
666
|
printQuestion(step, depth, output)
|
|
594
667
|
} else if (step.type === "loop") {
|
|
@@ -612,8 +685,7 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
612
685
|
}
|
|
613
686
|
if (step.content) {
|
|
614
687
|
printStructuredContent(step.content, indent, output)
|
|
615
|
-
}
|
|
616
|
-
output.push("")
|
|
688
|
+
}
|
|
617
689
|
}
|
|
618
690
|
|
|
619
691
|
function printAddress(step, indent, output) {
|
|
@@ -628,11 +700,12 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
628
700
|
|
|
629
701
|
function printError(step, indent, output) {
|
|
630
702
|
output.push(indent + translate("error") + ":")
|
|
631
|
-
|
|
703
|
+
var ind2 = indent + makeIndent(1)
|
|
704
|
+
output.push(ind2 + step.message)
|
|
632
705
|
if (step.content) {
|
|
633
|
-
|
|
706
|
+
var ind3 = indent + makeIndent(2)
|
|
707
|
+
printStructuredContent(step.content, ind3, output)
|
|
634
708
|
}
|
|
635
|
-
output.push("")
|
|
636
709
|
}
|
|
637
710
|
|
|
638
711
|
function empty(array) {
|
|
@@ -679,7 +752,7 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
679
752
|
printSteps(algorithm.body, 0, output)
|
|
680
753
|
}
|
|
681
754
|
|
|
682
|
-
module.exports = {printPseudo}
|
|
755
|
+
module.exports = {printPseudo, printWithIndent, makeIndent}
|
|
683
756
|
},{"./tools":8}],6:[function(require,module,exports){
|
|
684
757
|
var {buildTree} = require("./technicalTree")
|
|
685
758
|
const { createError, sortByProperty } = require("./tools");
|
|
@@ -1160,6 +1233,10 @@ function createError(message, filename, nodeId) {
|
|
|
1160
1233
|
return error
|
|
1161
1234
|
}
|
|
1162
1235
|
|
|
1236
|
+
function remove(array, element) {
|
|
1237
|
+
return array.filter(item => item != element)
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1163
1240
|
function sortByProperty(array, property, order = "asc") {
|
|
1164
1241
|
if (!Array.isArray(array)) {
|
|
1165
1242
|
throw new Error("First argument must be an array");
|
|
@@ -1187,7 +1264,7 @@ function addRange(to, from) {
|
|
|
1187
1264
|
to.push(item)
|
|
1188
1265
|
}
|
|
1189
1266
|
}
|
|
1190
|
-
module.exports = { createError, sortByProperty, addRange }
|
|
1267
|
+
module.exports = { createError, sortByProperty, addRange, remove }
|
|
1191
1268
|
},{}],9:[function(require,module,exports){
|
|
1192
1269
|
var translationsRu = {
|
|
1193
1270
|
"error": "ОШИБКА",
|
|
@@ -1303,8 +1380,8 @@ function optimizeTree(steps) {
|
|
|
1303
1380
|
var result = []
|
|
1304
1381
|
|
|
1305
1382
|
for (var step of steps) {
|
|
1306
|
-
if (step.type === "end" || step.type === "branch" || step.type === "
|
|
1307
|
-
if (step.type === "action" && !step.content) { continue }
|
|
1383
|
+
if (step.type === "end" || step.type === "branch" || step.type === "loopend") { continue }
|
|
1384
|
+
if ((step.type === "action" || step.type === "comment") && !step.content) { continue }
|
|
1308
1385
|
var copy
|
|
1309
1386
|
if (step.type === "question") {
|
|
1310
1387
|
copy = optimizeQuestion(step)
|
package/browsertest.html
CHANGED
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
width: 100%;
|
|
21
21
|
}
|
|
22
22
|
</style>
|
|
23
|
-
|
|
24
23
|
<title>Drakongen browser test</title>
|
|
25
24
|
</head>
|
|
26
25
|
<body>
|
|
@@ -29,13 +28,14 @@
|
|
|
29
28
|
<textarea id="input" rows="30" autocorrect="false" placeholder="Enter drakon Json here" spellcheck="false"></textarea>
|
|
30
29
|
<div><select id="format">
|
|
31
30
|
<option value="pseudo">Pseudocode</option>
|
|
31
|
+
<option value="graf">Graf mind-map</option>
|
|
32
32
|
<option value="tree">Tree</option>
|
|
33
33
|
</select></div>
|
|
34
34
|
<div><select id="language">
|
|
35
35
|
<option value="en">English</option>
|
|
36
36
|
<option value="no">Norsk</option>
|
|
37
37
|
<option value="ru">Русский</option>
|
|
38
|
-
</select></div>
|
|
38
|
+
</select></div>
|
|
39
39
|
<button onclick="convert()">Convert to pseudocode</button>
|
|
40
40
|
<div></div>
|
|
41
41
|
<pre id="output"></pre>
|
|
@@ -67,6 +67,8 @@
|
|
|
67
67
|
var content
|
|
68
68
|
if (format.value === "pseudo") {
|
|
69
69
|
content = drakongen.toPseudocode(input.value, "Drakongen browser test", "Drakongen browser test.drakon", language.value)
|
|
70
|
+
} else if (format.value === "graf") {
|
|
71
|
+
content = drakongen.toMindTree(input.value, "Drakongen browser test", "Drakongen browser test.graf")
|
|
70
72
|
} else {
|
|
71
73
|
content = drakongen.toTree(input.value, "Drakongen browser test", "Drakongen browser test.drakon", language.value)
|
|
72
74
|
}
|
package/buildexamples.js
CHANGED
|
@@ -38,7 +38,7 @@ async function processDrakonFiles() {
|
|
|
38
38
|
const files = await fs.readdir(examplesFolder);
|
|
39
39
|
|
|
40
40
|
// Filter for .drakon files
|
|
41
|
-
const drakonFiles = files.filter(file => file.endsWith('.drakon'));
|
|
41
|
+
const drakonFiles = files.filter(file => file.endsWith('.drakon') || file.endsWith('.graf'));
|
|
42
42
|
|
|
43
43
|
// Process each .drakon file
|
|
44
44
|
for (const file of drakonFiles) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node src/main.js --project exampleproject/foo.proj --output exampleproject
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"items": {
|
|
3
|
+
"1": {
|
|
4
|
+
"type": "idea",
|
|
5
|
+
"content": "<p>x: number</p>",
|
|
6
|
+
"parent": "root",
|
|
7
|
+
"treeType": "treeview",
|
|
8
|
+
"ordinal": 0
|
|
9
|
+
},
|
|
10
|
+
"2": {
|
|
11
|
+
"type": "idea",
|
|
12
|
+
"content": "<p>y: number</p>",
|
|
13
|
+
"parent": "root",
|
|
14
|
+
"treeType": "treeview",
|
|
15
|
+
"ordinal": 1
|
|
16
|
+
},
|
|
17
|
+
"root": {
|
|
18
|
+
"treeType": "treeview",
|
|
19
|
+
"type": "header"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"type": "graf",
|
|
23
|
+
"id": "class Point.graf"
|
|
24
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"items": {
|
|
3
|
+
"1": {
|
|
4
|
+
"type": "end"
|
|
5
|
+
},
|
|
6
|
+
"2": {
|
|
7
|
+
"type": "branch",
|
|
8
|
+
"branchId": 0,
|
|
9
|
+
"one": "8"
|
|
10
|
+
},
|
|
11
|
+
"3": {
|
|
12
|
+
"type": "action",
|
|
13
|
+
"content": "<p>return sqrt(x * x + y * y)</p>",
|
|
14
|
+
"one": "1"
|
|
15
|
+
},
|
|
16
|
+
"4": {
|
|
17
|
+
"type": "question",
|
|
18
|
+
"content": "<p>x > 0</p>",
|
|
19
|
+
"one": "5",
|
|
20
|
+
"two": "6",
|
|
21
|
+
"flag1": 1
|
|
22
|
+
},
|
|
23
|
+
"5": {
|
|
24
|
+
"type": "question",
|
|
25
|
+
"content": "<p>y > 0</p>",
|
|
26
|
+
"one": "7",
|
|
27
|
+
"two": "6",
|
|
28
|
+
"flag1": 1
|
|
29
|
+
},
|
|
30
|
+
"6": {
|
|
31
|
+
"type": "action",
|
|
32
|
+
"content": "<p>return 0</p>",
|
|
33
|
+
"one": "1"
|
|
34
|
+
},
|
|
35
|
+
"7": {
|
|
36
|
+
"type": "question",
|
|
37
|
+
"content": "<p>x is approx. equal y</p>",
|
|
38
|
+
"one": "3",
|
|
39
|
+
"two": "6",
|
|
40
|
+
"flag1": 0
|
|
41
|
+
},
|
|
42
|
+
"8": {
|
|
43
|
+
"type": "action",
|
|
44
|
+
"content": "<p>x = point.x</p><p>y = point.y</p>",
|
|
45
|
+
"one": "4"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"type": "drakon",
|
|
49
|
+
"id": "foo.drakon",
|
|
50
|
+
"params": "<p>arguments:</p><ul><li>point: Point</li></ul><p><br /></p><p>returns: number</p>"
|
|
51
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Generate a JavaScript function "foo".
|
|
2
|
+
Do not use "new", "class", and "this" keywords.
|
|
3
|
+
Use "undefined" instead of "null".
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Procedure "approximately equal"
|
|
7
|
+
arguments:
|
|
8
|
+
- left: number
|
|
9
|
+
- right: number
|
|
10
|
+
returns: boolean
|
|
11
|
+
|
|
12
|
+
Algorithm:
|
|
13
|
+
threshold = 0.00001
|
|
14
|
+
delta = left - right
|
|
15
|
+
If Math.abs(delta) > threshold
|
|
16
|
+
return true
|
|
17
|
+
Else
|
|
18
|
+
return false
|
|
19
|
+
|
|
20
|
+
End of procedure
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## class Point
|
|
24
|
+
|
|
25
|
+
x: number
|
|
26
|
+
y: number
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Procedure "foo"
|
|
31
|
+
arguments:
|
|
32
|
+
- point: Point
|
|
33
|
+
|
|
34
|
+
returns: number
|
|
35
|
+
|
|
36
|
+
Algorithm:
|
|
37
|
+
x = point.x
|
|
38
|
+
y = point.y
|
|
39
|
+
If (x > 0 and y > 0) and not (x is approx. equal y)
|
|
40
|
+
return sqrt(x * x + y * y)
|
|
41
|
+
Else
|
|
42
|
+
return 0
|
|
43
|
+
|
|
44
|
+
End of procedure
|
|
45
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"items": {
|
|
3
|
+
"1": {
|
|
4
|
+
"type": "end"
|
|
5
|
+
},
|
|
6
|
+
"2": {
|
|
7
|
+
"type": "branch",
|
|
8
|
+
"branchId": 0,
|
|
9
|
+
"one": "5"
|
|
10
|
+
},
|
|
11
|
+
"3": {
|
|
12
|
+
"type": "action",
|
|
13
|
+
"content": "<p>delta = left - right</p>",
|
|
14
|
+
"one": "4"
|
|
15
|
+
},
|
|
16
|
+
"4": {
|
|
17
|
+
"type": "question",
|
|
18
|
+
"content": "<p>Math.abs(delta) > threshold</p>",
|
|
19
|
+
"one": "6",
|
|
20
|
+
"two": "7",
|
|
21
|
+
"flag1": 1
|
|
22
|
+
},
|
|
23
|
+
"5": {
|
|
24
|
+
"type": "action",
|
|
25
|
+
"content": "<p>threshold = 0.00001</p>",
|
|
26
|
+
"one": "3"
|
|
27
|
+
},
|
|
28
|
+
"6": {
|
|
29
|
+
"type": "action",
|
|
30
|
+
"content": "<p>return true</p>",
|
|
31
|
+
"one": "1"
|
|
32
|
+
},
|
|
33
|
+
"7": {
|
|
34
|
+
"type": "action",
|
|
35
|
+
"content": "<p>return false</p>",
|
|
36
|
+
"one": "1"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"params": "<p>arguments:</p><ul><li>left: number</li><li>right: number</li></ul><p>returns: boolean</p>",
|
|
40
|
+
"type": "drakon",
|
|
41
|
+
"id": "approximately equal.drakon"
|
|
42
|
+
}
|
package/examples/00.Empty.txt
CHANGED