@anydigital/11ty-bricks 1.0.0-alpha → 1.0.0-alpha.3
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 +56 -4
- package/package.json +10 -2
- package/src/cli/download-files.js +136 -0
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Import and use the entire plugin. You can configure which helpers to enable usin
|
|
|
21
21
|
import eleventyBricks from "@anydigital/11ty-bricks";
|
|
22
22
|
|
|
23
23
|
export default function(eleventyConfig) {
|
|
24
|
-
eleventyBricks
|
|
24
|
+
eleventyConfig.addPlugin(eleventyBricks, {
|
|
25
25
|
autoRaw: true // Enable autoRaw preprocessor (default: false)
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ export default function(eleventyConfig) {
|
|
|
34
34
|
const eleventyBricks = require("@anydigital/11ty-bricks");
|
|
35
35
|
|
|
36
36
|
module.exports = function(eleventyConfig) {
|
|
37
|
-
eleventyBricks
|
|
37
|
+
eleventyConfig.addPlugin(eleventyBricks, {
|
|
38
38
|
autoRaw: true // Enable autoRaw preprocessor (default: false)
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -78,12 +78,12 @@ When using the plugin (Option 1), you can configure which helpers to enable:
|
|
|
78
78
|
|
|
79
79
|
**Example:**
|
|
80
80
|
```javascript
|
|
81
|
-
eleventyBricks
|
|
81
|
+
eleventyConfig.addPlugin(eleventyBricks, {
|
|
82
82
|
autoRaw: true
|
|
83
83
|
});
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
## Available Helpers
|
|
86
|
+
## Available 11ty Helpers
|
|
87
87
|
|
|
88
88
|
### autoRaw
|
|
89
89
|
|
|
@@ -102,6 +102,58 @@ Use {{ variable }} to output variables.
|
|
|
102
102
|
|
|
103
103
|
Would try to process `{{ variable }}` as a template variable. With `autoRaw`, it displays exactly as written.
|
|
104
104
|
|
|
105
|
+
## CLI Helper Commands
|
|
106
|
+
|
|
107
|
+
After installing this package, the `download-files` command becomes available:
|
|
108
|
+
|
|
109
|
+
### download-files
|
|
110
|
+
|
|
111
|
+
A CLI command that downloads external files to your project based on URLs specified in your `package.json`.
|
|
112
|
+
|
|
113
|
+
**Usage:**
|
|
114
|
+
|
|
115
|
+
1. Add a `_downloadFiles` field to your project's `package.json` with URL-to-path mappings:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"_downloadFiles": {
|
|
120
|
+
"https://example.com/library.js": "src/vendor/library.js",
|
|
121
|
+
"https://cdn.example.com/styles.css": "public/css/external.css"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
2. Run the download command:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx download-files
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Options:**
|
|
133
|
+
|
|
134
|
+
- `-o, --output <dir>`: Specify an output directory where all files will be downloaded (relative paths in `_downloadFiles` will be resolved relative to this directory)
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Download all files to a specific directory
|
|
138
|
+
npx download-files --output public
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Features:**
|
|
142
|
+
|
|
143
|
+
- Downloads multiple files from external URLs
|
|
144
|
+
- Automatically creates directories if they don't exist
|
|
145
|
+
- Overwrites existing files
|
|
146
|
+
- Continues downloading remaining files even if some fail
|
|
147
|
+
- Provides clear progress and error messages
|
|
148
|
+
- Returns appropriate exit codes for CI/CD integration
|
|
149
|
+
|
|
150
|
+
**Use Cases:**
|
|
151
|
+
|
|
152
|
+
- Download third-party libraries and assets
|
|
153
|
+
- Fetch external resources during build processes
|
|
154
|
+
- Keep vendored files up to date
|
|
155
|
+
- Automate dependency downloads that aren't available via npm
|
|
156
|
+
|
|
105
157
|
## Requirements
|
|
106
158
|
|
|
107
159
|
- Node.js >= 18.0.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anydigital/11ty-bricks",
|
|
3
|
-
"version": "1.0.0-alpha",
|
|
3
|
+
"version": "1.0.0-alpha.3",
|
|
4
4
|
"description": "A collection of helpful utilities and filters for Eleventy (11ty)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -10,11 +10,15 @@
|
|
|
10
10
|
"require": "./src/index.cjs"
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"download-files": "./src/cli/download-files.js"
|
|
15
|
+
},
|
|
13
16
|
"files": [
|
|
14
17
|
"src"
|
|
15
18
|
],
|
|
16
19
|
"scripts": {
|
|
17
|
-
"test": "node --test src/**/*.test.js"
|
|
20
|
+
"test": "node --test src/**/*.test.js",
|
|
21
|
+
"test2": "npx download-files && npx download-files --output ~subtest"
|
|
18
22
|
},
|
|
19
23
|
"keywords": [
|
|
20
24
|
"11ty",
|
|
@@ -40,5 +44,9 @@
|
|
|
40
44
|
},
|
|
41
45
|
"engines": {
|
|
42
46
|
"node": ">=18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"_downloadFiles": {
|
|
49
|
+
"https://raw.githubusercontent.com/anydigital/11ty-bricks/refs/heads/main/README.md": "~README.md",
|
|
50
|
+
"https://raw.githubusercontent.com/anydigital/11ty-bricks/refs/heads/main/LICENSE": "~test/LICENSE"
|
|
43
51
|
}
|
|
44
52
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
4
|
+
import { dirname, resolve, join } from 'path';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parse command line arguments
|
|
8
|
+
*
|
|
9
|
+
* @returns {Object} Parsed arguments
|
|
10
|
+
*/
|
|
11
|
+
function parseArgs() {
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const parsed = {
|
|
14
|
+
outputDir: null
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
|
|
20
|
+
if (arg === '--output' || arg === '-o') {
|
|
21
|
+
if (i + 1 < args.length) {
|
|
22
|
+
parsed.outputDir = args[i + 1];
|
|
23
|
+
i++; // Skip next argument
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error(`${arg} requires a directory path`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Downloads files specified in package.json's _downloadFiles field
|
|
35
|
+
*
|
|
36
|
+
* @param {string|null} outputDir - Optional output directory to prepend to all paths
|
|
37
|
+
* @returns {Promise<boolean>} True if all downloads succeeded, false if any failed
|
|
38
|
+
*/
|
|
39
|
+
async function download(outputDir = null) {
|
|
40
|
+
try {
|
|
41
|
+
// Find and read package.json from the current working directory
|
|
42
|
+
const packageJsonPath = resolve(process.cwd(), 'package.json');
|
|
43
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
44
|
+
|
|
45
|
+
const downloadFiles = packageJson._downloadFiles;
|
|
46
|
+
|
|
47
|
+
if (!downloadFiles || typeof downloadFiles !== 'object') {
|
|
48
|
+
console.log('No _downloadFiles field found in package.json');
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const entries = Object.entries(downloadFiles);
|
|
53
|
+
|
|
54
|
+
if (entries.length === 0) {
|
|
55
|
+
console.log('No files to download (_downloadFiles is empty)');
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log(`Starting download of ${entries.length} file(s)...\n`);
|
|
60
|
+
|
|
61
|
+
let hasErrors = false;
|
|
62
|
+
|
|
63
|
+
// Process all downloads
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
const url = entry[0];
|
|
66
|
+
let localPath = entry[1];
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
console.log(`Downloading: ${url}`);
|
|
70
|
+
console.log(` To: ${localPath}`);
|
|
71
|
+
|
|
72
|
+
// Download the file
|
|
73
|
+
const response = await fetch(url);
|
|
74
|
+
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Get the file content
|
|
80
|
+
const content = await response.arrayBuffer();
|
|
81
|
+
const buffer = Buffer.from(content);
|
|
82
|
+
|
|
83
|
+
// Prepend output directory to local path if specified
|
|
84
|
+
if (outputDir) {
|
|
85
|
+
localPath = join(outputDir, localPath);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Resolve the full path
|
|
89
|
+
const fullPath = resolve(process.cwd(), localPath);
|
|
90
|
+
|
|
91
|
+
// Create directory if it doesn't exist
|
|
92
|
+
const dir = dirname(fullPath);
|
|
93
|
+
await mkdir(dir, { recursive: true });
|
|
94
|
+
|
|
95
|
+
// Write the file
|
|
96
|
+
await writeFile(fullPath, buffer);
|
|
97
|
+
|
|
98
|
+
console.log(` Success: ${localPath}\n`);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
hasErrors = true;
|
|
101
|
+
console.error(` Error: ${error.message}`);
|
|
102
|
+
console.error(` URL: ${url}\n`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Summary
|
|
107
|
+
if (hasErrors) {
|
|
108
|
+
console.log('Download completed with errors');
|
|
109
|
+
return false;
|
|
110
|
+
} else {
|
|
111
|
+
console.log('All downloads completed successfully');
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.error(`Fatal error: ${error.message}`);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* CLI entry point
|
|
123
|
+
*/
|
|
124
|
+
async function main() {
|
|
125
|
+
try {
|
|
126
|
+
const args = parseArgs();
|
|
127
|
+
const success = await download(args.outputDir);
|
|
128
|
+
process.exit(success ? 0 : 1);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(`Error: ${error.message}`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
|
136
|
+
|