drakongen 1.3.0 → 1.4.4
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 +122 -40
- 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 +2 -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 +13 -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 +27 -4
- package/examples/Silhouette test 1.txt +10 -4
- 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.drakon +1 -1
- package/examples/getToken.txt +8 -17
- package/examples/hello.txt +4 -0
- package/examples/sil2.txt +3 -7
- package/examples/tmp.txt +3 -5
- 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 +65 -0
- package/prompts/project/project.proj +5 -0
- package/prompts/project/project.txt +82 -0
- package/prompts/project/start.txt +4 -0
- package/src/browserTools.js +1 -5
- package/src/drakonToPromptStruct.js +82 -8
- package/src/drakongen.js +7 -1
- package/src/index.js +9 -3
- package/src/main.js +73 -11
- package/src/nodeTools.js +1 -5
- package/src/printPseudo.js +15 -17
- package/src/translate.js +6 -3
- 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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
function htmlToString(html) {
|
|
4
4
|
if (!html) return '';
|
|
5
5
|
if (!html.startsWith('<') || !html.endsWith('>')) {
|
|
6
|
-
return html.split("\n")
|
|
6
|
+
return html.split("\n")
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
const parser = new DOMParser();
|
|
@@ -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,18 @@ 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) {
|
|
48
|
+
lines.push(translate("Parameters") + ":")
|
|
50
49
|
addRange(lines, htmlToString(diagram.params))
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
lines.push(translate("Procedure") + " \"" + diagram.name + "\"")
|
|
50
|
+
}
|
|
55
51
|
lines.push("")
|
|
56
52
|
lines.push(translate("Algorithm") + ":")
|
|
57
53
|
|
|
@@ -70,6 +66,7 @@ function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate)
|
|
|
70
66
|
lines.push(translate("End of subroutine"))
|
|
71
67
|
})
|
|
72
68
|
}
|
|
69
|
+
lines.push("")
|
|
73
70
|
lines.push(translate("End of procedure"))
|
|
74
71
|
if (diagram.description) {
|
|
75
72
|
lines.push("")
|
|
@@ -82,10 +79,83 @@ function drakonToPseudocode(drakonJson, name, filename, htmlToString, translate)
|
|
|
82
79
|
return {text:text,json:str}
|
|
83
80
|
}
|
|
84
81
|
|
|
85
|
-
|
|
82
|
+
|
|
83
|
+
function mindToTree(drakonJson, name, filename, htmlToString) {
|
|
84
|
+
let drakonGraph;
|
|
85
|
+
try {
|
|
86
|
+
drakonJson = drakonJson || ""
|
|
87
|
+
drakonJson = drakonJson.trim()
|
|
88
|
+
drakonJson = drakonJson || "{}"
|
|
89
|
+
drakonGraph = JSON.parse(drakonJson);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
var message = translate("Error parsing JSON") + ": " + error.message
|
|
92
|
+
throw createError(message, filename)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const nodes = drakonGraph.items || {};
|
|
96
|
+
var root = createMindNode("## " + name)
|
|
97
|
+
nodes["root"] = root
|
|
98
|
+
connectMindNodesToParent(nodes)
|
|
99
|
+
sortMindChildren(nodes)
|
|
100
|
+
var lines = []
|
|
101
|
+
printMindNode(root, 0, lines, htmlToString, true)
|
|
102
|
+
lines.push("")
|
|
103
|
+
var text = lines.join("\n")
|
|
104
|
+
return {text:text}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function connectMindNodesToParent(nodes) {
|
|
108
|
+
for (var id in nodes) {
|
|
109
|
+
var node = nodes[id]
|
|
110
|
+
if (node.parent) {
|
|
111
|
+
var parent = nodes[node.parent]
|
|
112
|
+
if (!parent.children) {
|
|
113
|
+
parent.children = []
|
|
114
|
+
}
|
|
115
|
+
parent.children.push(node)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function sortMindChildren(nodes) {
|
|
121
|
+
for (var id in nodes) {
|
|
122
|
+
var node = nodes[id]
|
|
123
|
+
if (node.children) {
|
|
124
|
+
sortByProperty(node.children, "ordinal")
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function printMindNode(node, depth, lines, htmlToString, first) {
|
|
130
|
+
var printed = htmlToString(node.content)
|
|
131
|
+
const indent = makeIndent(depth)
|
|
132
|
+
printWithIndent(printed, indent, lines)
|
|
133
|
+
var childDepth = depth + 1
|
|
134
|
+
if (first) {
|
|
135
|
+
lines.push("")
|
|
136
|
+
childDepth = 0
|
|
137
|
+
}
|
|
138
|
+
if (node.children) {
|
|
139
|
+
for (var child of node.children) {
|
|
140
|
+
printMindNode(child, childDepth, lines, htmlToString, false)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function createMindNode(name) {
|
|
146
|
+
return {
|
|
147
|
+
"type": "idea",
|
|
148
|
+
"content": "<p>" + name + "</p>",
|
|
149
|
+
"parent": undefined,
|
|
150
|
+
"treeType": "treeview",
|
|
151
|
+
"ordinal": 0
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = { drakonToPseudocode, mindToTree };
|
|
86
156
|
},{"./drakonToStruct":3,"./printPseudo":5,"./tools":8}],3:[function(require,module,exports){
|
|
87
157
|
const { structFlow, redirectNode } = require("./structFlow");
|
|
88
|
-
const { createError } = require("./tools");
|
|
158
|
+
const { createError, remove } = require("./tools");
|
|
89
159
|
|
|
90
160
|
var translate
|
|
91
161
|
|
|
@@ -122,9 +192,7 @@ function drakonToStruct(drakonJson, name, filename, translateFunction) {
|
|
|
122
192
|
branches.forEach(branch => checkBranchIsReferenced(branch, firstNodeId, filename))
|
|
123
193
|
rewireShortcircuit(nodes, filename)
|
|
124
194
|
branches.forEach(branch => cutOffBranch(nodes, branch))
|
|
125
|
-
|
|
126
195
|
var branchTrees = structFlow(nodes, branches, filename, translate)
|
|
127
|
-
|
|
128
196
|
return {
|
|
129
197
|
name: name,
|
|
130
198
|
params: drakonGraph.params || "",
|
|
@@ -237,8 +305,11 @@ function addFakeEnd(nodes, prev, node, end, addresses) {
|
|
|
237
305
|
nodes[address.id] = address
|
|
238
306
|
end.prev.push(address.id)
|
|
239
307
|
addresses.push(address)
|
|
308
|
+
node.prev.push(address.id)
|
|
240
309
|
}
|
|
241
310
|
redirectNode(nodes, prev, node.id, address.id)
|
|
311
|
+
address.prev.push(prev.id)
|
|
312
|
+
node.prev = remove(node.prev, prev.id)
|
|
242
313
|
}
|
|
243
314
|
|
|
244
315
|
function buildTwoWayConnections(nodes, firstNodeId) {
|
|
@@ -501,7 +572,7 @@ function markLoopBody(nodes, start, filename) {
|
|
|
501
572
|
|
|
502
573
|
module.exports = { drakonToStruct, drakonToGraph };
|
|
503
574
|
},{"./structFlow":6,"./tools":8}],4:[function(require,module,exports){
|
|
504
|
-
const { drakonToPseudocode } = require('./drakonToPromptStruct');
|
|
575
|
+
const { drakonToPseudocode, mindToTree } = require('./drakonToPromptStruct');
|
|
505
576
|
const { htmlToString } = require("./browserTools")
|
|
506
577
|
const { setUpLanguage, translate } = require("./translate")
|
|
507
578
|
const { drakonToStruct } = require("./drakonToStruct");
|
|
@@ -513,6 +584,12 @@ window.drakongen = {
|
|
|
513
584
|
return drakonToPseudocode(drakonJson, name, filename, htmlToString, translate).text
|
|
514
585
|
},
|
|
515
586
|
|
|
587
|
+
toMindTree: function (mindJson, name, filename, language) {
|
|
588
|
+
setUpLanguage(language)
|
|
589
|
+
var result = mindToTree(mindJson, name, filename, htmlToString)
|
|
590
|
+
return result.text
|
|
591
|
+
},
|
|
592
|
+
|
|
516
593
|
toTree: function (drakonJson, name, filename, language) {
|
|
517
594
|
setUpLanguage(language)
|
|
518
595
|
var result = drakonToStruct(drakonJson, name, filename, translate)
|
|
@@ -522,19 +599,21 @@ window.drakongen = {
|
|
|
522
599
|
},{"./browserTools":1,"./drakonToPromptStruct":2,"./drakonToStruct":3,"./translate":9}],5:[function(require,module,exports){
|
|
523
600
|
var {addRange} = require("./tools")
|
|
524
601
|
|
|
525
|
-
function
|
|
526
|
-
|
|
602
|
+
function makeIndent(depth) {
|
|
603
|
+
return " ".repeat(depth * 4);
|
|
604
|
+
}
|
|
527
605
|
|
|
606
|
+
function printWithIndent(lines, indent, output) {
|
|
607
|
+
if (!lines) {return}
|
|
608
|
+
lines.forEach(line => output.push(indent + line))
|
|
609
|
+
}
|
|
528
610
|
|
|
611
|
+
function printPseudo(algorithm, translate, output, htmlToString) {
|
|
529
612
|
function printStructuredContent(content, indent, output) {
|
|
530
613
|
var lines = printStructuredContentNoIdent(content)
|
|
531
614
|
printWithIndent(lines, indent, output)
|
|
532
615
|
}
|
|
533
616
|
|
|
534
|
-
function printWithIndent(lines, indent, output) {
|
|
535
|
-
lines.forEach(line => output.push(indent + line))
|
|
536
|
-
}
|
|
537
|
-
|
|
538
617
|
function printStructuredContentNoIdent(content) {
|
|
539
618
|
var lines = []
|
|
540
619
|
|
|
@@ -581,14 +660,10 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
581
660
|
return lines
|
|
582
661
|
}
|
|
583
662
|
|
|
584
|
-
function makeIndent(depth) {
|
|
585
|
-
return " ".repeat(depth * 4);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
663
|
function printSteps(steps, depth, output) {
|
|
589
664
|
const indent = makeIndent(depth)
|
|
590
665
|
for (var step of steps) {
|
|
591
|
-
if (step.type === "end" || step.type === "branch"
|
|
666
|
+
if (step.type === "end" || step.type === "branch") { continue }
|
|
592
667
|
if (step.type === "question") {
|
|
593
668
|
printQuestion(step, depth, output)
|
|
594
669
|
} else if (step.type === "loop") {
|
|
@@ -612,8 +687,7 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
612
687
|
}
|
|
613
688
|
if (step.content) {
|
|
614
689
|
printStructuredContent(step.content, indent, output)
|
|
615
|
-
}
|
|
616
|
-
output.push("")
|
|
690
|
+
}
|
|
617
691
|
}
|
|
618
692
|
|
|
619
693
|
function printAddress(step, indent, output) {
|
|
@@ -628,11 +702,12 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
628
702
|
|
|
629
703
|
function printError(step, indent, output) {
|
|
630
704
|
output.push(indent + translate("error") + ":")
|
|
631
|
-
|
|
705
|
+
var ind2 = indent + makeIndent(1)
|
|
706
|
+
output.push(ind2 + step.message)
|
|
632
707
|
if (step.content) {
|
|
633
|
-
|
|
708
|
+
var ind3 = indent + makeIndent(2)
|
|
709
|
+
printStructuredContent(step.content, ind3, output)
|
|
634
710
|
}
|
|
635
|
-
output.push("")
|
|
636
711
|
}
|
|
637
712
|
|
|
638
713
|
function empty(array) {
|
|
@@ -679,7 +754,7 @@ function printPseudo(algorithm, translate, output, htmlToString) {
|
|
|
679
754
|
printSteps(algorithm.body, 0, output)
|
|
680
755
|
}
|
|
681
756
|
|
|
682
|
-
module.exports = {printPseudo}
|
|
757
|
+
module.exports = {printPseudo, printWithIndent, makeIndent}
|
|
683
758
|
},{"./tools":8}],6:[function(require,module,exports){
|
|
684
759
|
var {buildTree} = require("./technicalTree")
|
|
685
760
|
const { createError, sortByProperty } = require("./tools");
|
|
@@ -1160,6 +1235,10 @@ function createError(message, filename, nodeId) {
|
|
|
1160
1235
|
return error
|
|
1161
1236
|
}
|
|
1162
1237
|
|
|
1238
|
+
function remove(array, element) {
|
|
1239
|
+
return array.filter(item => item != element)
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1163
1242
|
function sortByProperty(array, property, order = "asc") {
|
|
1164
1243
|
if (!Array.isArray(array)) {
|
|
1165
1244
|
throw new Error("First argument must be an array");
|
|
@@ -1187,7 +1266,7 @@ function addRange(to, from) {
|
|
|
1187
1266
|
to.push(item)
|
|
1188
1267
|
}
|
|
1189
1268
|
}
|
|
1190
|
-
module.exports = { createError, sortByProperty, addRange }
|
|
1269
|
+
module.exports = { createError, sortByProperty, addRange, remove }
|
|
1191
1270
|
},{}],9:[function(require,module,exports){
|
|
1192
1271
|
var translationsRu = {
|
|
1193
1272
|
"error": "ОШИБКА",
|
|
@@ -1215,7 +1294,8 @@ var translationsRu = {
|
|
|
1215
1294
|
"End of subroutine": "Конец подпрограммы",
|
|
1216
1295
|
"Description": "Описание",
|
|
1217
1296
|
"Algorithm": "Алгоритм",
|
|
1218
|
-
Remarks: "Замечания"
|
|
1297
|
+
Remarks: "Замечания",
|
|
1298
|
+
Parameters: "Параметры"
|
|
1219
1299
|
}
|
|
1220
1300
|
|
|
1221
1301
|
var translationsEn = {
|
|
@@ -1244,7 +1324,8 @@ var translationsEn = {
|
|
|
1244
1324
|
'End of subroutine': 'End of subroutine',
|
|
1245
1325
|
Description: 'Description',
|
|
1246
1326
|
Algorithm: 'Algorithm',
|
|
1247
|
-
Remarks: "Remarks"
|
|
1327
|
+
Remarks: "Remarks",
|
|
1328
|
+
Parameters: "Parameters"
|
|
1248
1329
|
}
|
|
1249
1330
|
|
|
1250
1331
|
var translationsNo = {
|
|
@@ -1273,7 +1354,8 @@ var translationsNo = {
|
|
|
1273
1354
|
'End of subroutine': 'Slutt på delprosedyre',
|
|
1274
1355
|
Description: 'Beskrivelse',
|
|
1275
1356
|
Algorithm: 'Algoritme',
|
|
1276
|
-
Remarks: "Bemerkninger"
|
|
1357
|
+
Remarks: "Bemerkninger",
|
|
1358
|
+
Parameters: "Parametere"
|
|
1277
1359
|
};
|
|
1278
1360
|
|
|
1279
1361
|
|
|
@@ -1303,8 +1385,8 @@ function optimizeTree(steps) {
|
|
|
1303
1385
|
var result = []
|
|
1304
1386
|
|
|
1305
1387
|
for (var step of steps) {
|
|
1306
|
-
if (step.type === "end" || step.type === "branch" || step.type === "
|
|
1307
|
-
if (step.type === "action" && !step.content) { continue }
|
|
1388
|
+
if (step.type === "end" || step.type === "branch" || step.type === "loopend") { continue }
|
|
1389
|
+
if ((step.type === "action" || step.type === "comment") && !step.content) { continue }
|
|
1308
1390
|
var copy
|
|
1309
1391
|
if (step.type === "question") {
|
|
1310
1392
|
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
|
+
"params": "<ul><li>point: Point</li></ul><p><br /></p><p>returns: number</p>",
|
|
49
|
+
"type": "drakon",
|
|
50
|
+
"id": "foo.drakon"
|
|
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
|
+
Parameters:
|
|
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
|
+
Parameters:
|
|
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
|
+
|