@yuneta/gobj-ui 7.26.27 → 7.26.28

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.
Files changed (44) hide show
  1. package/README.md +458 -22
  2. package/dist/gobj-ui.cjs.js +1063 -216
  3. package/dist/gobj-ui.es.js +1064 -217
  4. package/package.json +1 -1
  5. package/scripts/validate-locales.mjs +2269 -316
  6. package/src/c_g6_nodes_tree.js +1086 -253
  7. package/src/c_yui_form.js +11 -1
  8. package/src/c_yui_fsm_graph.js +5 -0
  9. package/src/c_yui_gclass.js +11 -0
  10. package/src/c_yui_gobj_tree_js.js +17 -0
  11. package/src/c_yui_json_graph.js +5 -0
  12. package/src/c_yui_nav.js +9 -6
  13. package/src/c_yui_pager.js +1 -1
  14. package/src/c_yui_period.js +11 -4
  15. package/src/c_yui_schema_editor.js +19 -7
  16. package/src/c_yui_shell.js +7 -7
  17. package/src/c_yui_treedb_graph.js +15 -6
  18. package/src/c_yui_treedb_schema.js +5 -0
  19. package/src/c_yui_treedb_topic_with_form.js +10 -10
  20. package/src/c_yui_treedb_topics.js +6 -6
  21. package/src/c_yui_window.js +2 -2
  22. package/src/c_yui_wizard.js +8 -1
  23. package/src/form_json_field.js +7 -0
  24. package/src/g6_canvas_tab_order.js +84 -0
  25. package/src/g6_canvas_tab_order.wiring.test.js +232 -0
  26. package/src/g6_nodes_tree_controls.test.js +547 -0
  27. package/src/g6_nodes_tree_focus.wiring.test.js +1360 -0
  28. package/src/g6_nodes_tree_i18n_keys.test.js +241 -5
  29. package/src/i18n_key_functions.js +146 -0
  30. package/src/i18n_key_functions.test.js +1204 -0
  31. package/src/lib_graph.js +38 -1
  32. package/src/nav_backbar_name.wiring.test.js +82 -0
  33. package/src/schema_flags.js +47 -0
  34. package/src/schema_import.js +7 -0
  35. package/src/shell_modals.js +20 -16
  36. package/src/shell_route_map.js +12 -2
  37. package/src/wizard_helpers.js +8 -0
  38. package/src/yui_dev.js +16 -3
  39. package/src/yui_dev_controls.test.js +174 -0
  40. package/src/yui_gclass_view.js +2 -2
  41. package/src/yui_graph_camera.js +1 -1
  42. package/src/yui_install.js +10 -8
  43. package/src/yui_table_select.js +2 -2
  44. package/src/yui_time.js +18 -3
@@ -1,10 +1,20 @@
1
1
  /***********************************************************************
2
2
  * g6_nodes_tree_i18n_keys.test.js
3
3
  *
4
- * The shape tables of c_g6_nodes_tree.js reach t() as DATA, so the
5
- * view publishes their keys in G6_NODES_TREE_I18N_KEYS, which a
6
- * consumer's validate-locales asks the locales for. A shape added to
7
- * a table and not to the list would render raw in every language.
4
+ * The keys of c_g6_nodes_tree.js that reach t() as DATA or as an
5
+ * ARGUMENT -- the shape tables, the labels and buttons of the
6
+ * popovers, the names of the floating buttons, the shell's error
7
+ * messages -- are invisible to a consumer's validate-locales, which
8
+ * only sees `t('<literal>')` and the `data-i18n*` / `i18n:` forms.
9
+ * So the view publishes them in G6_NODES_TREE_I18N_KEYS, and a key
10
+ * missing from that list renders raw in every language with the
11
+ * validator green (REV-CLOUD V20.5.1: "some records were gone
12
+ * before the delete").
13
+ *
14
+ * The module is read as a syntax tree, so every CALL is checked,
15
+ * not only the tables: a key handed to one of those helpers and
16
+ * not published fails here, and so does a new helper that hands
17
+ * t() a variable this test does not know the source of.
8
18
  *
9
19
  * Copyright (c) 2026, ArtGins.
10
20
  * All Rights Reserved.
@@ -13,8 +23,10 @@ import {describe, test, expect} from "vitest";
13
23
  import {readFileSync} from "node:fs";
14
24
  import {dirname, join} from "node:path";
15
25
  import {fileURLToPath} from "node:url";
26
+ import {parse} from "acorn";
16
27
 
17
28
  const SRC = readFileSync(join(dirname(fileURLToPath(import.meta.url)), "c_g6_nodes_tree.js"), "utf8");
29
+ const AST = parse(SRC, {ecmaVersion: "latest", sourceType: "module"});
18
30
 
19
31
  function array_of(name)
20
32
  {
@@ -23,7 +35,130 @@ function array_of(name)
23
35
  return [...m[1].matchAll(/'([^']+)'/g)].map((x) => x[1]);
24
36
  }
25
37
 
26
- describe("c_g6_nodes_tree publishes the keys of its shape tables", () => {
38
+ /* The helpers that hand t() a key they were given, and which argument
39
+ * carries it. A call passes a literal (it must be published) or the
40
+ * parameter of another of these (it passes the key through). */
41
+ const KEY_ARGS = {
42
+ create_form_label: [1],
43
+ create_floating_icon: [4],
44
+ show_dual_icons: [3, 5],
45
+ show_confirm_popover: [3],
46
+ yui_shell_show_error: [1],
47
+ };
48
+
49
+ /* The functions that call t() with something other than a literal,
50
+ * each with the place its keys come from:
51
+ * create_form_label, create_floating_icon: an argument (KEY_ARGS);
52
+ * name_form_control: the `data-i18n` create_form_label wrote;
53
+ * create_form_select, create_form_button_row: an `i18n:` property. */
54
+ const VARIABLE_T_CALLERS = [
55
+ "create_floating_icon",
56
+ "create_form_button_row",
57
+ "create_form_label",
58
+ "create_form_select",
59
+ "name_form_control",
60
+ ];
61
+
62
+ /* The tables whose items reach `i18n:` through a `.map()`: the first
63
+ * test of this file checks that their keys are published. */
64
+ const KEY_TABLES = ["NODE_SHAPES", "PORT_SHAPES"];
65
+
66
+ /* Every node of the tree, with the stack of the nodes above it. */
67
+ function each_node(node, visit, stack = [])
68
+ {
69
+ visit(node, stack);
70
+ stack.push(node);
71
+ for(const k of Object.keys(node)) {
72
+ const v = node[k];
73
+ if(Array.isArray(v)) {
74
+ for(const c of v) {
75
+ if(c && typeof c.type === "string") {
76
+ each_node(c, visit, stack);
77
+ }
78
+ }
79
+ } else if(v && typeof v.type === "string") {
80
+ each_node(v, visit, stack);
81
+ }
82
+ }
83
+ stack.pop();
84
+ }
85
+
86
+ function is_string_literal(n)
87
+ {
88
+ if(!n) {
89
+ return false;
90
+ }
91
+ if(n.type === "Literal" && typeof n.value === "string") {
92
+ return true;
93
+ }
94
+ return n.type === "TemplateLiteral" && n.expressions.length === 0;
95
+ }
96
+
97
+ function literal_value(n)
98
+ {
99
+ if(n.type === "Literal") {
100
+ return n.value;
101
+ }
102
+ return n.quasis[0].value.cooked;
103
+ }
104
+
105
+ function is_function(n)
106
+ {
107
+ return n.type === "FunctionDeclaration" || n.type === "FunctionExpression" ||
108
+ n.type === "ArrowFunctionExpression";
109
+ }
110
+
111
+ function has_param(fn, name)
112
+ {
113
+ return fn.params.some((p) => p.type === "Identifier" && p.name === name);
114
+ }
115
+
116
+ /* The innermost function above, that declares `name` as a parameter. */
117
+ function function_with_param(stack, name)
118
+ {
119
+ for(let i = stack.length - 1; i >= 0; i--) {
120
+ if(is_function(stack[i]) && has_param(stack[i], name)) {
121
+ return {fn: stack[i], parent: stack[i - 1]};
122
+ }
123
+ }
124
+ return null;
125
+ }
126
+
127
+ function enclosing_declaration(stack)
128
+ {
129
+ for(let i = stack.length - 1; i >= 0; i--) {
130
+ if(stack[i].type === "FunctionDeclaration") {
131
+ return stack[i].id.name;
132
+ }
133
+ }
134
+ return "<module>";
135
+ }
136
+
137
+ function line_of(n)
138
+ {
139
+ return SRC.slice(0, n.start).split("\n").length;
140
+ }
141
+
142
+ /* A key handed on by name is the parameter of one of the KEY_ARGS
143
+ * helpers (passed through), or the item of a KEY_TABLES `.map()`. */
144
+ function variable_key_is_known(stack, name)
145
+ {
146
+ const found = function_with_param(stack, name);
147
+ if(!found) {
148
+ return false;
149
+ }
150
+ if(found.fn.type === "FunctionDeclaration" && KEY_ARGS[found.fn.id.name]) {
151
+ return true;
152
+ }
153
+ const call = found.parent;
154
+ return !!(call && call.type === "CallExpression" && call.arguments[0] === found.fn &&
155
+ call.callee.type === "MemberExpression" &&
156
+ call.callee.property.name === "map" &&
157
+ call.callee.object.type === "Identifier" &&
158
+ KEY_TABLES.includes(call.callee.object.name));
159
+ }
160
+
161
+ describe("c_g6_nodes_tree publishes the keys it hands to t() as data", () => {
27
162
  test("every node and port shape is in G6_NODES_TREE_I18N_KEYS", () => {
28
163
  const published = new Set(array_of("G6_NODES_TREE_I18N_KEYS"));
29
164
  for(const shape of [...array_of("NODE_SHAPES"), ...array_of("PORT_SHAPES")]) {
@@ -36,4 +171,105 @@ describe("c_g6_nodes_tree publishes the keys of its shape tables", () => {
36
171
  expect(SRC).toMatch(/o\.setAttribute\('data-i18n', opt\.i18n\)/);
37
172
  expect(SRC).not.toMatch(/label: t\('/);
38
173
  });
174
+
175
+ test("every function that hands t() a variable is one whose keys are checked here", () => {
176
+ const callers = new Set();
177
+ each_node(AST, (n, stack) => {
178
+ if(n.type === "CallExpression" && n.callee.type === "Identifier" &&
179
+ n.callee.name === "t" && !is_string_literal(n.arguments[0])) {
180
+ callers.add(enclosing_declaration(stack));
181
+ }
182
+ });
183
+ /* A new one fails here: teach KEY_ARGS (or the `i18n:` check
184
+ * below) where its keys come from, and publish them. */
185
+ expect([...callers].sort()).toEqual(VARIABLE_T_CALLERS);
186
+ });
187
+
188
+ test("every key handed to those helpers by argument is published", () => {
189
+ const published = new Set(array_of("G6_NODES_TREE_I18N_KEYS"));
190
+ const missing = [];
191
+ const unknowable = [];
192
+ let calls = 0;
193
+ each_node(AST, (n, stack) => {
194
+ if(n.type !== "CallExpression" || n.callee.type !== "Identifier" ||
195
+ !KEY_ARGS[n.callee.name]) {
196
+ return;
197
+ }
198
+ calls++;
199
+ for(const i of KEY_ARGS[n.callee.name]) {
200
+ const arg = n.arguments[i];
201
+ if(is_string_literal(arg)) {
202
+ if(!published.has(literal_value(arg))) {
203
+ missing.push(`${n.callee.name}('${literal_value(arg)}') :${line_of(n)}`);
204
+ }
205
+ } else if(!(arg && arg.type === "Identifier" &&
206
+ variable_key_is_known(stack, arg.name))) {
207
+ unknowable.push(`${n.callee.name} argument ${i} :${line_of(n)}`);
208
+ }
209
+ }
210
+ });
211
+ expect(calls).toBeGreaterThan(10);
212
+ expect(missing).toEqual([]);
213
+ expect(unknowable).toEqual([]);
214
+ });
215
+
216
+ test("an `i18n:` property is a literal, or a key the checks above reach", () => {
217
+ const unknowable = [];
218
+ each_node(AST, (n, stack) => {
219
+ if(n.type !== "Property" || n.shorthand || n.key.type !== "Identifier" ||
220
+ n.key.name !== "i18n" || stack[stack.length - 1].type !== "ObjectExpression") {
221
+ return;
222
+ }
223
+ if(is_string_literal(n.value)) {
224
+ return; /* validate-locales reads `i18n: '<key>'` */
225
+ }
226
+ if(!(n.value.type === "Identifier" && variable_key_is_known(stack, n.value.name))) {
227
+ unknowable.push(`i18n: ${SRC.slice(n.value.start, n.value.end)} :${line_of(n)}`);
228
+ }
229
+ });
230
+ expect(unknowable).toEqual([]);
231
+ });
232
+
233
+ test("a toolbar item's `title_key` is the key of its `title`", () => {
234
+ /* toolbar_item_html() writes `title` as the name and
235
+ * `title_key` as its data-i18n-title / -aria-label: two
236
+ * writings of one key, which must not drift apart. Every
237
+ * object with a `title: t('<key>')` is a toolbar item here. */
238
+ const prop = (obj, name) => obj.properties.find((p) => p.type === "Property" &&
239
+ !p.computed && p.key.type === "Identifier" && p.key.name === name);
240
+ const bad = [];
241
+ let items = 0;
242
+ each_node(AST, (n) => {
243
+ if(n.type !== "ObjectExpression") {
244
+ return;
245
+ }
246
+ const title = prop(n, "title");
247
+ const key = prop(n, "title_key");
248
+ if(!title && !key) {
249
+ return;
250
+ }
251
+ const is_t = title && title.value.type === "CallExpression" &&
252
+ title.value.callee.type === "Identifier" && title.value.callee.name === "t" &&
253
+ is_string_literal(title.value.arguments[0]);
254
+ if(!is_t) {
255
+ return; /* not a translated title: nothing to key */
256
+ }
257
+ items++;
258
+ const want = literal_value(title.value.arguments[0]);
259
+ if(!key || !is_string_literal(key.value) || literal_value(key.value) !== want) {
260
+ bad.push(`title: t('${want}') without title_key '${want}' :${line_of(n)}`);
261
+ }
262
+ });
263
+ expect(items).toBeGreaterThan(15);
264
+ expect(bad).toEqual([]);
265
+ });
266
+
267
+ test("the published list holds the keys REV-CLOUD V20.5.1 found missing", () => {
268
+ const published = new Set(array_of("G6_NODES_TREE_I18N_KEYS"));
269
+ for(const key of ["some records were gone before the delete",
270
+ "node properties", "delete node", "edge properties",
271
+ "unlink", "link to hook", "port properties"]) {
272
+ expect(published.has(key), key).toBe(true);
273
+ }
274
+ });
39
275
  });
@@ -0,0 +1,146 @@
1
+ /***********************************************************************
2
+ * i18n_key_functions.js
3
+ *
4
+ * The gobj-ui functions that RECEIVE an i18n key as an
5
+ * argument, and where it goes. Pure data: no import, no code.
6
+ *
7
+ * A key handed to a function -- `yui_shell_show_error(shell,
8
+ * "the connection dropped")`, `icon_button(gobj, "yi-copy",
9
+ * "EV_COPY_ALL", "copy json")` -- reaches t() inside the function,
10
+ * by a parameter, where no scan of `t("...")` can see it. Up to
11
+ * gobj-ui 7.26.27 such a key was invisible to validate-locales,
12
+ * and several shipped untranslated (REV-CLOUD V20.5.1). This table
13
+ * names every such function: validate-locales reads the string
14
+ * literals given at these positions as keys the source asks for,
15
+ * in the app's own source and in the gobj-ui modules it mounts.
16
+ *
17
+ * An entry:
18
+ *
19
+ * module the src/ module that defines the function
20
+ * name its name
21
+ * exported true: an app or another module imports it, and
22
+ * every call bound to that import is read;
23
+ * false: a helper of its own module, read there
24
+ * keys where the keys are, one string per position:
25
+ * "1" the second argument
26
+ * "2.title" property `title` of an object
27
+ * literal given as the third
28
+ * "1.actions[].label"
29
+ * `label` of each object literal
30
+ * of the array `actions`
31
+ * A position may also hold DOM or nothing: only
32
+ * a string there is a key.
33
+ *
34
+ * What is read at a position: a string literal, a template with
35
+ * no `${}`, every branch of a `?:`, `||`, `??` (the right one of
36
+ * `&&`), and what the reader follows -- a const to its value, a
37
+ * property of a const object, the element of a const array a
38
+ * `.map()` or a for...of walks. A `let`, a parameter or data is
39
+ * not read: its keys are published in an exported
40
+ * `<NAME>_I18N_KEYS` array, and the call is MARKED with a comment
41
+ * right before what it hands over, `i18n: <NAME>_I18N_KEYS` (the
42
+ * list) or `i18n: data` (no key a list can hold). A marked `let`
43
+ * is held to its marker: every literal it is given is read and
44
+ * must be in the list, and one given nothing but literals fails
45
+ * (write it as a const, which the reader follows).
46
+ *
47
+ * A test (i18n_key_functions.test.js) holds the library to it,
48
+ * per CALL: a key position given anything else than a literal, a
49
+ * const the reader follows, a key position of the enclosing
50
+ * table function handed on, or a marked value fails, with the
51
+ * file and the line. Publishing a list exempts no module.
52
+ *
53
+ * A function added to the library that hands one of its
54
+ * parameters to t(), to `i18n`, or to a `data-i18n*` attribute
55
+ * goes in this table.
56
+ *
57
+ * Copyright (c) 2026, ArtGins.
58
+ * All Rights Reserved.
59
+ ***********************************************************************/
60
+
61
+ export const I18N_KEY_FUNCTIONS = Object.freeze([
62
+ /*
63
+ * Exported: an app calls them
64
+ */
65
+ /* shell_modals.js -- a string message IS a key (DOM is drawn as it is) */
66
+ {module: "shell_modals.js", name: "yui_shell_show_info", exported: true, keys: ["1"]},
67
+ {module: "shell_modals.js", name: "yui_shell_show_warning", exported: true, keys: ["1"]},
68
+ {module: "shell_modals.js", name: "yui_shell_show_error", exported: true, keys: ["1"]},
69
+ {module: "shell_modals.js", name: "yui_shell_show_modal", exported: true, keys: ["1", "2.title"]},
70
+ {module: "shell_modals.js", name: "yui_shell_confirm_ok", exported: true,
71
+ keys: ["1", "2.title", "2.ok_label"]},
72
+ {module: "shell_modals.js", name: "yui_shell_confirm_yesno", exported: true,
73
+ keys: ["1", "2.title", "2.yes_label", "2.no_label"]},
74
+ {module: "shell_modals.js", name: "yui_shell_confirm_danger", exported: true,
75
+ keys: ["1", "2.title", "2.confirm_label", "2.cancel_label"]},
76
+ {module: "shell_modals.js", name: "yui_shell_confirm_yesnocancel", exported: true,
77
+ keys: ["1", "2.title", "2.yes_label", "2.no_label", "2.cancel_label"]},
78
+ /* yui_install.js */
79
+ {module: "yui_install.js", name: "yui_install_ask_once", exported: true,
80
+ keys: ["1.message", "1.yes_label", "1.no_label"]},
81
+ /* yui_table_select.js -- the actions of the selection bar */
82
+ {module: "yui_table_select.js", name: "yui_selection_bar", exported: true,
83
+ keys: ["1.actions[].label"]},
84
+ /* yui_asset.js -- the marker of a missing asset */
85
+ {module: "yui_asset.js", name: "yui_asset_missing", exported: true, keys: ["1.key"]},
86
+ {module: "yui_asset.js", name: "yui_asset_element", exported: true, keys: ["1.key"]},
87
+ /* table_cell_text.js -- the tooltip key of a hook cell */
88
+ {module: "table_cell_text.js", name: "hook_cell_spec", exported: true, keys: ["4"]},
89
+ /* yui_time.js -- a granularity names itself by its id */
90
+ {module: "yui_time.js", name: "period_name", exported: true, keys: ["0", "0.id"]},
91
+
92
+ /*
93
+ * Helpers of their own module
94
+ */
95
+ {module: "shell_modals.js", name: "show_notification", exported: false, keys: ["2"]},
96
+ {module: "shell_modals.js", name: "build_dialog", exported: false,
97
+ keys: ["1", "2[].label", "3.title"]},
98
+ {module: "yui_time.js", name: "tr", exported: false, keys: ["1"]},
99
+ {module: "yui_tabulator_i18n.js", name: "tr", exported: false, keys: ["0"]},
100
+ {module: "yui_toolbar.js", name: "arrow_button", exported: false, keys: ["2"]},
101
+ {module: "yui_graph_camera.js", name: "camera_button", exported: false, keys: ["3"]},
102
+ {module: "c_yui_json.js", name: "icon_button", exported: false, keys: ["3"]},
103
+ {module: "c_yui_json_pad.js", name: "pad_button", exported: false, keys: ["3"]},
104
+ {module: "c_yui_json_pad.js", name: "build_pane", exported: false, keys: ["2"]},
105
+ {module: "c_yui_gclass.js", name: "icon_button", exported: false, keys: ["3"]},
106
+ {module: "c_yui_gclass.js", name: "empty_line", exported: false, keys: ["0"]},
107
+ {module: "c_yui_gclass.js", name: "build_zone", exported: false, keys: ["1.key"]},
108
+ {module: "c_yui_period.js", name: "nav_button", exported: false, keys: ["3"]},
109
+ {module: "c_yui_period.js", name: "mode_name", exported: false, keys: ["0.id", "0.roll.label"]},
110
+ {module: "c_yui_form.js", name: "cell_icon", exported: false, keys: ["1"]},
111
+ {module: "c_yui_treedb_graph.js", name: "step_button", exported: false, keys: ["2"]},
112
+ {module: "c_yui_treedb_graph.js", name: "layout_step_button", exported: false, keys: ["3"]},
113
+ {module: "c_yui_treedb_graph.js", name: "answer_print_tranger_refused", exported: false,
114
+ keys: ["2.i18n"]},
115
+ {module: "c_yui_treedb_topics.js", name: "answer_print_tranger_refused", exported: false,
116
+ keys: ["2.i18n"]},
117
+ {module: "c_yui_treedb_topics.js", name: "card_action_anchor", exported: false, keys: ["2"]},
118
+ {module: "c_yui_treedb_topics.js", name: "push_meta", exported: false, keys: ["0"]},
119
+ {module: "c_yui_treedb_topics.js", name: "relation", exported: false, keys: ["1"]},
120
+ {module: "c_yui_treedb_topic_with_form.js", name: "confirm_then", exported: false, keys: ["1"]},
121
+ {module: "c_yui_treedb_topic_with_form.js", name: "present_json_popup", exported: false,
122
+ keys: ["2.title"]},
123
+ {module: "c_yui_schema_editor.js", name: "show_notice", exported: false, keys: ["1"]},
124
+ {module: "c_yui_schema_editor.js", name: "toolbar_button", exported: false, keys: ["2"]},
125
+ {module: "c_yui_schema_editor.js", name: "row_icon", exported: false, keys: ["3"]},
126
+ {module: "c_yui_schema_editor.js", name: "name_control", exported: false, keys: ["1"]},
127
+ {module: "c_yui_schema_editor.js", name: "named", exported: false, keys: ["1"]},
128
+ {module: "c_yui_schema_editor.js", name: "name_attrs", exported: false, keys: ["0"]},
129
+ {module: "c_yui_schema_editor.js", name: "field", exported: false, keys: ["2", "4"]},
130
+ {module: "c_yui_schema_editor.js", name: "row", exported: false, keys: ["0"]},
131
+ {module: "c_yui_schema_editor.js", name: "confirm_then", exported: false, keys: ["1"]},
132
+ {module: "c_yui_schema_editor.js", name: "end_writes", exported: false, keys: ["1"]},
133
+ {module: "c_yui_schema_editor.js", name: "open_dialog", exported: false, keys: ["2"]},
134
+ {module: "c_g6_nodes_tree.js", name: "create_floating_icon", exported: false, keys: ["4"]},
135
+ {module: "c_g6_nodes_tree.js", name: "show_dual_icons", exported: false, keys: ["3", "5"]},
136
+ {module: "c_g6_nodes_tree.js", name: "create_form_label", exported: false, keys: ["1"]},
137
+ {module: "c_g6_nodes_tree.js", name: "create_form_select", exported: false, keys: ["1[].i18n"]},
138
+ {module: "c_g6_nodes_tree.js", name: "create_form_button_row", exported: false, keys: ["1[].i18n"]},
139
+ {module: "c_g6_nodes_tree.js", name: "show_confirm_popover", exported: false, keys: ["3"]},
140
+ {module: "yui_dev.js", name: "mk_view", exported: false, keys: ["1"]},
141
+ {module: "yui_dev.js", name: "mk_out", exported: false, keys: ["1"]},
142
+ {module: "yui_dev.js", name: "mk_expand", exported: false, keys: ["1"]},
143
+ {module: "yui_dev.js", name: "mk_dir", exported: false, keys: ["3"]},
144
+ {module: "yui_dev.js", name: "grp", exported: false, keys: ["0"]},
145
+ {module: "yui_dev.js", name: "grp_scroll", exported: false, keys: ["0"]},
146
+ ]);