@maccesar/titools 2.0.7 → 2.2.0
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/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
- package/README.md +250 -168
- package/agents/{ti-researcher.md → ti-pro.md} +10 -10
- package/bin/titools.js +16 -12
- package/lib/cleanup.js +95 -0
- package/lib/commands/agents.js +146 -70
- package/lib/commands/skills.js +349 -0
- package/lib/commands/uninstall.js +189 -154
- package/lib/commands/update.js +104 -21
- package/lib/config.js +26 -20
- package/lib/downloader.js +1 -1
- package/lib/installer.js +37 -97
- package/lib/platform.js +9 -5
- package/lib/prompts/checkboxCancel.js +264 -0
- package/lib/prompts/selectCancel.js +204 -0
- package/lib/symlink.js +19 -7
- package/lib/utils.js +17 -17
- package/package.json +10 -10
- package/skills/alloy-guides/SKILL.md +8 -30
- package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
- package/skills/alloy-guides/references/CONCEPTS.md +5 -25
- package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
- package/skills/alloy-guides/references/MODELS.md +40 -10
- package/skills/alloy-guides/references/PURGETSS.md +1 -11
- package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
- package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
- package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
- package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
- package/skills/alloy-guides/references/WIDGETS.md +1 -17
- package/skills/alloy-howtos/SKILL.md +1 -22
- package/skills/alloy-howtos/references/best_practices.md +0 -17
- package/skills/alloy-howtos/references/cli_reference.md +1 -23
- package/skills/alloy-howtos/references/config_files.md +86 -15
- package/skills/alloy-howtos/references/custom_tags.md +14 -13
- package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
- package/skills/alloy-howtos/references/samples.md +4 -14
- package/skills/purgetss/SKILL.md +11 -37
- package/skills/purgetss/references/EXAMPLES.md +106 -17
- package/skills/purgetss/references/animation-system.md +0 -67
- package/skills/purgetss/references/apply-directive.md +0 -18
- package/skills/purgetss/references/arbitrary-values.md +0 -25
- package/skills/purgetss/references/class-index.md +0 -46
- package/skills/purgetss/references/cli-commands.md +0 -41
- package/skills/purgetss/references/configurable-properties.md +0 -55
- package/skills/purgetss/references/custom-rules.md +0 -14
- package/skills/purgetss/references/customization-deep-dive.md +0 -49
- package/skills/purgetss/references/dynamic-component-creation.md +56 -37
- package/skills/purgetss/references/grid-layout.md +0 -32
- package/skills/purgetss/references/icon-fonts.md +0 -50
- package/skills/purgetss/references/installation-setup.md +61 -32
- package/skills/purgetss/references/migration-guide.md +127 -0
- package/skills/purgetss/references/opacity-modifier.md +0 -34
- package/skills/purgetss/references/performance-tips.md +261 -0
- package/skills/purgetss/references/platform-modifiers.md +0 -46
- package/skills/purgetss/references/smart-mappings.md +0 -12
- package/skills/purgetss/references/tikit-components.md +393 -0
- package/skills/purgetss/references/titanium-resets.md +1 -27
- package/skills/purgetss/references/ui-ux-design.md +467 -117
- package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
- package/skills/ti-expert/references/alloy-builtins.md +387 -0
- package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
- package/skills/ti-expert/references/anti-patterns.md +90 -0
- package/skills/ti-expert/references/cli-expert.md +109 -0
- package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
- package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
- package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
- package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
- package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
- package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
- package/skills/ti-expert/references/performance-listview.md +251 -0
- package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
- package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
- package/skills/ti-expert/references/security-fundamentals.md +284 -0
- package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
- package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
- package/skills/ti-expert/references/testing-unit.md +433 -0
- package/skills/ti-expert/references/theming.md +394 -0
- package/skills/ti-guides/SKILL.md +1 -14
- package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
- package/skills/ti-guides/references/app-distribution.md +48 -10
- package/skills/ti-guides/references/application-frameworks.md +9 -2
- package/skills/ti-guides/references/cli-reference.md +338 -82
- package/skills/ti-guides/references/coding-best-practices.md +14 -4
- package/skills/ti-guides/references/commonjs-advanced.md +103 -6
- package/skills/ti-guides/references/hello-world.md +5 -2
- package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
- package/skills/ti-guides/references/javascript-primer.md +4 -3
- package/skills/ti-guides/references/resources.md +0 -1
- package/skills/ti-guides/references/style-and-conventions.md +57 -9
- package/skills/ti-guides/references/tiapp-config.md +48 -6
- package/skills/ti-howtos/SKILL.md +2 -27
- package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
- package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
- package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
- package/skills/ti-howtos/references/cross-platform-development.md +68 -37
- package/skills/ti-howtos/references/debugging-profiling.md +8 -53
- package/skills/ti-howtos/references/extending-titanium.md +12 -51
- package/skills/ti-howtos/references/google-maps-v2.md +30 -29
- package/skills/ti-howtos/references/ios-map-kit.md +19 -25
- package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
- package/skills/ti-howtos/references/local-data-sources.md +45 -37
- package/skills/ti-howtos/references/location-and-maps.md +47 -28
- package/skills/ti-howtos/references/media-apis.md +84 -27
- package/skills/ti-howtos/references/notification-services.md +40 -89
- package/skills/ti-howtos/references/remote-data-sources.md +21 -36
- package/skills/ti-howtos/references/tutorials.md +79 -39
- package/skills/ti-howtos/references/using-modules.md +4 -30
- package/skills/ti-howtos/references/web-content-integration.md +28 -45
- package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
- package/skills/ti-ui/SKILL.md +1 -21
- package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
- package/skills/ti-ui/references/animation-and-matrices.md +0 -47
- package/skills/ti-ui/references/application-structures.md +0 -46
- package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
- package/skills/ti-ui/references/event-handling.md +32 -40
- package/skills/ti-ui/references/gestures.md +0 -40
- package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
- package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
- package/skills/ti-ui/references/listviews-and-performance.md +187 -73
- package/skills/ti-ui/references/orientation.md +57 -71
- package/skills/ti-ui/references/platform-ui-android.md +114 -48
- package/skills/ti-ui/references/platform-ui-ios.md +63 -38
- package/skills/ti-ui/references/scrolling-views.md +14 -23
- package/skills/ti-ui/references/tableviews.md +6 -56
- package/lib/commands/install.js +0 -188
- package/skills/alloy-expert/references/anti-patterns.md +0 -133
- package/skills/alloy-expert/references/testing.md +0 -872
- package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
- package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
- package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
- /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
- /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Separator,
|
|
3
|
+
ValidationError,
|
|
4
|
+
createPrompt,
|
|
5
|
+
isBackspaceKey,
|
|
6
|
+
isDownKey,
|
|
7
|
+
isEnterKey,
|
|
8
|
+
isNumberKey,
|
|
9
|
+
isUpKey,
|
|
10
|
+
makeTheme,
|
|
11
|
+
useEffect,
|
|
12
|
+
useKeypress,
|
|
13
|
+
useMemo,
|
|
14
|
+
usePagination,
|
|
15
|
+
usePrefix,
|
|
16
|
+
useRef,
|
|
17
|
+
useState,
|
|
18
|
+
} from '@inquirer/core';
|
|
19
|
+
import { cursorHide } from '@inquirer/ansi';
|
|
20
|
+
import { styleText } from 'node:util';
|
|
21
|
+
import figures from '@inquirer/figures';
|
|
22
|
+
|
|
23
|
+
const selectTheme = {
|
|
24
|
+
icon: { cursor: figures.pointer },
|
|
25
|
+
style: {
|
|
26
|
+
disabled: (text) => styleText('dim', `- ${text}`),
|
|
27
|
+
description: (text) => styleText('cyan', text),
|
|
28
|
+
keysHelpTip: (keys) =>
|
|
29
|
+
keys
|
|
30
|
+
.map(([key, action]) => `${styleText('bold', key)} ${styleText('dim', action)}`)
|
|
31
|
+
.join(styleText('dim', ' • ')),
|
|
32
|
+
},
|
|
33
|
+
indexMode: 'hidden',
|
|
34
|
+
keybindings: [],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function isSelectable(item) {
|
|
38
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function normalizeChoices(choices) {
|
|
42
|
+
return choices.map((choice) => {
|
|
43
|
+
if (Separator.isSeparator(choice)) return choice;
|
|
44
|
+
if (typeof choice !== 'object' || choice === null || !('value' in choice)) {
|
|
45
|
+
const name = String(choice);
|
|
46
|
+
return {
|
|
47
|
+
value: choice,
|
|
48
|
+
name,
|
|
49
|
+
short: name,
|
|
50
|
+
disabled: false,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const name = choice.name ?? String(choice.value);
|
|
54
|
+
const normalizedChoice = {
|
|
55
|
+
value: choice.value,
|
|
56
|
+
name,
|
|
57
|
+
short: choice.short ?? name,
|
|
58
|
+
disabled: choice.disabled ?? false,
|
|
59
|
+
};
|
|
60
|
+
if (choice.description) {
|
|
61
|
+
normalizedChoice.description = choice.description;
|
|
62
|
+
}
|
|
63
|
+
return normalizedChoice;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const selectCancel = createPrompt((config, done) => {
|
|
68
|
+
const { loop = true, pageSize = 7, cancelValue = 'cancel' } = config;
|
|
69
|
+
const theme = makeTheme(selectTheme, config.theme);
|
|
70
|
+
const { keybindings } = theme;
|
|
71
|
+
const [status, setStatus] = useState('idle');
|
|
72
|
+
const [cancelled, setCancelled] = useState(false);
|
|
73
|
+
const prefix = usePrefix({ status, theme });
|
|
74
|
+
const searchTimeoutRef = useRef();
|
|
75
|
+
const searchEnabled = !keybindings.includes('vim');
|
|
76
|
+
const items = useMemo(() => normalizeChoices(config.choices), [config.choices]);
|
|
77
|
+
const bounds = useMemo(() => {
|
|
78
|
+
const first = items.findIndex(isSelectable);
|
|
79
|
+
const last = items.findLastIndex(isSelectable);
|
|
80
|
+
if (first === -1) {
|
|
81
|
+
throw new ValidationError('[select prompt] No selectable choices. All choices are disabled.');
|
|
82
|
+
}
|
|
83
|
+
return { first, last };
|
|
84
|
+
}, [items]);
|
|
85
|
+
const defaultItemIndex = useMemo(() => {
|
|
86
|
+
if (!('default' in config)) return -1;
|
|
87
|
+
return items.findIndex((item) => isSelectable(item) && item.value === config.default);
|
|
88
|
+
}, [config.default, items]);
|
|
89
|
+
const [active, setActive] = useState(defaultItemIndex === -1 ? bounds.first : defaultItemIndex);
|
|
90
|
+
const selectedChoice = items[active];
|
|
91
|
+
|
|
92
|
+
useKeypress((key, rl) => {
|
|
93
|
+
clearTimeout(searchTimeoutRef.current);
|
|
94
|
+
if (key.name?.toLowerCase() === 'q') {
|
|
95
|
+
setCancelled(true);
|
|
96
|
+
setStatus('done');
|
|
97
|
+
done(cancelValue);
|
|
98
|
+
} else if (isEnterKey(key)) {
|
|
99
|
+
setStatus('done');
|
|
100
|
+
done(selectedChoice.value);
|
|
101
|
+
}
|
|
102
|
+
else if (isUpKey(key, keybindings) || isDownKey(key, keybindings)) {
|
|
103
|
+
rl.clearLine(0);
|
|
104
|
+
if (
|
|
105
|
+
loop ||
|
|
106
|
+
(isUpKey(key, keybindings) && active !== bounds.first) ||
|
|
107
|
+
(isDownKey(key, keybindings) && active !== bounds.last)
|
|
108
|
+
) {
|
|
109
|
+
const offset = isUpKey(key, keybindings) ? -1 : 1;
|
|
110
|
+
let next = active;
|
|
111
|
+
do {
|
|
112
|
+
next = (next + offset + items.length) % items.length;
|
|
113
|
+
} while (!isSelectable(items[next]));
|
|
114
|
+
setActive(next);
|
|
115
|
+
}
|
|
116
|
+
} else if (isNumberKey(key) && !Number.isNaN(Number(rl.line))) {
|
|
117
|
+
const selectedIndex = Number(rl.line) - 1;
|
|
118
|
+
let selectableIndex = -1;
|
|
119
|
+
const position = items.findIndex((item) => {
|
|
120
|
+
if (Separator.isSeparator(item)) return false;
|
|
121
|
+
selectableIndex++;
|
|
122
|
+
return selectableIndex === selectedIndex;
|
|
123
|
+
});
|
|
124
|
+
const item = items[position];
|
|
125
|
+
if (item != null && isSelectable(item)) {
|
|
126
|
+
setActive(position);
|
|
127
|
+
}
|
|
128
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
129
|
+
rl.clearLine(0);
|
|
130
|
+
}, 700);
|
|
131
|
+
} else if (isBackspaceKey(key)) {
|
|
132
|
+
rl.clearLine(0);
|
|
133
|
+
} else if (searchEnabled) {
|
|
134
|
+
const searchTerm = rl.line.toLowerCase();
|
|
135
|
+
const matchIndex = items.findIndex((item) => {
|
|
136
|
+
if (Separator.isSeparator(item) || !isSelectable(item)) return false;
|
|
137
|
+
return item.name.toLowerCase().startsWith(searchTerm);
|
|
138
|
+
});
|
|
139
|
+
if (matchIndex !== -1) {
|
|
140
|
+
setActive(matchIndex);
|
|
141
|
+
}
|
|
142
|
+
searchTimeoutRef.current = setTimeout(() => {
|
|
143
|
+
rl.clearLine(0);
|
|
144
|
+
}, 700);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
useEffect(() => () => {
|
|
149
|
+
clearTimeout(searchTimeoutRef.current);
|
|
150
|
+
}, []);
|
|
151
|
+
|
|
152
|
+
const message = theme.style.message(config.message, status);
|
|
153
|
+
const helpLine = theme.style.keysHelpTip([
|
|
154
|
+
['↑↓', 'navigate'],
|
|
155
|
+
['⏎', 'select'],
|
|
156
|
+
['q', 'quit'],
|
|
157
|
+
]);
|
|
158
|
+
let separatorCount = 0;
|
|
159
|
+
const page = usePagination({
|
|
160
|
+
items,
|
|
161
|
+
active,
|
|
162
|
+
renderItem({ item, isActive, index }) {
|
|
163
|
+
if (Separator.isSeparator(item)) {
|
|
164
|
+
separatorCount++;
|
|
165
|
+
return ` ${item.separator}`;
|
|
166
|
+
}
|
|
167
|
+
const indexLabel = theme.indexMode === 'number' ? `${index + 1 - separatorCount}. ` : '';
|
|
168
|
+
if (item.disabled) {
|
|
169
|
+
const disabledLabel = typeof item.disabled === 'string' ? item.disabled : '(disabled)';
|
|
170
|
+
return theme.style.disabled(`${indexLabel}${item.name} ${disabledLabel}`);
|
|
171
|
+
}
|
|
172
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
173
|
+
const cursor = isActive ? theme.icon.cursor : ` `;
|
|
174
|
+
return color(`${cursor} ${indexLabel}${item.name}`);
|
|
175
|
+
},
|
|
176
|
+
pageSize,
|
|
177
|
+
loop,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
if (status === 'done') {
|
|
181
|
+
if (cancelled) {
|
|
182
|
+
return [prefix, message].filter(Boolean).join(' ');
|
|
183
|
+
}
|
|
184
|
+
return [prefix, message, theme.style.answer(selectedChoice.short)]
|
|
185
|
+
.filter(Boolean)
|
|
186
|
+
.join(' ');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const { description } = selectedChoice;
|
|
190
|
+
const lines = [
|
|
191
|
+
[prefix, message].filter(Boolean).join(' '),
|
|
192
|
+
page,
|
|
193
|
+
' ',
|
|
194
|
+
description ? theme.style.description(description) : '',
|
|
195
|
+
helpLine,
|
|
196
|
+
]
|
|
197
|
+
.filter(Boolean)
|
|
198
|
+
.join('\n')
|
|
199
|
+
.trimEnd();
|
|
200
|
+
return `${lines}${cursorHide}`;
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
export { Separator };
|
|
204
|
+
export default selectCancel;
|
package/lib/symlink.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { mkdirSync, existsSync } from 'fs';
|
|
7
|
-
import { symlink, readlink, unlink } from 'fs/promises';
|
|
8
|
-
import { join, dirname } from 'path';
|
|
7
|
+
import { symlink, readlink, unlink, lstat } from 'fs/promises';
|
|
8
|
+
import { join, dirname, relative } from 'path';
|
|
9
9
|
import { copy, remove } from 'fs-extra';
|
|
10
10
|
import { isWindows } from './platform.js';
|
|
11
11
|
|
|
@@ -13,9 +13,10 @@ import { isWindows } from './platform.js';
|
|
|
13
13
|
* Create a symlink or copy as fallback
|
|
14
14
|
* @param {string} target - Target path (what the symlink points to)
|
|
15
15
|
* @param {string} path - Symlink path (where to create it)
|
|
16
|
+
* @param {boolean} useRelative - Whether to use a relative path for the symlink
|
|
16
17
|
* @returns {Promise<boolean>} True if successful
|
|
17
18
|
*/
|
|
18
|
-
export async function createSymlinkOrCopy(target, path) {
|
|
19
|
+
export async function createSymlinkOrCopy(target, path, useRelative = false) {
|
|
19
20
|
// Ensure parent directory exists
|
|
20
21
|
const dir = dirname(path);
|
|
21
22
|
if (!existsSync(dir)) {
|
|
@@ -27,9 +28,16 @@ export async function createSymlinkOrCopy(target, path) {
|
|
|
27
28
|
await removePath(path);
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
// Determine final target path
|
|
32
|
+
let finalTarget = target;
|
|
33
|
+
if (useRelative) {
|
|
34
|
+
finalTarget = relative(dirname(path), target);
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
// Try creating symlink first
|
|
31
38
|
try {
|
|
32
|
-
|
|
39
|
+
// Windows requires 'junction' or 'dir' for directory symlinks
|
|
40
|
+
await symlink(finalTarget, path, 'dir');
|
|
33
41
|
return true;
|
|
34
42
|
} catch (error) {
|
|
35
43
|
// On Windows or if symlink fails, copy the directory
|
|
@@ -64,11 +72,12 @@ async function removePath(path) {
|
|
|
64
72
|
* Create symlinks for all skills to a platform directory
|
|
65
73
|
* @param {string} platformSkillsDir - Platform skills directory
|
|
66
74
|
* @param {Array} skills - List of skill names
|
|
75
|
+
* @param {string} baseDir - Optional base directory for target resolution
|
|
67
76
|
* @returns {Promise<Object>} Results object with success/failure counts
|
|
68
77
|
*/
|
|
69
|
-
export async function createSkillSymlinks(platformSkillsDir, skills) {
|
|
78
|
+
export async function createSkillSymlinks(platformSkillsDir, skills, baseDir) {
|
|
70
79
|
const { getAgentsSkillsDir } = await import('./config.js');
|
|
71
|
-
const agentsSkillsDir = getAgentsSkillsDir();
|
|
80
|
+
const agentsSkillsDir = getAgentsSkillsDir(baseDir);
|
|
72
81
|
|
|
73
82
|
const results = {
|
|
74
83
|
linked: [],
|
|
@@ -80,11 +89,14 @@ export async function createSkillSymlinks(platformSkillsDir, skills) {
|
|
|
80
89
|
mkdirSync(platformSkillsDir, { recursive: true });
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
// Use relative symlinks if we are in a local installation
|
|
93
|
+
const useRelative = !!baseDir;
|
|
94
|
+
|
|
83
95
|
for (const skill of skills) {
|
|
84
96
|
const target = join(agentsSkillsDir, skill);
|
|
85
97
|
const linkPath = join(platformSkillsDir, skill);
|
|
86
98
|
|
|
87
|
-
if (await createSymlinkOrCopy(target, linkPath)) {
|
|
99
|
+
if (await createSymlinkOrCopy(target, linkPath, useRelative)) {
|
|
88
100
|
results.linked.push(skill);
|
|
89
101
|
} else {
|
|
90
102
|
results.failed.push(skill);
|
package/lib/utils.js
CHANGED
|
@@ -40,20 +40,21 @@ export function removeOldBlock(filePath) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const content = readFileSync(filePath, 'utf8');
|
|
43
|
-
//
|
|
44
|
-
const
|
|
43
|
+
// Surgical regex to match ONLY the Titanium knowledge block
|
|
44
|
+
const blockRegex = /\n*<!-- TITANIUM-KNOWLEDGE-(v[\d.]+|START) -->[\s\S]*?<!-- (END-TITANIUM-KNOWLEDGE|TITANIUM-KNOWLEDGE-END) -->\n*/g;
|
|
45
45
|
|
|
46
|
-
const newContent = content.replace(
|
|
46
|
+
const newContent = content.replace(blockRegex, '\n').trimEnd();
|
|
47
47
|
|
|
48
|
-
writeFileSync(filePath, newContent, 'utf8');
|
|
48
|
+
writeFileSync(filePath, newContent + '\n', 'utf8');
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Build the compressed documentation index dynamically by scanning skills
|
|
54
|
+
* @param {string} rootPath - The root path to use in the index (default: ~/.agents/skills)
|
|
54
55
|
* @returns {string} The compressed index section
|
|
55
56
|
*/
|
|
56
|
-
export function buildKnowledgeIndex() {
|
|
57
|
+
export function buildKnowledgeIndex(rootPath = '~/.agents/skills') {
|
|
57
58
|
let skills = [];
|
|
58
59
|
|
|
59
60
|
try {
|
|
@@ -84,18 +85,19 @@ export function buildKnowledgeIndex() {
|
|
|
84
85
|
// Note: Using \u0060 to avoid backtick parsing issues in template literals
|
|
85
86
|
return '### Compressed Documentation Index\n\n' +
|
|
86
87
|
'\u0060\u0060\u0060\n' +
|
|
87
|
-
|
|
88
|
+
`[Titanium SDK Docs Index]|root: ${rootPath}\n` +
|
|
88
89
|
'|' + indexEntries.join('\n|') + '\n' +
|
|
89
90
|
'\u0060\u0060\u0060';
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
/**
|
|
93
94
|
* Create the Titanium knowledge block content dynamically
|
|
95
|
+
* @param {string} rootPath - The root path to use in the index
|
|
94
96
|
* @returns {string} The knowledge block content
|
|
95
97
|
*/
|
|
96
|
-
export function createKnowledgeBlock() {
|
|
98
|
+
export function createKnowledgeBlock(rootPath) {
|
|
97
99
|
// Build the compressed index dynamically
|
|
98
|
-
const compressedIndex = buildKnowledgeIndex();
|
|
100
|
+
const compressedIndex = buildKnowledgeIndex(rootPath);
|
|
99
101
|
|
|
100
102
|
// Build the knowledge block using template literals
|
|
101
103
|
const blockHeader = `${BLOCK_START}\n<!-- Version: ${TITANIUM_KNOWLEDGE_VERSION} -->`;
|
|
@@ -108,27 +110,28 @@ Always consult the documentation files below rather than relying on training dat
|
|
|
108
110
|
|
|
109
111
|
This knowledge index is based on the latest Titanium SDK documentation.`;
|
|
110
112
|
|
|
111
|
-
return `\n
|
|
113
|
+
return `\n${blockHeader}\n${commentContent}\n\n${compressedIndex}\n${BLOCK_END}\n`;
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
/**
|
|
115
117
|
* Add or update Titanium knowledge block in a file
|
|
116
118
|
* @param {string} filePath - Path to the file
|
|
119
|
+
* @param {string} rootPath - Optional root path for the index
|
|
117
120
|
* @returns {boolean} True if file was updated
|
|
118
121
|
*/
|
|
119
|
-
export function addOrUpdateBlock(filePath) {
|
|
122
|
+
export function addOrUpdateBlock(filePath, rootPath) {
|
|
120
123
|
let content = '';
|
|
121
124
|
|
|
122
125
|
if (existsSync(filePath)) {
|
|
123
126
|
content = readFileSync(filePath, 'utf8');
|
|
124
127
|
}
|
|
125
128
|
|
|
126
|
-
const block = createKnowledgeBlock();
|
|
129
|
+
const block = createKnowledgeBlock(rootPath);
|
|
127
130
|
|
|
128
131
|
// Regex to find ALL existing blocks (old versioned or new static)
|
|
129
132
|
// Global flag /g is CRITICAL here to remove every single occurrence
|
|
130
133
|
const globalBlockRegex = /<!-- TITANIUM-KNOWLEDGE-(v[\d.]+|START) -->[\s\S]*?<!-- (END-TITANIUM-KNOWLEDGE|TITANIUM-KNOWLEDGE-END) -->/g;
|
|
131
|
-
|
|
134
|
+
|
|
132
135
|
// Clean up all existing blocks to prevent accumulation
|
|
133
136
|
content = content.replace(globalBlockRegex, '').trim();
|
|
134
137
|
|
|
@@ -216,11 +219,8 @@ export function formatList(items) {
|
|
|
216
219
|
* @returns {Array} Array of version parts
|
|
217
220
|
*/
|
|
218
221
|
export function parseVersion(version) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
.replace('.RC', '-')
|
|
222
|
-
.split(/[.-]/)
|
|
223
|
-
.map((v) => parseInt(v, 10) || 0);
|
|
222
|
+
const matches = version.match(/\d+/g) || [];
|
|
223
|
+
return matches.map((v) => parseInt(v, 10));
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maccesar/titools",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Titanium SDK skills and agents for AI coding assistants (Claude Code, Gemini CLI, Codex CLI)",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -41,23 +41,23 @@
|
|
|
41
41
|
"node": ">=18.0.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"ora": "^
|
|
49
|
-
"tar": "^7.
|
|
44
|
+
"@inquirer/prompts": "^8.2.0",
|
|
45
|
+
"chalk": "^5.6.2",
|
|
46
|
+
"commander": "^14.0.3",
|
|
47
|
+
"fs-extra": "^11.3.3",
|
|
48
|
+
"ora": "^9.1.0",
|
|
49
|
+
"tar": "^7.5.7"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"eslint": "^
|
|
53
|
-
"prettier": "^3.
|
|
52
|
+
"eslint": "^9.39.2",
|
|
53
|
+
"prettier": "^3.8.1"
|
|
54
54
|
},
|
|
55
55
|
"files": [
|
|
56
56
|
"bin/",
|
|
57
57
|
"lib/",
|
|
58
58
|
"skills/",
|
|
59
59
|
"agents/",
|
|
60
|
-
"AGENTS-
|
|
60
|
+
"AGENTS-VERCEL-RESEARCH.md",
|
|
61
61
|
"scripts/titools-docs"
|
|
62
62
|
],
|
|
63
63
|
"publishConfig": {
|
|
@@ -26,28 +26,6 @@ This skill automatically detects Alloy projects when invoked and provides framew
|
|
|
26
26
|
- **Not detected** → Indicates this skill is for Alloy projects only, does not suggest Alloy-specific features
|
|
27
27
|
:::
|
|
28
28
|
|
|
29
|
-
## Table of Contents
|
|
30
|
-
|
|
31
|
-
- [Alloy MVC Framework Guide](#alloy-mvc-framework-guide)
|
|
32
|
-
- [Project Detection](#project-detection)
|
|
33
|
-
- [Table of Contents](#table-of-contents)
|
|
34
|
-
- [Quick Reference](#quick-reference)
|
|
35
|
-
- [Project Structure](#project-structure)
|
|
36
|
-
- [MVC Quick Start](#mvc-quick-start)
|
|
37
|
-
- [Key Concepts](#key-concepts)
|
|
38
|
-
- [Critical Rules](#critical-rules)
|
|
39
|
-
- [Platform-Specific Properties in TSS](#platform-specific-properties-in-tss)
|
|
40
|
-
- [Common Patterns](#common-patterns)
|
|
41
|
-
- [Creating a Model](#creating-a-model)
|
|
42
|
-
- [Data Binding](#data-binding)
|
|
43
|
-
- [Platform-Specific Code](#platform-specific-code)
|
|
44
|
-
- [Widget Usage](#widget-usage)
|
|
45
|
-
- [Compilation Process](#compilation-process)
|
|
46
|
-
- [References](#references)
|
|
47
|
-
- [Related Skills](#related-skills)
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
29
|
## Quick Reference
|
|
52
30
|
|
|
53
31
|
| Topic | Reference File |
|
|
@@ -61,7 +39,7 @@ This skill automatically detects Alloy projects when invoked and provides framew
|
|
|
61
39
|
| Controllers-less views, patterns | [VIEWS_WITHOUT_CONTROLLERS.md](references/VIEWS_WITHOUT_CONTROLLERS.md) |
|
|
62
40
|
| Creating and using widgets | [WIDGETS.md](references/WIDGETS.md) |
|
|
63
41
|
| CLI commands, code generation | [CLI_TASKS.md](references/CLI_TASKS.md) |
|
|
64
|
-
| PurgeTSS integration
|
|
42
|
+
| PurgeTSS integration (optional addon) | [PURGETSS.md](references/PURGETSS.md) |
|
|
65
43
|
|
|
66
44
|
## Project Structure
|
|
67
45
|
|
|
@@ -156,7 +134,7 @@ Using `Ti.UI.iOS.*` or `Ti.UI.Android.*` properties in TSS WITHOUT platform modi
|
|
|
156
134
|
|
|
157
135
|
**Available modifiers:** `[platform=ios]`, `[platform=android]`, `[formFactor=handheld]`, `[formFactor=tablet]`, `[if=Alloy.Globals.customVar]`
|
|
158
136
|
|
|
159
|
-
**For more platform-specific patterns, see** [
|
|
137
|
+
**For more platform-specific patterns, see** [Code Conventions (ti-expert)](skills/ti-expert/references/code-conventions.md#platform--device-modifiers) or [Platform UI guides (ti-ui)](skills/ti-ui/references/platform-ui-ios.md).
|
|
160
138
|
:::
|
|
161
139
|
|
|
162
140
|
## Common Patterns
|
|
@@ -206,9 +184,9 @@ Read detailed documentation from the reference files listed above based on your
|
|
|
206
184
|
|
|
207
185
|
For tasks beyond Alloy MVC basics, use these complementary skills:
|
|
208
186
|
|
|
209
|
-
| Task
|
|
210
|
-
|
|
|
211
|
-
| Modern architecture, services, patterns
|
|
212
|
-
| Alloy CLI, config files, debugging errors
|
|
213
|
-
| Utility-first styling with PurgeTSS
|
|
214
|
-
| Native features (location, push, media)
|
|
187
|
+
| Task | Use This Skill |
|
|
188
|
+
| ---------------------------------------------- | -------------- |
|
|
189
|
+
| Modern architecture, services, patterns | `ti-expert` |
|
|
190
|
+
| Alloy CLI, config files, debugging errors | `alloy-howtos` |
|
|
191
|
+
| Utility-first styling with PurgeTSS (optional) | `purgetss` |
|
|
192
|
+
| Native features (location, push, media) | `ti-howtos` |
|
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
# Alloy Tasks with the CLI
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
- [Alloy Tasks with the CLI](#alloy-tasks-with-the-cli)
|
|
6
|
-
- [Table of Contents](#table-of-contents)
|
|
7
|
-
- [Creating a New Application](#creating-a-new-application)
|
|
8
|
-
- [Creating a New Application Using a Test Application](#creating-a-new-application-using-a-test-application)
|
|
9
|
-
- [Generating Components](#generating-components)
|
|
10
|
-
- [Generating a Controller](#generating-a-controller)
|
|
11
|
-
- [Generating a View](#generating-a-view)
|
|
12
|
-
- [Generating a Style](#generating-a-style)
|
|
13
|
-
- [Generating a Model](#generating-a-model)
|
|
14
|
-
- [Generating a Migration](#generating-a-migration)
|
|
15
|
-
- [Generating a Widget](#generating-a-widget)
|
|
16
|
-
- [Generating alloy.jmk](#generating-alloyjmk)
|
|
17
|
-
- [Extracting Localization Strings](#extracting-localization-strings)
|
|
18
|
-
- [Compiling a Specific View-Controller](#compiling-a-specific-view-controller)
|
|
19
|
-
- [Building an Application](#building-an-application)
|
|
20
|
-
- [Installing Special Project Components](#installing-special-project-components)
|
|
21
|
-
- [Installing the Compiler Plugin](#installing-the-compiler-plugin)
|
|
3
|
+
Alloy provides command-line interface (CLI) tasks to create a new project, generate skeleton components such as controllers and models, and compile the source files into the Titanium project.
|
|
22
4
|
|
|
23
5
|
## Creating a New Application
|
|
24
6
|
|
|
@@ -88,7 +70,7 @@ To generate a style for a view-controller:
|
|
|
88
70
|
alloy generate style <name> [--widgetname <widget_name>]
|
|
89
71
|
```
|
|
90
72
|
|
|
91
|
-
Alloy uses the id and attribute names in the markup file to populate the skeleton style file. This creates `app/styles/<name>.tss`.
|
|
73
|
+
Alloy uses the id and attribute names in the markup file to populate the skeleton style file. This creates `app/styles/<name>.tss`. If you add new `id` or `class` attributes to the markup file, running either of these commands updates the style file with the new attributes.
|
|
92
74
|
|
|
93
75
|
To generate style files for all view-controllers:
|
|
94
76
|
|
|
@@ -104,7 +86,7 @@ To generate a model:
|
|
|
104
86
|
alloy generate model <name> <adapter> [<col_name_1>:<col_type_1> <col_name_2>:<col_type_2> ...] [-o path_to_project/app]
|
|
105
87
|
```
|
|
106
88
|
|
|
107
|
-
The fourth parameter selects the adapter type: `sql` for SQLite or `properties` for local storage.
|
|
89
|
+
The fourth parameter selects the adapter type: `sql` for SQLite or `properties` for local storage. The fifth parameter defines the table schema. This is required for `sql` and `properties` adapter types.
|
|
108
90
|
|
|
109
91
|
This creates `app/models/<name>.js`, and `app/migrations/DATETIME_<name>.js` if the adapter type is 'sql'.
|
|
110
92
|
|
|
@@ -148,8 +130,8 @@ alloy extract-i18n [language] [--apply]
|
|
|
148
130
|
|
|
149
131
|
**Parameters**:
|
|
150
132
|
|
|
151
|
-
* `language` – Optional. Two-letter language code (`en
|
|
152
|
-
* `--apply` – Optional. Writes new entries to `strings.xml`. Without it, displays a preview.
|
|
133
|
+
* `language` – Optional. Two-letter language code (`en`, `es`, etc.). Default is `en`.
|
|
134
|
+
* `--apply` – Optional. Writes new entries to `strings.xml`. Without it, displays a preview. This is a safe operation: it only adds new entries and never removes existing ones.
|
|
153
135
|
|
|
154
136
|
Supported functions:
|
|
155
137
|
|
|
@@ -197,7 +179,15 @@ Running with `--apply`:
|
|
|
197
179
|
alloy extract-i18n --apply
|
|
198
180
|
```
|
|
199
181
|
|
|
200
|
-
Generates `app/i18n/en/strings.xml
|
|
182
|
+
Generates `app/i18n/en/strings.xml`.
|
|
183
|
+
|
|
184
|
+
To generate strings for another language, pass the language code:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
alloy extract-i18n es --apply
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This generates `app/i18n/es/strings.xml`.
|
|
201
191
|
|
|
202
192
|
```xml
|
|
203
193
|
<resources>
|
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
# Alloy Concepts
|
|
2
2
|
|
|
3
|
-
## Table of Contents
|
|
4
|
-
|
|
5
|
-
- [Alloy Concepts](#alloy-concepts)
|
|
6
|
-
- [Table of Contents](#table-of-contents)
|
|
7
|
-
- [Overview](#overview)
|
|
8
|
-
- [Model-View-Controller](#model-view-controller)
|
|
9
|
-
- [Alloy: MVC with Backbone](#alloy-mvc-with-backbone)
|
|
10
|
-
- [Alloy and the Titanium SDK](#alloy-and-the-titanium-sdk)
|
|
11
|
-
- [Titanium SDK to Alloy Mapping](#titanium-sdk-to-alloy-mapping)
|
|
12
|
-
- [Convention over Configuration](#convention-over-configuration)
|
|
13
|
-
- [Platform-Specific Resources](#platform-specific-resources)
|
|
14
|
-
- [Widgets](#widgets)
|
|
15
|
-
- [Builtins](#builtins)
|
|
16
|
-
- [Compilation Process](#compilation-process)
|
|
17
|
-
- [Cleanup](#cleanup)
|
|
18
|
-
- [Build Configuration](#build-configuration)
|
|
19
|
-
- [Alloy Framework, Assets, and Lib](#alloy-framework-assets-and-lib)
|
|
20
|
-
- [Model-View-Controller and Widget Generation](#model-view-controller-and-widget-generation)
|
|
21
|
-
- [Main Application](#main-application)
|
|
22
|
-
- [Code Optimization](#code-optimization)
|
|
23
|
-
|
|
24
3
|
## Overview
|
|
25
4
|
|
|
26
5
|
This guide covers the important concepts related to the Alloy framework, including the model-view-controller framework, convention-over-configuration design, widgets, and built-in support from Backbone.js and Underscore.js.
|
|
@@ -59,14 +38,15 @@ For assets, such as images, any references to the `Resources` folder in the Tita
|
|
|
59
38
|
|
|
60
39
|
| Titanium SDK Component | Alloy Component |
|
|
61
40
|
| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
-
| **Titanium.UI
|
|
41
|
+
| **Titanium.UI.\* Objects** (and others: `Ti.Android.Menu`, `Ti.Facebook.LoginButton`, `Ti.Map`, `Ti.Media.VideoPlayer`) | **XML element**. Remove the namespace. For some elements, you may need to assign the `ns` attribute. Some objects are implicitly assigned namespaces by Alloy. |
|
|
63
42
|
| `Titanium.UI.createButton();` | `<Button />` creates a button |
|
|
64
43
|
| | **TSS element**. Remove the namespace. |
|
|
65
44
|
| | `"Button":{ /* Button attributes */ }` |
|
|
66
45
|
| **Titanium Object properties** | **XML attribute** if the property can be expressed as a string, number or Titanium SDK constant. |
|
|
67
46
|
| `Titanium.UI.createButton({text: "Foobar", top: 0, width: Ti.UI.SIZE});` | `<Button title="Foobar" top="0" width="Ti.UI.SIZE"/>` |
|
|
68
|
-
| | **TSS attribute** if the property can be directly expressed as a string, number, Titanium SDK constant, dictionary or array.
|
|
47
|
+
| | **TSS attribute** if the property can be directly expressed as a string, number, Titanium SDK constant, dictionary or array. Indirectly, you can assign a method or value to the `Alloy.Globals` or `Alloy.CFG` namespace and reference it in the TSS file. |
|
|
69
48
|
| | `"Button":{ title: "Foobar", top: 0, width: Ti.UI.SIZE }` |
|
|
49
|
+
| **Titanium Object properties (proxy)** | Some properties that take Titanium objects can be expressed inline using XML tags (Property Mapping). See [VIEWS_XML.md](./VIEWS_XML.md#property-mapping). |
|
|
70
50
|
| **Titanium Object methods** | Use in the controller code. You need to define the `id` attribute of the object in the XML markup, so the object can be referenced in the controller. |
|
|
71
51
|
| `const button = Titanium.UI.createButton(); button.setTitle('Push Me!');` | `// Need to give the object an ID: <Button id="button" />` then `$.button.setTitle('Push Me!');` |
|
|
72
52
|
| **Titanium Object events** | XML attribute to bind a callback in the associated controller. Capitalize the first character of the event name and append 'on' to the beginning of the name. |
|
|
@@ -84,7 +64,7 @@ The following is a list of directories and files that can be found in an Alloy p
|
|
|
84
64
|
| `app/alloy.jmk` | Build configuration file. See Build Configuration File (alloy.jmk). |
|
|
85
65
|
| `app/alloy.js` | Initializer file used to preconfigure components or override Alloy methods before the main controller is executed. |
|
|
86
66
|
| `app/config.json` | Project configuration file. See Project Configuration File (config.json). |
|
|
87
|
-
| `app/assets` | Contains image assets and other files that need to be copied into the `Resources` directory. Reference these files in the code without the 'app/assets' path.
|
|
67
|
+
| `app/assets` | Contains image assets and other files that need to be copied into the `Resources` directory. Reference these files in the code without the 'app/assets' path (and without the platform-specific folder if it is inside one). |
|
|
88
68
|
| `app/controllers` | Contains controllers in the format `filename.js` to a corresponding view file `app/views/filename.xml`. |
|
|
89
69
|
| `app/i18n` | Since Alloy 1.8.0 and Titanium 5.2.0 Language Strings are sourced from `app/i18n` and Alloy will generate the `i18n` folder in the project root. |
|
|
90
70
|
| `app/lib` | Contains application-specific library code, typically in the CommonJS format. |
|
|
@@ -96,7 +76,7 @@ The following is a list of directories and files that can be found in an Alloy p
|
|
|
96
76
|
| `app/themes` | Contains themes to customize the assets and styles of the entire GUI. |
|
|
97
77
|
| `app/views` | Contains views in the format `filename.xml` with the optional corresponding files `app/controllers/filename.js` and `app/styles/filename.tss`. |
|
|
98
78
|
| `app/widgets` | Contains widget files. Each widget will have its own `app`-like directory structure. |
|
|
99
|
-
| `i18n` | Since Alloy 1.8.0 and Titanium 5.2.0 Language Strings are sourced from `app/i18n` and Alloy will generate the `i18n` folder in the project root.
|
|
79
|
+
| `i18n` | Since Alloy 1.8.0 and Titanium 5.2.0 Language Strings are sourced from `app/i18n` and Alloy will generate the `i18n` folder in the project root. Before Alloy 1.8.0, the `i18n` folder was managed in the project root directly. |
|
|
100
80
|
| `Resources` | Contains the Titanium files generated by the Alloy interface from the `app` directory. All files will be overwritten each time the application is built. Since Alloy 1.3.0, Alloy creates a separate Titanium project for each platform you build for in the `Resources/<platform>` folder. |
|
|
101
81
|
|
|
102
82
|
**Notes:** the `lib`, `migrations`, `themes` and `widgets` folders are not automatically generated when creating a new project. The `migrations` and `widgets` folder will be generated by the Alloy command-line interface if any of those components are generated. The `lib` and `themes` folders will need to be manually created.
|
|
@@ -1,22 +1,5 @@
|
|
|
1
1
|
# Alloy Controllers
|
|
2
2
|
|
|
3
|
-
## Table of Contents
|
|
4
|
-
|
|
5
|
-
- [Alloy Controllers](#alloy-controllers)
|
|
6
|
-
- [Table of Contents](#table-of-contents)
|
|
7
|
-
- [Overview](#overview)
|
|
8
|
-
- [Controllers](#controllers)
|
|
9
|
-
- [Events](#events)
|
|
10
|
-
- [Inheritance](#inheritance)
|
|
11
|
-
- [Conditional Code](#conditional-code)
|
|
12
|
-
- [Passing Arguments](#passing-arguments)
|
|
13
|
-
- [Global Namespace](#global-namespace)
|
|
14
|
-
- [Initializer File (alloy.js)](#initializer-file-alloyjs)
|
|
15
|
-
- [Library Code and CommonJS Modules](#library-code-and-commonjs-modules)
|
|
16
|
-
- [Specs Folder](#specs-folder)
|
|
17
|
-
- [Platform-Specific Library Folders](#platform-specific-library-folders)
|
|
18
|
-
- [Extending Alloy, Underscore.js and Backbone.js](#extending-alloy-underscorejs-and-backbonejs)
|
|
19
|
-
|
|
20
3
|
## Overview
|
|
21
4
|
|
|
22
5
|
This topic covers how to write controller code as well as other JavaScript files excluding models. Some traditional Titanium development is required, since Alloy controllers make direct calls to the Titanium SDK API to manipulate UI objects and access non-UI APIs.
|
|
@@ -132,8 +115,8 @@ The following are the constants defined by Alloy for use in the controller code:
|
|
|
132
115
|
* `ENV_DEV` : true if the current compiler target is built for development (running in the simulator or emulator)
|
|
133
116
|
* `ENV_TEST` : true if the current compiler target is built for testing on a device
|
|
134
117
|
* `ENV_PRODUCTION` : true if the current compiler target is built for production (running after a packaged installation)
|
|
135
|
-
* `DIST_ADHOC` (since Alloy 1.4.0) : true if the current compiler target is built for iOS Ad Hoc distribution
|
|
136
|
-
* `DIST_STORE` (since Alloy 1.4.0) : true if the current compiler target is built for deployment to the Google Play Store or iTunes App Store
|
|
118
|
+
* `DIST_ADHOC` (since Alloy 1.4.0) : true if the current compiler target is built for iOS Ad Hoc distribution, for example, if you set the `-T dist-adhoc` option when building with the Titanium CLI. Note that `ENV_PRODUCTION` will be true too since this deployment is only for production builds.
|
|
119
|
+
* `DIST_STORE` (since Alloy 1.4.0) : true if the current compiler target is built for deployment to the Google Play Store or iTunes App Store, for example, if you set the `-T dist-appstore` or `-T dist-playstore` option. Note that `ENV_PRODUCTION` will be true too since this deployment is only for production builds.
|
|
137
120
|
|
|
138
121
|
For example, since iOS devices do not include a back button, the application can conditionally add one to a window controller:
|
|
139
122
|
|