purgetss 7.2.7 → 7.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -46
- package/bin/purgetss +4 -4
- package/dist/fontawesome.tss +3 -3
- package/dist/purgetss.ui.js +10 -5
- package/dist/{tailwind.tss → utilities.tss} +5 -8
- package/experimental/completions2.js +7 -8
- package/lib/templates/create/index.js +5 -0
- package/lib/templates/create/index.xml +68 -0
- package/lib/templates/fontawesome/beta-reset.tss +3 -3
- package/lib/templates/fontawesome/free-reset.tss +3 -3
- package/lib/templates/fontawesome/pro-reset.tss +3 -3
- package/lib/templates/purgetss.ui.js.cjs +9 -4
- package/lib/templates/tailwind/custom-template.tss +1 -2
- package/package.json +2 -2
- package/src/cli/commands/create.js +31 -3
- package/src/cli/commands/dependencies.js +1 -1
- package/src/cli/commands/init.js +1 -1
- package/src/cli/commands/purge.js +139 -5
- package/src/core/builders/tailwind-builder.js +2 -2
- package/src/core/purger/tailwind-purger.js +6 -6
- package/src/dev/builders/tailwind-builder.js +3 -3
- package/src/index.js +1 -1
- package/src/shared/constants.js +2 -2
- package/src/shared/helpers/animation.js +2 -2
- package/src/shared/helpers/media.js +2 -2
- package/src/shared/helpers/ui-properties.js +1 -1
package/README.md
CHANGED
|
@@ -10,80 +10,70 @@
|
|
|
10
10
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
**PurgeTSS** is a toolkit
|
|
13
|
+
**PurgeTSS** is a toolkit for building mobile apps with the [Titanium framework](https://titaniumsdk.com). It adds practical utilities to speed up styling and reduce repeated setup work.
|
|
14
14
|
|
|
15
|
-
It
|
|
15
|
+
It includes utility classes, icon font support, an Animation module, a simple grid system, and the `shades` command for generating custom colors.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
If you build UI-heavy screens, PurgeTSS helps you move faster without hand-writing long TSS files.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
## What's New in v7.
|
|
21
|
+
## What's New in v7.3.x
|
|
22
22
|
|
|
23
|
-
**
|
|
23
|
+
**File rename and improved error handling.** PurgeTSS v7.3 renames `tailwind.tss` to `utilities.tss` to reflect the project's standalone identity, and adds XML syntax validation to catch errors early.
|
|
24
24
|
|
|
25
|
-
###
|
|
25
|
+
### Breaking changes
|
|
26
26
|
|
|
27
|
-
- **
|
|
28
|
-
-
|
|
29
|
-
- `
|
|
30
|
-
- `build-legacy` (legacy Tailwind build removed)
|
|
31
|
-
- **Complete legacy mode removal**:
|
|
32
|
-
- All legacy-related code and conditional checks eliminated
|
|
33
|
-
- Legacy mode no longer supported anywhere in the codebase
|
|
27
|
+
- **File rename**: Output file is now `utilities.tss` instead of `tailwind.tss`
|
|
28
|
+
- Generated file: `purgetss/styles/utilities.tss` (was `purgetss/styles/tailwind.tss`)
|
|
29
|
+
- Distribution file: `dist/utilities.tss` (was `dist/tailwind.tss`)
|
|
34
30
|
|
|
35
|
-
###
|
|
31
|
+
### Major improvements
|
|
36
32
|
|
|
37
|
-
- **
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
- **Enhanced CLI Experience**: Reorganized commands into logical categories with improved error handling and intelligent command suggestions.
|
|
42
|
-
- **Titanium SDK 13.1 Support**: Updated definitions to support new properties in Titanium SDK 13.1.0.GA while maintaining full compatibility with previous SDK versions.
|
|
43
|
-
- **New Utility Classes**: Added support for properties like `navBarColor`, `forceBottomPosition`, and `multipleWindows` (available in latest SDKs).
|
|
33
|
+
- **XML syntax validation**: Catches common Alloy XML malformations before processing
|
|
34
|
+
- Detects missing opening `<` brackets (e.g., `Label id=` instead of `<Label id=`)
|
|
35
|
+
- Shows detailed error messages with line numbers, context preview, and fix suggestions
|
|
36
|
+
- Saves debugging time by catching errors early in the build process
|
|
44
37
|
|
|
45
|
-
|
|
38
|
+
- **Classic Titanium compatibility**: `deviceInfo()` function now works in both Alloy and Classic projects
|
|
39
|
+
- Removed dependency on `Alloy.isTablet`/`Alloy.isHandheld`
|
|
40
|
+
- Uses platform-based detection instead
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
- Automatically detects and handles both FontAwesome 6 and 7 formats.
|
|
49
|
-
- The `-f` flag now controls both font class names AND icon prefixes using filenames.
|
|
50
|
-
- **`tailwind init`**: Removed redundant flags for a cleaner initialization process.
|
|
51
|
-
- **`shades` command**: Improved precision in generating custom color shades.
|
|
52
|
-
- **CLI Categories**: Commands are now grouped by purpose: Setup, Development, Assets, Utilities, and Maintenance.
|
|
42
|
+
### Migration guide
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
If you have references to `tailwind.tss` in your project, update them to `utilities.tss`:
|
|
55
45
|
|
|
56
|
-
For most users, upgrading is seamless:
|
|
57
46
|
```bash
|
|
58
|
-
|
|
47
|
+
# Update any custom scripts or paths
|
|
48
|
+
# From: purgetss/styles/tailwind.tss
|
|
49
|
+
# To: purgetss/styles/utilities.tss
|
|
59
50
|
```
|
|
60
51
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **Clean reinstall**: If you experience issues, try a clean reinstall: `npm uninstall -g purgetss && npm install -g purgetss`.
|
|
52
|
+
For most users, upgrading is straightforward:
|
|
53
|
+
```bash
|
|
54
|
+
npm install -g purgetss@latest
|
|
55
|
+
```
|
|
66
56
|
|
|
67
57
|
---
|
|
68
58
|
|
|
69
59
|
Here are its main functionalities:
|
|
70
60
|
|
|
71
|
-
- **
|
|
72
|
-
- **Efficient
|
|
73
|
-
- **Customization and JIT
|
|
74
|
-
- **Icon
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
- **Animation
|
|
78
|
-
- **Grid
|
|
61
|
+
- **Utility-First Classes**: PurgeTSS ships with 21,000+ utility classes, so you get a lot of styling options out of the box.
|
|
62
|
+
- **Efficient style management**: It parses all XML files to create a clean `app.tss` containing only the classes used in your project, reducing size and improving performance.
|
|
63
|
+
- **Customization and JIT classes**: You can customize default classes via a config file and use JIT classes for arbitrary values inside views.
|
|
64
|
+
- **Icon fonts integration**: Use icon fonts such as Font Awesome, Material Icons, Material Symbols, and Framework7-Icons in Buttons and Labels.
|
|
65
|
+
- **`fonts.tss` generation**: The `build-fonts` command creates a `fonts.tss` file with class definitions and fontFamily selectors for regular and icon fonts, with simplified options for filenames and icon prefixes.
|
|
66
|
+
- **`shades` command**: Generate custom color shades from a hex color without external tools.
|
|
67
|
+
- **Animation module**: Apply basic 2D matrix animations or transformations to elements or arrays of elements.
|
|
68
|
+
- **Grid system**: A two-dimensional grid system to align and distribute elements within views.
|
|
79
69
|
|
|
80
|
-
|
|
70
|
+
In short, PurgeTSS keeps styling consistent and removes a lot of repetitive UI setup work.
|
|
81
71
|
|
|
82
72
|
### Visit the official documentation site at [purgetss.com](https://purgetss.com) to learn more.
|
|
83
73
|
|
|
84
74
|
## Requirements
|
|
85
75
|
|
|
86
|
-
- **Titanium SDK** (Compatible with all versions; 13.1.
|
|
76
|
+
- **Titanium SDK** (Compatible with all versions; 13.1.1.GA recommended for full property support)
|
|
87
77
|
- **Alloy Framework** (for most commands)
|
|
88
78
|
- **Node.js 20+** (required for the CLI tool)
|
|
89
79
|
|
package/bin/purgetss
CHANGED
|
@@ -115,7 +115,7 @@ program.helpInformation = function () {
|
|
|
115
115
|
output.push(` ${chalk.cyan('install-dependencies|id')} Install ${chalk.green('ESLint')} and ${chalk.green('Tailwind CSS')}`)
|
|
116
116
|
output.push('')
|
|
117
117
|
output.push(` ${chalk.green('Daily Development:')}`)
|
|
118
|
-
output.push(` ${chalk.cyan('build|b')} ${chalk.gray('[options]')} Generate ${chalk.yellow('
|
|
118
|
+
output.push(` ${chalk.cyan('build|b')} ${chalk.gray('[options]')} Generate ${chalk.yellow('utilities.tss')} file`)
|
|
119
119
|
output.push(` ${chalk.cyan('watch|w')} ${chalk.gray('[options]')} Auto-run ${chalk.green('PurgeTSS')} on project compilation`)
|
|
120
120
|
output.push(` ${chalk.cyan('module|m')} Copy ${chalk.yellow('purgetss.ui.js')} module to your ${chalk.yellow('lib')} folder`)
|
|
121
121
|
output.push('')
|
|
@@ -254,8 +254,8 @@ program
|
|
|
254
254
|
program
|
|
255
255
|
.command('build')
|
|
256
256
|
.alias('b')
|
|
257
|
-
.description(`Generate ${chalk.yellow('
|
|
258
|
-
.addHelpText('after', `\nGenerates ${chalk.yellow('
|
|
257
|
+
.description(`Generate ${chalk.yellow('utilities.tss')} file`)
|
|
258
|
+
.addHelpText('after', `\nGenerates ${chalk.yellow('utilities.tss')} file based on attributes in ${chalk.yellow('./purgetss/config.cjs')}\nAlso generates custom ${chalk.yellow('fontawesome.tss')} file if FontAwesome Beta/Pro is installed`)
|
|
259
259
|
.option('--glossary', 'Create a glossary folder with all generated classes')
|
|
260
260
|
.action(async (options) => {
|
|
261
261
|
try {
|
|
@@ -378,7 +378,7 @@ program
|
|
|
378
378
|
.option('-s, --single', 'Generate a single color definition')
|
|
379
379
|
.option('-l, --log', 'Log shades instead of saving them')
|
|
380
380
|
.option('-j, --json', `Log shades in ${chalk.yellow('app/config.json')} format`)
|
|
381
|
-
.option('-t, --tailwind', `Log shades in ${chalk.yellow('
|
|
381
|
+
.option('-t, --tailwind', `Log shades in ${chalk.yellow('utilities.tss.config.js')} format`)
|
|
382
382
|
.action(async (hexcode, name, options) => {
|
|
383
383
|
try {
|
|
384
384
|
const result = await shades({ hexcode, name }, options)
|
package/dist/fontawesome.tss
CHANGED
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
'.fa':{ font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
8
8
|
'.fas': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
9
9
|
'.far': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
10
|
-
'.fab': { font: { fontFamily: '
|
|
10
|
+
'.fab': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
11
11
|
|
|
12
12
|
'.fa-solid': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
13
13
|
'.fa-regular': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
14
|
-
'.fa-brands': { font: { fontFamily: '
|
|
14
|
+
'.fa-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
15
15
|
|
|
16
16
|
'.fontawesome': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
17
17
|
'.fontawesome-solid': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
18
18
|
'.fontawesome-regular': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
19
|
-
'.fontawesome-brands': { font: { fontFamily: '
|
|
19
|
+
'.fontawesome-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
20
20
|
|
|
21
21
|
// Font Sizes
|
|
22
22
|
'.fa-lg': { font: { fontSize: 21 } }
|
package/dist/purgetss.ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// PurgeTSS v7.
|
|
1
|
+
// PurgeTSS v7.3.0
|
|
2
2
|
// Created by César Estrada
|
|
3
3
|
// https://purgetss.com
|
|
4
4
|
|
|
@@ -388,19 +388,24 @@ function deviceInfo() {
|
|
|
388
388
|
console.warn('------------------- DEVICE INFO -------------------')
|
|
389
389
|
const platform = Ti.Platform
|
|
390
390
|
const displayCaps = platform.displayCaps
|
|
391
|
+
|
|
392
|
+
// Classic-compatible detection (no Alloy dependency)
|
|
393
|
+
const isTablet = platform.osname === 'ipad'
|
|
394
|
+
const isHandheld = ['iphone', 'android'].includes(platform.osname) && !isTablet
|
|
395
|
+
|
|
391
396
|
console.warn(`
|
|
392
397
|
version: ${platform.version}
|
|
393
398
|
name: ${platform.name}
|
|
394
|
-
|
|
399
|
+
isTablet: ${isTablet}
|
|
400
|
+
isHandheld: ${isHandheld}
|
|
401
|
+
model: ${platform.model}
|
|
395
402
|
locale: ${platform.locale}
|
|
396
403
|
osname: ${platform.osname}
|
|
397
404
|
ostype: ${platform.ostype}
|
|
398
|
-
|
|
405
|
+
username: ${platform.username}
|
|
399
406
|
manufacturer: ${platform.manufacturer}
|
|
400
407
|
architecture: ${platform.architecture}
|
|
401
408
|
availableMemory: ${platform.availableMemory}
|
|
402
|
-
isTablet: ${Alloy.isTablet}
|
|
403
|
-
isHandheld: ${Alloy.isHandheld}
|
|
404
409
|
Ti.Platform.displayCaps.dpi: ${displayCaps.dpi}
|
|
405
410
|
Ti.Platform.displayCaps.density: ${displayCaps.density}
|
|
406
411
|
Ti.Platform.displayCaps.platformWidth: ${displayCaps.platformWidth}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Created by Adam Wathan ( https://twitter.com/adamwathan ).
|
|
3
|
-
|
|
4
|
-
// Tailwind-like styles
|
|
1
|
+
// Utility classes for Titanium
|
|
5
2
|
// Generated with PurgeTSS
|
|
6
3
|
// https://purgetss.com
|
|
7
4
|
// default config.js file
|
|
@@ -1468,7 +1465,7 @@
|
|
|
1468
1465
|
'.drag-apply': { draggingType: 'apply' }
|
|
1469
1466
|
'.drag-animate': { draggingType: 'animate' }
|
|
1470
1467
|
|
|
1471
|
-
// Property(ies): shadowOffset, shadowRadius, shadowColor
|
|
1468
|
+
// Property(ies): shadowOffset, shadowRadius, shadowColor
|
|
1472
1469
|
// Component(s): Ti.UI.Button, Ti.UI.Label
|
|
1473
1470
|
'.drop-shadow-xs': { shadowOffset: { x: 0, y: 0 }, shadowRadius: 1, shadowColor: '#80000000' }
|
|
1474
1471
|
'.drop-shadow-sm': { shadowOffset: { x: 0, y: 1 }, shadowRadius: 2, shadowColor: '#80000000' }
|
|
@@ -1676,7 +1673,7 @@
|
|
|
1676
1673
|
|
|
1677
1674
|
// Ti.Media
|
|
1678
1675
|
// Property(ies): scalingMode - ( Alternative )
|
|
1679
|
-
// Description: Background Size for compatibility
|
|
1676
|
+
// Description: Background Size for compatibility
|
|
1680
1677
|
// Component(s): Ti.UI.ImageView
|
|
1681
1678
|
'.bg-auto': { scalingMode: Ti.Media.IMAGE_SCALING_AUTO }
|
|
1682
1679
|
'.bg-fill': { scalingMode: Ti.Media.IMAGE_SCALING_FILL }
|
|
@@ -1685,7 +1682,7 @@
|
|
|
1685
1682
|
'.bg-contain': { scalingMode: Ti.Media.IMAGE_SCALING_ASPECT_FIT }
|
|
1686
1683
|
|
|
1687
1684
|
// Property(ies): scalingMode - ( Alternative )
|
|
1688
|
-
// Description: Object Fit for compatibility
|
|
1685
|
+
// Description: Object Fit for compatibility
|
|
1689
1686
|
// Component(s): Ti.UI.ImageView
|
|
1690
1687
|
'.object-auto': { scalingMode: Ti.Media.IMAGE_SCALING_AUTO }
|
|
1691
1688
|
'.object-fill': { scalingMode: Ti.Media.IMAGE_SCALING_FILL }
|
|
@@ -1715,7 +1712,7 @@
|
|
|
1715
1712
|
'.pointer-events-auto': { touchEnabled: true }
|
|
1716
1713
|
'.pointer-events-none': { touchEnabled: false }
|
|
1717
1714
|
|
|
1718
|
-
// Property(ies): iOS: viewShadowOffset, viewShadowRadius, viewShadowColor, Android: elevation
|
|
1715
|
+
// Property(ies): iOS: viewShadowOffset, viewShadowRadius, viewShadowColor, Android: elevation
|
|
1719
1716
|
// Component(s): iOS: Ti.UI.View, Android: Ti.UI.Android.CardView, Ti.UI.Animation, Ti.UI.View
|
|
1720
1717
|
'.shadow-xs': { viewShadowOffset: { x: 0, y: 0 }, viewShadowRadius: 1, viewShadowColor: '#80000000', elevation: 4 }
|
|
1721
1718
|
'.shadow-sm': { viewShadowOffset: { x: 0, y: 1 }, viewShadowRadius: 2, viewShadowColor: '#80000000', elevation: 8 }
|
|
@@ -43,7 +43,7 @@ if (configOptions) {
|
|
|
43
43
|
configOptions.widgets = configOptions.widgets ?? false
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
function
|
|
46
|
+
function autoBuildUtilitiesTSS(options = {}) {
|
|
47
47
|
// Refresh config at the start of the function to ensure it's up-to-date
|
|
48
48
|
configFile = getConfigFile()
|
|
49
49
|
configFile.purge = configFile.purge ?? { mode: 'all' }
|
|
@@ -59,8 +59,7 @@ function autoBuildTailwindTSS(options = {}) {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
saveGlossary = options.glossary ?? false
|
|
62
|
-
let tailwindStyles = fs.readFileSync(path.resolve(__dirname, '../lib/templates/tailwind/template.tss'), 'utf8')
|
|
63
|
-
tailwindStyles += fs.readFileSync(path.resolve(__dirname, '../lib/templates/tailwind/custom-template.tss'), 'utf8')
|
|
62
|
+
let tailwindStyles = fs.readFileSync(path.resolve(__dirname, '../lib/templates/tailwind/custom-template.tss'), 'utf8')
|
|
64
63
|
tailwindStyles += (fs.existsSync(projectsConfigJS)) ? `// config.js file updated on: ${getFileUpdatedDate(projectsConfigJS)}\n` : '// default config.js file\n'
|
|
65
64
|
|
|
66
65
|
const baseValues = combineDefaultThemeWithConfigFile()
|
|
@@ -76,14 +75,14 @@ function autoBuildTailwindTSS(options = {}) {
|
|
|
76
75
|
|
|
77
76
|
if (fs.existsSync(projectsConfigJS)) {
|
|
78
77
|
makeSureFolderExists(cwd + '/purgetss/styles/')
|
|
79
|
-
saveFile(cwd + '/purgetss/styles/
|
|
80
|
-
logger.file('./purgetss/styles/
|
|
78
|
+
saveFile(cwd + '/purgetss/styles/utilities.tss', tailwindStyles)
|
|
79
|
+
logger.file('./purgetss/styles/utilities.tss')
|
|
81
80
|
} else {
|
|
82
|
-
saveFile(path.resolve(__dirname, '../dist/
|
|
83
|
-
logger.file('./dist/
|
|
81
|
+
saveFile(path.resolve(__dirname, '../dist/utilities.tss'), tailwindStyles)
|
|
82
|
+
logger.file('./dist/utilities.tss')
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
|
-
export {
|
|
85
|
+
export { autoBuildUtilitiesTSS }
|
|
87
86
|
|
|
88
87
|
function processCustomClasses() {
|
|
89
88
|
let tailwindStyles = ''
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<Alloy>
|
|
2
|
+
<Window class="extend-safe-area-false bg-gradient-to-b from-purple-700 to-blue-800">
|
|
3
|
+
<ScrollView class="vertical mx-4">
|
|
4
|
+
<!-- Header -->
|
|
5
|
+
<Label class="text-center text-3xl font-bold text-white">Welcome to PurgeTSS</Label>
|
|
6
|
+
<Label class="text-center text-sm text-white">Tailwind-inspired utility classes for Titanium/Alloy</Label>
|
|
7
|
+
|
|
8
|
+
<!-- Typography Examples -->
|
|
9
|
+
<Label class="mt-4 text-center text-xl font-semibold text-white">Typography</Label>
|
|
10
|
+
|
|
11
|
+
<Label class="m-2 h-auto text-center text-lg font-bold text-purple-400">Heading Text</Label>
|
|
12
|
+
<Label class="mx-2 text-center text-sm text-gray-300">Body text with normal weight</Label>
|
|
13
|
+
<Label class="m-2 h-auto text-center text-xs italic text-green-400">Small italic text</Label>
|
|
14
|
+
|
|
15
|
+
<!-- Color Examples -->
|
|
16
|
+
<Label class="mt-4 text-center text-xl font-semibold text-white">Colors</Label>
|
|
17
|
+
|
|
18
|
+
<View class="horizontal my-2">
|
|
19
|
+
<View class="wh-12 m-1 rounded bg-red-500" />
|
|
20
|
+
<View class="wh-12 m-1 rounded bg-orange-500" />
|
|
21
|
+
<View class="wh-12 m-1 rounded bg-amber-500" />
|
|
22
|
+
<View class="wh-12 m-1 rounded bg-yellow-500" />
|
|
23
|
+
<View class="wh-12 m-1 rounded bg-lime-500" />
|
|
24
|
+
<View class="wh-12 m-1 rounded bg-green-500" />
|
|
25
|
+
<View class="wh-12 m-1 rounded bg-emerald-500" />
|
|
26
|
+
<View class="wh-12 m-1 rounded bg-teal-500" />
|
|
27
|
+
<View class="wh-12 m-1 rounded bg-cyan-500" />
|
|
28
|
+
<View class="wh-12 m-1 rounded bg-sky-500" />
|
|
29
|
+
<View class="wh-12 m-1 rounded bg-blue-500" />
|
|
30
|
+
<View class="wh-12 m-1 rounded bg-indigo-500" />
|
|
31
|
+
<View class="wh-12 m-1 rounded bg-violet-500" />
|
|
32
|
+
<View class="wh-12 m-1 rounded bg-purple-500" />
|
|
33
|
+
<View class="wh-12 m-1 rounded bg-fuchsia-500" />
|
|
34
|
+
<View class="wh-12 m-1 rounded bg-pink-500" />
|
|
35
|
+
<View class="wh-12 m-1 rounded bg-rose-500" />
|
|
36
|
+
<View class="wh-12 bg-brand-500 m-1 rounded" />
|
|
37
|
+
</View>
|
|
38
|
+
|
|
39
|
+
<!-- Layout Examples -->
|
|
40
|
+
<Label class="mt-4 text-center text-xl font-semibold text-white">Layouts</Label>
|
|
41
|
+
|
|
42
|
+
<Label class="mt-2 text-center text-xs text-gray-400">Horizontal layout</Label>
|
|
43
|
+
<View class="horizontal">
|
|
44
|
+
<View class="wh-12 m-1 rounded bg-red-500" />
|
|
45
|
+
<View class="wh-12 m-1 rounded bg-green-500" />
|
|
46
|
+
<View class="wh-12 m-1 rounded bg-blue-500" />
|
|
47
|
+
</View>
|
|
48
|
+
|
|
49
|
+
<Label class="mt-2 text-center text-xs text-gray-400">Vertical layout</Label>
|
|
50
|
+
<View class="vertical mb-2">
|
|
51
|
+
<View class="wh-12 m-1 rounded bg-yellow-500" />
|
|
52
|
+
<View class="wh-12 m-1 rounded bg-pink-500" />
|
|
53
|
+
</View>
|
|
54
|
+
|
|
55
|
+
<!-- Border & Radius Examples -->
|
|
56
|
+
<Label class="mt-4 text-center text-xl font-semibold text-white">Borders & Radius</Label>
|
|
57
|
+
|
|
58
|
+
<View class="horizontal mt-2">
|
|
59
|
+
<View class="wh-14 m-1 rounded border-2 border-white bg-black/30" />
|
|
60
|
+
<View class="rounded-full-14 m-1 border-2 border-blue-500 bg-black/30" />
|
|
61
|
+
<View class="wh-14 m-1 rounded-lg border-2 border-purple-500 bg-black/30" />
|
|
62
|
+
</View>
|
|
63
|
+
|
|
64
|
+
<!-- CTA Button -->
|
|
65
|
+
<Label class="mt-2 text-center text-xs text-blue-50">Open app/views/index.xml to customize this screen</Label>
|
|
66
|
+
</ScrollView>
|
|
67
|
+
</Window>
|
|
68
|
+
</Alloy>
|
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
'.fas': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
5
5
|
'.fal': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
6
6
|
'.far': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
7
|
-
'.fab': { font: { fontFamily: '
|
|
7
|
+
'.fab': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
8
8
|
|
|
9
9
|
'.fa-thin': { font: { fontFamily: 'FontAwesome6Pro-Thin' } }
|
|
10
10
|
'.fa-solid': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
11
11
|
'.fa-light': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
12
12
|
'.fa-regular': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
13
|
-
'.fa-brands': { font: { fontFamily: '
|
|
13
|
+
'.fa-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
14
14
|
|
|
15
15
|
'.fontawesome': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
16
16
|
'.fontawesome-thin': { font: { fontFamily: 'FontAwesome6Pro-Thin' } }
|
|
17
17
|
'.fontawesome-solid': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
18
18
|
'.fontawesome-light': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
19
19
|
'.fontawesome-regular': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
20
|
-
'.fontawesome-brands': { font: { fontFamily: '
|
|
20
|
+
'.fontawesome-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
21
21
|
|
|
22
22
|
// Font Sizes
|
|
23
23
|
'.fa-1x': { font: { fontSize: 16 } }
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
'.fa':{ font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
3
3
|
'.fas': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
4
4
|
'.far': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
5
|
-
'.fab': { font: { fontFamily: '
|
|
5
|
+
'.fab': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
6
6
|
|
|
7
7
|
'.fa-solid': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
8
8
|
'.fa-regular': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
9
|
-
'.fa-brands': { font: { fontFamily: '
|
|
9
|
+
'.fa-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
10
10
|
|
|
11
11
|
'.fontawesome': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
12
12
|
'.fontawesome-solid': { font: { fontFamily: 'FontAwesome7Free-Solid' } }
|
|
13
13
|
'.fontawesome-regular': { font: { fontFamily: 'FontAwesome7Free-Regular' } }
|
|
14
|
-
'.fontawesome-brands': { font: { fontFamily: '
|
|
14
|
+
'.fontawesome-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
15
15
|
|
|
16
16
|
// Font Sizes
|
|
17
17
|
'.fa-lg': { font: { fontSize: 21 } }
|
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
'.fas': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
5
5
|
'.fal': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
6
6
|
'.far': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
7
|
-
'.fab': { font: { fontFamily: '
|
|
7
|
+
'.fab': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
8
8
|
|
|
9
9
|
'.fa-thin': { font: { fontFamily: 'FontAwesome6Pro-Thin' } }
|
|
10
10
|
'.fa-solid': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
11
11
|
'.fa-light': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
12
12
|
'.fa-regular': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
13
|
-
'.fa-brands': { font: { fontFamily: '
|
|
13
|
+
'.fa-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
14
14
|
|
|
15
15
|
'.fontawesome': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
16
16
|
'.fontawesome-thin': { font: { fontFamily: 'FontAwesome6Pro-Thin' } }
|
|
17
17
|
'.fontawesome-solid': { font: { fontFamily: 'FontAwesome6Pro-Solid' } }
|
|
18
18
|
'.fontawesome-light': { font: { fontFamily: 'FontAwesome6Pro-Light' } }
|
|
19
19
|
'.fontawesome-regular': { font: { fontFamily: 'FontAwesome6Pro-Regular' } }
|
|
20
|
-
'.fontawesome-brands': { font: { fontFamily: '
|
|
20
|
+
'.fontawesome-brands': { font: { fontFamily: 'FontAwesome7Brands-Regular' } }
|
|
21
21
|
|
|
22
22
|
// Font Sizes
|
|
23
23
|
'.fa-lg': { font: { fontSize: 21 } }
|
|
@@ -387,19 +387,24 @@ function deviceInfo() {
|
|
|
387
387
|
console.warn('------------------- DEVICE INFO -------------------')
|
|
388
388
|
const platform = Ti.Platform
|
|
389
389
|
const displayCaps = platform.displayCaps
|
|
390
|
+
|
|
391
|
+
// Classic-compatible detection (no Alloy dependency)
|
|
392
|
+
const isTablet = platform.osname === 'ipad'
|
|
393
|
+
const isHandheld = ['iphone', 'android'].includes(platform.osname) && !isTablet
|
|
394
|
+
|
|
390
395
|
console.warn(`
|
|
391
396
|
version: ${platform.version}
|
|
392
397
|
name: ${platform.name}
|
|
393
|
-
|
|
398
|
+
isTablet: ${isTablet}
|
|
399
|
+
isHandheld: ${isHandheld}
|
|
400
|
+
model: ${platform.model}
|
|
394
401
|
locale: ${platform.locale}
|
|
395
402
|
osname: ${platform.osname}
|
|
396
403
|
ostype: ${platform.ostype}
|
|
397
|
-
|
|
404
|
+
username: ${platform.username}
|
|
398
405
|
manufacturer: ${platform.manufacturer}
|
|
399
406
|
architecture: ${platform.architecture}
|
|
400
407
|
availableMemory: ${platform.availableMemory}
|
|
401
|
-
isTablet: ${Alloy.isTablet}
|
|
402
|
-
isHandheld: ${Alloy.isHandheld}
|
|
403
408
|
Ti.Platform.displayCaps.dpi: ${displayCaps.dpi}
|
|
404
409
|
Ti.Platform.displayCaps.density: ${displayCaps.density}
|
|
405
410
|
Ti.Platform.displayCaps.platformWidth: ${displayCaps.platformWidth}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "purgetss",
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.3.1",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"purgetss": "bin/purgetss"
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"keywords": [
|
|
58
58
|
"Appcelerator",
|
|
59
59
|
"Titanium",
|
|
60
|
-
"
|
|
60
|
+
"utilities.tss",
|
|
61
61
|
"fontawesome.tss",
|
|
62
62
|
"cli"
|
|
63
63
|
],
|
|
@@ -27,7 +27,7 @@ import { start, finish } from '../utils/cli-helpers.js'
|
|
|
27
27
|
*/
|
|
28
28
|
function robustDelete(folderPath, callback) {
|
|
29
29
|
const deleteCommand = `chown -R $USER "${folderPath}" 2>/dev/null; rm -rf "${folderPath}"`
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
exec(deleteCommand, (error) => {
|
|
32
32
|
if (error) {
|
|
33
33
|
// Retry once after a brief delay for stubborn node_modules
|
|
@@ -64,6 +64,31 @@ function createProject(workspace, argsName, projectID, options) {
|
|
|
64
64
|
execSync(`ti create -n ${projectName} -t app -p all --alloy --no-prompt --id ${projectID}`)
|
|
65
65
|
execSync(`cd ${projectDirectory} && purgetss w && purgetss b`)
|
|
66
66
|
|
|
67
|
+
// Remove default index.tss file (not needed with PurgeTSS - app.tss is auto-generated)
|
|
68
|
+
// Use argsName instead of projectName because projectName includes quotes for shell commands
|
|
69
|
+
const indexTssPath = `${workspace}/${argsName}/app/styles/index.tss`
|
|
70
|
+
|
|
71
|
+
if (fs.existsSync(indexTssPath)) {
|
|
72
|
+
try {
|
|
73
|
+
fs.unlinkSync(indexTssPath)
|
|
74
|
+
} catch (error) {
|
|
75
|
+
logger.error(`Failed to remove index.tss: ${error.message}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Copy PurgeTSS welcome screen (index.xml and index.js)
|
|
80
|
+
const templatesDir = path.resolve(projectRoot, 'lib/templates/create')
|
|
81
|
+
const viewsDir = `${workspace}/${argsName}/app/views`
|
|
82
|
+
const controllersDir = `${workspace}/${argsName}/app/controllers`
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
fs.copyFileSync(`${templatesDir}/index.xml`, `${viewsDir}/index.xml`)
|
|
86
|
+
fs.copyFileSync(`${templatesDir}/index.js`, `${controllersDir}/index.js`)
|
|
87
|
+
logger.info('PurgeTSS welcome screen installed')
|
|
88
|
+
} catch (error) {
|
|
89
|
+
logger.error(`Failed to copy PurgeTSS templates: ${error.message}`)
|
|
90
|
+
}
|
|
91
|
+
|
|
67
92
|
if (options.vendor) {
|
|
68
93
|
logger.info('Installing Fonts')
|
|
69
94
|
execSync(`cd ${projectDirectory} && purgetss il -m -v=${options.vendor}`)
|
|
@@ -148,6 +173,9 @@ export function create(args, options) {
|
|
|
148
173
|
console.log('')
|
|
149
174
|
logger.warn(chalk.yellow('Project creation has been canceled!'))
|
|
150
175
|
}
|
|
176
|
+
return null
|
|
177
|
+
}).catch(error => {
|
|
178
|
+
logger.error(error)
|
|
151
179
|
})
|
|
152
180
|
}
|
|
153
181
|
} else {
|
|
@@ -159,8 +187,8 @@ export function create(args, options) {
|
|
|
159
187
|
logger.info('You must have', chalk.green('`app.idprefix`'), 'and', chalk.green('`app.workspace`'), 'configured to create a project with', chalk.green('`PurgeTSS`'))
|
|
160
188
|
console.log('')
|
|
161
189
|
logger.info('Please, set them like this:')
|
|
162
|
-
logger.info(chalk.green('ti config app.idprefix'), chalk.yellow(
|
|
163
|
-
logger.info(chalk.green('ti config app.workspace'), chalk.yellow(
|
|
190
|
+
logger.info(chalk.green('ti config app.idprefix'), chalk.yellow(`'com.your.reverse.domain'`))
|
|
191
|
+
logger.info(chalk.green('ti config app.workspace'), chalk.yellow(`'path/to/your/workspace'`))
|
|
164
192
|
}
|
|
165
193
|
})
|
|
166
194
|
}
|
|
@@ -59,7 +59,7 @@ export function dependencies(options) {
|
|
|
59
59
|
|
|
60
60
|
// Install Tailwind CSS
|
|
61
61
|
logger.info(`Installing ${chalk.green('Tailwind CSS')}`)
|
|
62
|
-
execSync(`cd "${cwd}" && npm i -D tailwindcss && npx tailwindcss init`)
|
|
62
|
+
execSync(`cd "${cwd}" && npm i -D tailwindcss@3 && npx tailwindcss init`)
|
|
63
63
|
|
|
64
64
|
logger.info('The dependencies and config files have been installed successfully!')
|
|
65
65
|
|
package/src/cli/commands/init.js
CHANGED
|
@@ -177,7 +177,7 @@ export function init(options = {}) {
|
|
|
177
177
|
// Get commands when needed
|
|
178
178
|
const { methodCommand, oppositeCommand } = getCommands()
|
|
179
179
|
|
|
180
|
-
//
|
|
180
|
+
// utilities.tss
|
|
181
181
|
if (!fs.existsSync(projectsTailwind_TSS)) {
|
|
182
182
|
buildTailwindBasedOnConfigOptions(options)
|
|
183
183
|
}
|
|
@@ -123,6 +123,112 @@ function encodeHTML(str) {
|
|
|
123
123
|
return str.replace(/&/gm, i => code[i])
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Validate XML syntax before processing
|
|
128
|
+
* Returns true if valid, throws error if invalid
|
|
129
|
+
*/
|
|
130
|
+
function validateXML(xmlText, filePath) {
|
|
131
|
+
// Pre-validate: check for common Alloy XML malformations
|
|
132
|
+
// preValidateXML will throw a special error that should be caught at a higher level
|
|
133
|
+
const preValidationError = preValidateXML(xmlText, filePath)
|
|
134
|
+
if (preValidationError) {
|
|
135
|
+
throw preValidationError
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
convert.xml2json(encodeHTML(xmlText), { compact: true })
|
|
140
|
+
return true
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// Parse line/column from error message
|
|
143
|
+
const lineMatch = error.message.match(/Line:\s*(\d+)/)
|
|
144
|
+
const columnMatch = error.message.match(/Column:\s*(\d+)/)
|
|
145
|
+
const charMatch = error.message.match(/Char:\s*(.+)/)
|
|
146
|
+
|
|
147
|
+
let errorMessage = chalk.red(`\n::PurgeTSS:: XML Syntax Error\n`) +
|
|
148
|
+
chalk.yellow(`File: "${filePath}"\n`)
|
|
149
|
+
|
|
150
|
+
if (lineMatch || columnMatch) {
|
|
151
|
+
const lineNum = lineMatch ? parseInt(lineMatch[1]) : '?'
|
|
152
|
+
const colNum = columnMatch ? parseInt(columnMatch[1]) : '?'
|
|
153
|
+
const badChar = charMatch ? charMatch[1] : '?'
|
|
154
|
+
|
|
155
|
+
errorMessage += chalk.yellow(`Error near line: ${lineNum}\n\n`)
|
|
156
|
+
|
|
157
|
+
// Extract and show context: line before, error line, and line after
|
|
158
|
+
const lines = xmlText.split('\n')
|
|
159
|
+
const startLine = Math.max(0, lineNum - 2)
|
|
160
|
+
const endLine = Math.min(lines.length, lineNum + 2)
|
|
161
|
+
|
|
162
|
+
errorMessage += chalk.gray('Context:\n')
|
|
163
|
+
for (let i = startLine; i < endLine; i++) {
|
|
164
|
+
const lineNumDisplay = i + 1
|
|
165
|
+
const isTargetLine = (lineNumDisplay === lineNum)
|
|
166
|
+
const prefix = isTargetLine ? chalk.red('>>>') : chalk.gray(' ')
|
|
167
|
+
const lineContent = lines[i] || ''
|
|
168
|
+
|
|
169
|
+
errorMessage += `${prefix} ${chalk.gray(String(lineNumDisplay).padStart(3, ' '))}: ${lineContent}\n`
|
|
170
|
+
}
|
|
171
|
+
errorMessage += '\n'
|
|
172
|
+
|
|
173
|
+
errorMessage += chalk.red(`Error: Unmatched or malformed tag (missing < or >)\n`)
|
|
174
|
+
} else {
|
|
175
|
+
errorMessage += chalk.yellow(`Error details: ${error.message}\n`)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
errorMessage += chalk.gray('\nTip: Check for tags missing opening < or closing >\n')
|
|
179
|
+
|
|
180
|
+
throw new Error(errorMessage)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Pre-validate XML for common Alloy malformations
|
|
186
|
+
* Returns Error if problem found, null if OK
|
|
187
|
+
*/
|
|
188
|
+
function preValidateXML(xmlText, filePath) {
|
|
189
|
+
const lines = xmlText.split('\n')
|
|
190
|
+
|
|
191
|
+
// Check for tags without opening < (common mistake: Label, View, etc. without <)
|
|
192
|
+
for (let i = 0; i < lines.length; i++) {
|
|
193
|
+
const line = lines[i]
|
|
194
|
+
const trimmed = line.trim()
|
|
195
|
+
|
|
196
|
+
// Skip empty lines, comments, and closing tags
|
|
197
|
+
if (!trimmed || trimmed.startsWith('<!--') || trimmed.startsWith('</') || trimmed.startsWith('<Alloy') || trimmed.startsWith('</')) {
|
|
198
|
+
continue
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Check for line starting with uppercase letter followed by space and common Alloy attributes
|
|
202
|
+
// Pattern: "Label id=", "View class=","Button onClick=", etc. WITHOUT opening <
|
|
203
|
+
const tagWithoutOpening = trimmed.match(/^[A-Z][a-zA-Z0-9_]+\s+(id|class|onClick|onOpen|onClose|height|width|backgroundColor|color|font|text|hintText|imageUrl)=/)
|
|
204
|
+
|
|
205
|
+
if (tagWithoutOpening) {
|
|
206
|
+
const tagName = trimmed.split(/\s+|[>=]/)[0]
|
|
207
|
+
const relativePath = filePath.replace(process.cwd() + '/', '')
|
|
208
|
+
|
|
209
|
+
// Create a custom error with details for the caller to handle
|
|
210
|
+
const error = new Error(`XML Syntax Error in ${relativePath}:${i + 1}`)
|
|
211
|
+
error.isPreValidationError = true
|
|
212
|
+
error.filePath = relativePath
|
|
213
|
+
error.lineNumber = i + 1
|
|
214
|
+
error.lineContent = line.trim()
|
|
215
|
+
error.tagName = tagName
|
|
216
|
+
|
|
217
|
+
// Print error using logger (still throw, but caller can catch and handle)
|
|
218
|
+
logger.error('XML Syntax Error')
|
|
219
|
+
logger.warn(`File: "${relativePath}"`)
|
|
220
|
+
logger.warn(`Line: ${i + 1}`)
|
|
221
|
+
logger.warn(`Content: "${line.trim()}"`)
|
|
222
|
+
logger.warn(`Error: Tag "<${tagName}>" is missing opening "<"`)
|
|
223
|
+
logger.warn(`Fix: Change "${tagName}" to "<${tagName}>"`)
|
|
224
|
+
|
|
225
|
+
throw error
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return false
|
|
230
|
+
}
|
|
231
|
+
|
|
126
232
|
/**
|
|
127
233
|
* Extract classes from file content
|
|
128
234
|
* COPIED exactly from original extractClasses() function
|
|
@@ -131,7 +237,7 @@ function extractClasses(currentText, currentFile) {
|
|
|
131
237
|
try {
|
|
132
238
|
const jsontext = convert.xml2json(encodeHTML(currentText), { compact: true })
|
|
133
239
|
|
|
134
|
-
return traverse(JSON.parse(jsontext)).reduce(function(acc, value) {
|
|
240
|
+
return traverse(JSON.parse(jsontext)).reduce(function (acc, value) {
|
|
135
241
|
if (this.key === 'class' || this.key === 'id') acc.push(value.split(' '))
|
|
136
242
|
return acc
|
|
137
243
|
}, [])
|
|
@@ -246,7 +352,17 @@ function getUniqueClasses() {
|
|
|
246
352
|
const configFile = getConfigFile()
|
|
247
353
|
_.each(viewPaths, viewPath => {
|
|
248
354
|
const file = fs.readFileSync(viewPath, 'utf8')
|
|
249
|
-
if (file)
|
|
355
|
+
if (file) {
|
|
356
|
+
// Validate XML syntax first, regardless of mode
|
|
357
|
+
validateXML(file, viewPath)
|
|
358
|
+
|
|
359
|
+
// Then extract classes based on mode
|
|
360
|
+
if (configFile.purge.mode === 'all') {
|
|
361
|
+
allClasses.push(file.match(/[^<>"'`\s]*[^<>"'`\s:]/g))
|
|
362
|
+
} else {
|
|
363
|
+
allClasses.push(extractClasses(file, viewPath))
|
|
364
|
+
}
|
|
365
|
+
}
|
|
250
366
|
})
|
|
251
367
|
|
|
252
368
|
const controllerPaths = getControllerPaths()
|
|
@@ -315,7 +431,7 @@ function extractClassesOnly(currentText, currentFile) {
|
|
|
315
431
|
try {
|
|
316
432
|
const jsontext = convert.xml2json(encodeHTML(currentText), { compact: true })
|
|
317
433
|
|
|
318
|
-
return traverse(JSON.parse(jsontext)).reduce(function(acc, value) {
|
|
434
|
+
return traverse(JSON.parse(jsontext)).reduce(function (acc, value) {
|
|
319
435
|
if (this.key === 'class' || this.key === 'classes' || this.key === 'icon' || this.key === 'activeIcon') acc.push(value.split(' '))
|
|
320
436
|
return acc
|
|
321
437
|
}, [])
|
|
@@ -331,7 +447,12 @@ function extractClassesOnly(currentText, currentFile) {
|
|
|
331
447
|
function getClassesOnlyFromXMLFiles() {
|
|
332
448
|
const allClasses = []
|
|
333
449
|
const viewPaths = getViewPaths()
|
|
334
|
-
_.each(viewPaths, viewPath =>
|
|
450
|
+
_.each(viewPaths, viewPath => {
|
|
451
|
+
const file = fs.readFileSync(viewPath, 'utf8')
|
|
452
|
+
// Validate XML before processing
|
|
453
|
+
validateXML(file, viewPath)
|
|
454
|
+
allClasses.push(extractClassesOnly(file, viewPath))
|
|
455
|
+
})
|
|
335
456
|
|
|
336
457
|
const uniqueClasses = []
|
|
337
458
|
_.each(_.uniq(_.flattenDeep(allClasses)).sort(), uniqueClass => {
|
|
@@ -455,7 +576,20 @@ export function purgeClasses(options) {
|
|
|
455
576
|
|
|
456
577
|
backupOriginalAppTss()
|
|
457
578
|
|
|
458
|
-
|
|
579
|
+
let uniqueClasses
|
|
580
|
+
|
|
581
|
+
try {
|
|
582
|
+
uniqueClasses = getUniqueClasses()
|
|
583
|
+
} catch (error) {
|
|
584
|
+
// Handle pre-validation errors (XML syntax errors detected before parsing)
|
|
585
|
+
if (error.isPreValidationError) {
|
|
586
|
+
// Error already printed by preValidateXML, exit cleanly
|
|
587
|
+
// eslint-disable-next-line n/no-process-exit
|
|
588
|
+
process.exit(1)
|
|
589
|
+
}
|
|
590
|
+
// Re-throw other errors
|
|
591
|
+
throw error
|
|
592
|
+
}
|
|
459
593
|
|
|
460
594
|
let tempPurged = copyResetTemplateAnd_appTSS()
|
|
461
595
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
// Import functions from their new modular locations
|
|
10
10
|
import * as helpers from '../../shared/helpers.js'
|
|
11
|
-
import {
|
|
11
|
+
import { autoBuildUtilitiesTSS } from '../../../experimental/completions2.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Build Tailwind (AUTO mode using experimental completions engine)
|
|
@@ -16,7 +16,7 @@ import { autoBuildTailwindTSS } from '../../../experimental/completions2.js'
|
|
|
16
16
|
*/
|
|
17
17
|
export function buildTailwind(options) {
|
|
18
18
|
// Always modern mode in v7.1 - legacy removed completely
|
|
19
|
-
|
|
19
|
+
autoBuildUtilitiesTSS(options)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable camelcase */
|
|
2
2
|
/**
|
|
3
3
|
* PurgeTSS v7.1.0 - Core Purger: Tailwind
|
|
4
|
-
*
|
|
4
|
+
* utilities.tss purging engine - removes unused classes
|
|
5
5
|
*
|
|
6
6
|
* COPIED from src/index.js during refactorization - NO CHANGES to logic.
|
|
7
7
|
*
|
|
@@ -42,18 +42,18 @@ function cleanClassNameFn(className) {
|
|
|
42
42
|
* NO CHANGES to logic, preserving 100% of original functionality
|
|
43
43
|
*
|
|
44
44
|
* @param {Array} uniqueClasses - Array of unique class names found in XML files
|
|
45
|
-
* @returns {string} Purged
|
|
45
|
+
* @returns {string} Purged utilities.tss classes as string
|
|
46
46
|
*/
|
|
47
47
|
export function purgeTailwind(uniqueClasses, debug = false) {
|
|
48
48
|
if (debug) localStart()
|
|
49
49
|
|
|
50
|
-
logger.info('Purging', chalk.yellow('
|
|
50
|
+
logger.info('Purging', chalk.yellow('utilities.tss'), 'styles...')
|
|
51
51
|
|
|
52
52
|
let purgedClasses = ''
|
|
53
53
|
let tailwindClasses = fs.readFileSync(projectsTailwind_TSS, 'utf8').split(/\r?\n/)
|
|
54
54
|
|
|
55
|
-
if (`// config.js file updated on: ${getFileUpdatedDate(projectsConfigJS)}` !== tailwindClasses[
|
|
56
|
-
logger.info(chalk.yellow('config.js'), 'file changed!, rebuilding
|
|
55
|
+
if (`// config.js file updated on: ${getFileUpdatedDate(projectsConfigJS)}` !== tailwindClasses[3]) {
|
|
56
|
+
logger.info(chalk.yellow('config.js'), 'file changed!, rebuilding utilities.tss...')
|
|
57
57
|
checkIfColorModule()
|
|
58
58
|
buildTailwindBasedOnConfigOptions()
|
|
59
59
|
createDefinitionsFile()
|
|
@@ -211,7 +211,7 @@ export function purgeTailwind(uniqueClasses, debug = false) {
|
|
|
211
211
|
// Add arbitrary values
|
|
212
212
|
purgedClasses += (arbitraryValues !== '\n// Arbitrary Values\n') ? arbitraryValues : ''
|
|
213
213
|
|
|
214
|
-
if (debug) localFinish('Purging ' + chalk.yellow('
|
|
214
|
+
if (debug) localFinish('Purging ' + chalk.yellow('utilities.tss') + ' styles...')
|
|
215
215
|
|
|
216
216
|
return purgedClasses
|
|
217
217
|
}
|
|
@@ -4,20 +4,20 @@
|
|
|
4
4
|
* Builds Tailwind CSS files for development/distribution using auto-generation.
|
|
5
5
|
* COPIED from lib/build-tailwind.js - NO CHANGES to logic.
|
|
6
6
|
*
|
|
7
|
-
* Generates: ./dist/
|
|
7
|
+
* Generates: ./dist/utilities.tss
|
|
8
8
|
*
|
|
9
9
|
* @since 7.1.0 (refactored from lib/)
|
|
10
10
|
* @author César Estrada
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { autoBuildUtilitiesTSS } from '../../../experimental/completions2.js'
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Main builder function
|
|
17
17
|
* COPIED exactly from original constructor() function
|
|
18
18
|
*/
|
|
19
19
|
export function buildTailwind() {
|
|
20
|
-
|
|
20
|
+
autoBuildUtilitiesTSS()
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Execute if run directly
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All functionality is accessed through CLI commands:
|
|
6
6
|
*
|
|
7
7
|
* - purgetss (initialize and purge)
|
|
8
|
-
* - purgetss build (build
|
|
8
|
+
* - purgetss build (build utilities.tss)
|
|
9
9
|
* - purgetss build-fonts (build fonts)
|
|
10
10
|
* - purgetss module (install UI modules)
|
|
11
11
|
* - purgetss watch (setup auto-purging)
|
package/src/shared/constants.js
CHANGED
|
@@ -37,7 +37,7 @@ export const projectsFontAwesomeJS = `${cwd}/app/lib/fontawesome.js`
|
|
|
37
37
|
|
|
38
38
|
export const projectsPurgeTSSFolder = `${cwd}/purgetss`
|
|
39
39
|
export const projectsConfigJS = `${cwd}/purgetss/config.cjs`
|
|
40
|
-
export const projectsTailwind_TSS = `${cwd}/purgetss/styles/
|
|
40
|
+
export const projectsTailwind_TSS = `${cwd}/purgetss/styles/utilities.tss`
|
|
41
41
|
export const projectsPurge_TSS_Fonts_Folder = `${cwd}/purgetss/fonts`
|
|
42
42
|
export const projectsPurge_TSS_Styles_Folder = `${cwd}/purgetss/styles`
|
|
43
43
|
export const projectsFA_TSS_File = `${cwd}/purgetss/styles/fontawesome.tss`
|
|
@@ -57,7 +57,7 @@ export const srcLibF7 = path.resolve(projectRoot, './dist/framework7icons.js')
|
|
|
57
57
|
export const srcPurgeTSSLibrary = path.resolve(projectRoot, './dist/purgetss.ui.js')
|
|
58
58
|
|
|
59
59
|
// TSS Files (generated)
|
|
60
|
-
export const srcTailwindTSS = path.resolve(projectRoot, './dist/
|
|
60
|
+
export const srcTailwindTSS = path.resolve(projectRoot, './dist/utilities.tss')
|
|
61
61
|
export const srcFontAwesomeTSSFile = path.resolve(projectRoot, './dist/fontawesome.tss')
|
|
62
62
|
export const srcFramework7FontTSSFile = path.resolve(projectRoot, './dist/framework7icons.tss')
|
|
63
63
|
export const srcMaterialIconsTSSFile = path.resolve(projectRoot, './dist/materialicons.tss')
|
|
@@ -314,7 +314,7 @@ export function viewShadowAndroid() {
|
|
|
314
314
|
*/
|
|
315
315
|
export function viewShadowIos(shadowValue = '#80000000') {
|
|
316
316
|
let convertedStyles = processComments({
|
|
317
|
-
prop: 'viewShadowOffset, viewShadowRadius, viewShadowColor -
|
|
317
|
+
prop: 'viewShadowOffset, viewShadowRadius, viewShadowColor - iOS Only',
|
|
318
318
|
modules: 'Ti.UI.View'
|
|
319
319
|
})
|
|
320
320
|
|
|
@@ -504,7 +504,7 @@ export function activitySharedElementReturnTransition() {
|
|
|
504
504
|
}
|
|
505
505
|
export function viewShadowV6(shadowValue = '#80000000') {
|
|
506
506
|
let convertedStyles = processComments({
|
|
507
|
-
prop: 'iOS: viewShadowOffset, viewShadowRadius, viewShadowColor, Android: elevation
|
|
507
|
+
prop: 'iOS: viewShadowOffset, viewShadowRadius, viewShadowColor, Android: elevation',
|
|
508
508
|
modules: 'iOS: Ti.UI.View, Android: Ti.UI.Android.CardView, Ti.UI.Animation, Ti.UI.View'
|
|
509
509
|
})
|
|
510
510
|
|
|
@@ -627,7 +627,7 @@ export function tiMedia(legacy = true) {
|
|
|
627
627
|
convertedStyles += processProperties({
|
|
628
628
|
prop: 'scalingMode - ( Alternative )',
|
|
629
629
|
modules: 'Ti.UI.ImageView',
|
|
630
|
-
description: 'Background Size for compatibility
|
|
630
|
+
description: 'Background Size for compatibility'
|
|
631
631
|
}, {
|
|
632
632
|
bg: '{ scalingMode: {value} }'
|
|
633
633
|
}, {
|
|
@@ -643,7 +643,7 @@ export function tiMedia(legacy = true) {
|
|
|
643
643
|
convertedStyles += processProperties({
|
|
644
644
|
prop: 'scalingMode - ( Alternative )',
|
|
645
645
|
modules: 'Ti.UI.ImageView',
|
|
646
|
-
description: 'Object Fit for compatibility
|
|
646
|
+
description: 'Object Fit for compatibility'
|
|
647
647
|
}, {
|
|
648
648
|
object: '{ scalingMode: {value} }'
|
|
649
649
|
}, {
|
|
@@ -433,7 +433,7 @@ export function displayHomeAsUp() {
|
|
|
433
433
|
export function dropShadow() {
|
|
434
434
|
const shadowValue = '#80000000'
|
|
435
435
|
let convertedStyles = processComments({
|
|
436
|
-
prop: 'shadowOffset, shadowRadius, shadowColor
|
|
436
|
+
prop: 'shadowOffset, shadowRadius, shadowColor',
|
|
437
437
|
modules: 'Ti.UI.Button, Ti.UI.Label'
|
|
438
438
|
})
|
|
439
439
|
convertedStyles += `'.drop-shadow-xs': { shadowOffset: { x: 0, y: 0 }, shadowRadius: 1, shadowColor: '${shadowValue}' }\n`
|