portapack 0.3.1 → 0.3.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/.eslintrc.json +67 -8
- package/.releaserc.js +25 -27
- package/CHANGELOG.md +14 -22
- package/LICENSE.md +21 -0
- package/README.md +22 -53
- package/commitlint.config.js +30 -34
- package/dist/cli/cli-entry.cjs +183 -98
- package/dist/cli/cli-entry.cjs.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +178 -97
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.ts +38 -33
- package/docs/.vitepress/sidebar-generator.ts +89 -38
- package/docs/architecture.md +186 -0
- package/docs/cli.md +23 -23
- package/docs/code-of-conduct.md +7 -1
- package/docs/configuration.md +12 -11
- package/docs/contributing.md +6 -2
- package/docs/deployment.md +10 -5
- package/docs/development.md +8 -5
- package/docs/getting-started.md +13 -13
- package/docs/index.md +1 -1
- package/docs/public/android-chrome-192x192.png +0 -0
- package/docs/public/android-chrome-512x512.png +0 -0
- package/docs/public/apple-touch-icon.png +0 -0
- package/docs/public/favicon-16x16.png +0 -0
- package/docs/public/favicon-32x32.png +0 -0
- package/docs/public/favicon.ico +0 -0
- package/docs/roadmap.md +233 -0
- package/docs/site.webmanifest +1 -0
- package/docs/troubleshooting.md +12 -1
- package/examples/main.ts +5 -30
- package/examples/sample-project/script.js +1 -1
- package/jest.config.ts +8 -13
- package/nodemon.json +5 -10
- package/package.json +2 -5
- package/src/cli/cli-entry.ts +2 -2
- package/src/cli/cli.ts +21 -16
- package/src/cli/options.ts +127 -113
- package/src/core/bundler.ts +253 -222
- package/src/core/extractor.ts +632 -565
- package/src/core/minifier.ts +173 -162
- package/src/core/packer.ts +141 -137
- package/src/core/parser.ts +74 -73
- package/src/core/web-fetcher.ts +270 -258
- package/src/index.ts +18 -17
- package/src/types.ts +9 -11
- package/src/utils/font.ts +12 -6
- package/src/utils/logger.ts +110 -105
- package/src/utils/meta.ts +75 -76
- package/src/utils/mime.ts +50 -50
- package/src/utils/slugify.ts +33 -34
- package/tests/unit/cli/cli-entry.test.ts +72 -70
- package/tests/unit/cli/cli.test.ts +314 -278
- package/tests/unit/cli/options.test.ts +294 -301
- package/tests/unit/core/bundler.test.ts +426 -329
- package/tests/unit/core/extractor.test.ts +793 -549
- package/tests/unit/core/minifier.test.ts +374 -274
- package/tests/unit/core/packer.test.ts +298 -264
- package/tests/unit/core/parser.test.ts +538 -150
- package/tests/unit/core/web-fetcher.test.ts +389 -359
- package/tests/unit/index.test.ts +238 -197
- package/tests/unit/utils/font.test.ts +26 -21
- package/tests/unit/utils/logger.test.ts +267 -260
- package/tests/unit/utils/meta.test.ts +29 -28
- package/tests/unit/utils/mime.test.ts +73 -74
- package/tests/unit/utils/slugify.test.ts +14 -12
- package/tsconfig.build.json +9 -10
- package/tsconfig.jest.json +1 -1
- package/tsconfig.json +2 -2
- package/tsup.config.ts +8 -9
- package/typedoc.json +5 -9
- /package/docs/{portapack-transparent.png → public/portapack-transparent.png} +0 -0
- /package/docs/{portapack.jpg → public/portapack.jpg} +0 -0
@@ -1,5 +1,5 @@
|
|
1
|
-
import { defineConfig } from 'vitepress'
|
2
|
-
import { buildDocsSidebar } from './sidebar-generator'
|
1
|
+
import { defineConfig } from 'vitepress';
|
2
|
+
import { buildDocsSidebar } from './sidebar-generator';
|
3
3
|
|
4
4
|
export default defineConfig({
|
5
5
|
base: '/portapack/',
|
@@ -7,48 +7,53 @@ export default defineConfig({
|
|
7
7
|
description: 'Bundle & Minify HTML into a Single Portable File',
|
8
8
|
appearance: 'dark',
|
9
9
|
lastUpdated: true,
|
10
|
-
|
10
|
+
|
11
11
|
head: [
|
12
|
-
['link', { rel: 'icon', href: '/favicon.
|
12
|
+
['link', { rel: 'icon', href: '/portapack/favicon.ico' }],
|
13
13
|
['meta', { name: 'og:title', content: 'PortaPack' }],
|
14
|
-
[
|
15
|
-
|
16
|
-
|
14
|
+
[
|
15
|
+
'meta',
|
16
|
+
{ name: 'og:description', content: 'Bundle & Minify HTML into a Single Portable File' },
|
17
|
+
],
|
18
|
+
['meta', { name: 'og:image', content: '/portapack/portapack.jpg' }], // Updated to use your non-transparent logo
|
19
|
+
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
|
17
20
|
],
|
18
21
|
|
19
22
|
themeConfig: {
|
20
|
-
logo: '/
|
21
|
-
|
23
|
+
logo: '/portapack-transparent.png', // This path is relative to the public directory
|
24
|
+
|
22
25
|
socialLinks: [
|
23
26
|
{ icon: 'github', link: 'https://github.com/manicinc/portapack' },
|
24
27
|
{ icon: 'twitter', link: 'https://x.com/manicagency' },
|
25
28
|
{ icon: 'discord', link: 'https://discord.gg/DzNgXdYm' },
|
26
|
-
{
|
29
|
+
{
|
27
30
|
icon: {
|
28
|
-
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/></svg>'
|
29
|
-
},
|
30
|
-
link: 'https://www.linkedin.com/company/manic-agency-llc/'
|
31
|
-
}
|
31
|
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/></svg>',
|
32
|
+
},
|
33
|
+
link: 'https://www.linkedin.com/company/manic-agency-llc/',
|
34
|
+
},
|
32
35
|
],
|
33
36
|
|
34
37
|
footer: {
|
35
38
|
message: 'Released under the MIT License',
|
36
|
-
copyright: '© 2025 Manic Agency. All rights reserved.'
|
39
|
+
copyright: '© 2025 Manic Agency. All rights reserved.',
|
37
40
|
},
|
38
41
|
|
39
42
|
nav: [
|
40
43
|
{ text: 'Home', link: '/' },
|
41
44
|
{ text: 'Getting Started', link: '/getting-started' },
|
42
|
-
{
|
43
|
-
text: 'Docs',
|
45
|
+
{
|
46
|
+
text: 'Docs',
|
44
47
|
items: [
|
45
48
|
{ text: 'CLI Reference', link: '/cli' },
|
46
49
|
{ text: 'API', link: '/api/README' },
|
47
50
|
{ text: 'Configuration', link: '/configuration' },
|
48
|
-
{ text: 'Advanced Usage', link: '/advanced' }
|
49
|
-
]
|
51
|
+
{ text: 'Advanced Usage', link: '/advanced' },
|
52
|
+
],
|
50
53
|
},
|
51
|
-
{ text: 'Contributing', link: '/contributing' }
|
54
|
+
{ text: 'Contributing', link: '/contributing' },
|
55
|
+
{ text: 'Architecture', link: '/architecture'},
|
56
|
+
{ text: 'Roadmap', link: 'roadmap'}
|
52
57
|
],
|
53
58
|
|
54
59
|
sidebar: {
|
@@ -59,9 +64,9 @@ export default defineConfig({
|
|
59
64
|
items: [
|
60
65
|
{ text: 'Introduction', link: '/getting-started/' },
|
61
66
|
{ text: 'Installation', link: '/getting-started/installation' },
|
62
|
-
{ text: 'Quick Start', link: '/getting-started/quick-start' }
|
63
|
-
]
|
64
|
-
}
|
67
|
+
{ text: 'Quick Start', link: '/getting-started/quick-start' },
|
68
|
+
],
|
69
|
+
},
|
65
70
|
],
|
66
71
|
'/cli/': [
|
67
72
|
{
|
@@ -69,9 +74,9 @@ export default defineConfig({
|
|
69
74
|
items: [
|
70
75
|
{ text: 'Overview', link: '/cli/' },
|
71
76
|
{ text: 'Commands', link: '/cli/commands' },
|
72
|
-
{ text: 'Options', link: '/cli/options' }
|
73
|
-
]
|
74
|
-
}
|
77
|
+
{ text: 'Options', link: '/cli/options' },
|
78
|
+
],
|
79
|
+
},
|
75
80
|
],
|
76
81
|
'/configuration/': [
|
77
82
|
{
|
@@ -79,10 +84,10 @@ export default defineConfig({
|
|
79
84
|
items: [
|
80
85
|
{ text: 'Overview', link: '/configuration/' },
|
81
86
|
{ text: 'Options', link: '/configuration/options' },
|
82
|
-
{ text: 'Advanced', link: '/configuration/advanced' }
|
83
|
-
]
|
84
|
-
}
|
85
|
-
]
|
86
|
-
}
|
87
|
-
}
|
88
|
-
})
|
87
|
+
{ text: 'Advanced', link: '/configuration/advanced' },
|
88
|
+
],
|
89
|
+
},
|
90
|
+
],
|
91
|
+
},
|
92
|
+
},
|
93
|
+
});
|
@@ -1,5 +1,6 @@
|
|
1
|
-
import { glob } from 'glob'
|
2
|
-
import path from 'path'
|
1
|
+
import { glob } from 'glob';
|
2
|
+
import path from 'path';
|
3
|
+
import { fileURLToPath } from 'url'; // Needed for ESM __dirname equivalent
|
3
4
|
|
4
5
|
/**
|
5
6
|
* Sidebar item interface for VitePress configuration
|
@@ -11,63 +12,113 @@ export interface SidebarItem {
|
|
11
12
|
collapsed?: boolean;
|
12
13
|
}
|
13
14
|
|
15
|
+
// --- Helper to get the directory name in ES Modules ---
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
17
|
+
const __dirname = path.dirname(__filename);
|
18
|
+
// --- Assuming sidebar-generator.ts is directly inside 'docs' ---
|
19
|
+
// If it's deeper, adjust accordingly (e.g., path.resolve(__dirname, '..'))
|
20
|
+
const docsDir = __dirname;
|
21
|
+
const apiDir = path.join(docsDir, 'api'); // Absolute path to the api directory
|
22
|
+
|
14
23
|
/**
|
15
24
|
* Automatically builds sidebar from generated TypeDoc files
|
16
25
|
* @returns Dynamically generated sidebar configuration
|
17
26
|
*/
|
18
27
|
export function buildDocsSidebar(): SidebarItem[] {
|
19
28
|
try {
|
29
|
+
// Log the directory being scanned
|
30
|
+
console.log(`Scanning for markdown files in: ${apiDir}`);
|
31
|
+
|
20
32
|
// Get all markdown files from the API docs directory using absolute path
|
21
|
-
|
22
|
-
|
33
|
+
// Use path.join for cross-platform compatibility
|
34
|
+
const apiFiles = glob.sync(path.join(apiDir, '**/*.md').replace(/\\/g, '/'), {
|
35
|
+
absolute: true,
|
36
|
+
}); // Use forward slashes for glob
|
37
|
+
|
38
|
+
// Log found files for debugging
|
39
|
+
console.log(`Found ${apiFiles.length} API files:`, apiFiles);
|
40
|
+
|
23
41
|
// Build sidebar structure
|
24
|
-
const apiSidebar: SidebarItem[] = []
|
25
|
-
|
42
|
+
const apiSidebar: SidebarItem[] = [];
|
43
|
+
|
26
44
|
// Define documentation sections to process
|
27
45
|
const sections = [
|
28
46
|
{ name: 'Modules', path: 'modules' },
|
29
47
|
{ name: 'Classes', path: 'classes' },
|
30
48
|
{ name: 'Interfaces', path: 'interfaces' },
|
31
49
|
{ name: 'Functions', path: 'functions' },
|
32
|
-
{ name: 'Types', path: 'types' }
|
33
|
-
|
50
|
+
{ name: 'Types', path: 'types' },
|
51
|
+
// Add other sections if needed
|
52
|
+
];
|
34
53
|
|
35
54
|
// Process each section
|
36
55
|
sections.forEach(({ name, path: sectionPath }) => {
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
56
|
+
// Filter files based on the absolute path to the section directory
|
57
|
+
const sectionDir = path.join(apiDir, sectionPath);
|
58
|
+
const sectionFiles = apiFiles
|
59
|
+
.filter(file => {
|
60
|
+
// Check if the file is within the current section's directory
|
61
|
+
// and is not an index file directly within that section directory
|
62
|
+
const fileDirPath = path.dirname(file);
|
63
|
+
return (
|
64
|
+
file.startsWith(sectionDir) && fileDirPath !== sectionDir && !file.endsWith('index.md')
|
65
|
+
);
|
66
|
+
// Alternative, simpler check if structure is flat within sections:
|
67
|
+
// return file.startsWith(path.join(apiDir, sectionPath, '/')) && !file.endsWith('index.md');
|
68
|
+
})
|
69
|
+
.map(file => {
|
70
|
+
// Calculate path relative to the 'docs' directory for the link
|
71
|
+
const relativePath = path.relative(docsDir, file);
|
72
|
+
const basename = path.basename(file, '.md');
|
73
|
+
const link = '/' + relativePath.replace(/\\/g, '/').replace(/\.md$/, ''); // Ensure forward slashes for URL
|
74
|
+
|
75
|
+
console.log(`Processing file: ${file}, Relative Path: ${relativePath}, Link: ${link}`); // Debug log
|
76
|
+
|
77
|
+
return {
|
78
|
+
text: basename.replace(/^_/, '').replace(/-/g, ' '), // Basic cleanup
|
79
|
+
link: link,
|
80
|
+
};
|
81
|
+
})
|
82
|
+
.sort((a, b) => a.text.localeCompare(b.text)); // Sort items alphabetically
|
83
|
+
|
49
84
|
if (sectionFiles.length > 0) {
|
50
85
|
apiSidebar.push({
|
51
86
|
text: name,
|
52
|
-
collapsed: false,
|
53
|
-
items: sectionFiles
|
54
|
-
})
|
87
|
+
collapsed: false, // Or true if you prefer them collapsed
|
88
|
+
items: sectionFiles,
|
89
|
+
});
|
55
90
|
}
|
56
|
-
})
|
57
|
-
|
58
|
-
// Add main API index
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
91
|
+
});
|
92
|
+
|
93
|
+
// Add main API index if it exists (relative to docsDir)
|
94
|
+
const mainApiIndex = path.join(apiDir, 'index.md'); // Or maybe README.md? Check your TypeDoc output
|
95
|
+
// Check if the main index file exists using glob result or fs.existsSync
|
96
|
+
const mainApiIndexExists = apiFiles.some(file => file === mainApiIndex);
|
97
|
+
|
98
|
+
if (mainApiIndexExists) {
|
99
|
+
apiSidebar.unshift({
|
100
|
+
text: 'API Overview', // Or 'API Reference'
|
101
|
+
link: '/api/', // Link to the root index file of the API section
|
102
|
+
});
|
103
|
+
} else {
|
104
|
+
// Maybe add a placeholder or log a warning if the main index is missing
|
105
|
+
console.warn(
|
106
|
+
'Main API index file (e.g., docs/api/index.md or docs/api/README.md) not found.'
|
107
|
+
);
|
108
|
+
}
|
109
|
+
|
110
|
+
// Log the final generated sidebar
|
111
|
+
console.log('Generated API Sidebar:', JSON.stringify(apiSidebar, null, 2));
|
112
|
+
|
113
|
+
return apiSidebar;
|
65
114
|
} catch (error) {
|
66
|
-
console.error('Error building docs sidebar:', error)
|
115
|
+
console.error('Error building docs sidebar:', error);
|
67
116
|
// Return basic sidebar if there's an error
|
68
|
-
return [
|
69
|
-
|
70
|
-
|
71
|
-
|
117
|
+
return [
|
118
|
+
{
|
119
|
+
text: 'API Reference (Error)',
|
120
|
+
link: '/api/',
|
121
|
+
},
|
122
|
+
];
|
72
123
|
}
|
73
|
-
}
|
124
|
+
}
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# PortaPack Architecture
|
2
|
+
|
3
|
+
## Overview
|
4
|
+
|
5
|
+
PortaPack is a sophisticated tool that bundles entire websites—HTML, CSS, JavaScript, images, and fonts—into self-contained HTML files for offline access. This document outlines the architectural components that make up the system.
|
6
|
+
|
7
|
+
```mermaid
|
8
|
+
graph TD
|
9
|
+
CLI[CLI Entry Point] --> Options[Options Parser]
|
10
|
+
Options --> Core
|
11
|
+
API[API Entry Point] --> Core
|
12
|
+
|
13
|
+
subgraph Core ["Core Pipeline"]
|
14
|
+
Parser[HTML Parser] --> Extractor[Asset Extractor]
|
15
|
+
Extractor --> Minifier[Asset Minifier]
|
16
|
+
Minifier --> Packer[HTML Packer]
|
17
|
+
end
|
18
|
+
|
19
|
+
subgraph Recursive ["Advanced Features"]
|
20
|
+
WebFetcher[Web Fetcher] --> MultipageBundler[Multipage Bundler]
|
21
|
+
end
|
22
|
+
|
23
|
+
WebFetcher --> Parser
|
24
|
+
Core --> Output[Bundled HTML]
|
25
|
+
MultipageBundler --> Output
|
26
|
+
|
27
|
+
subgraph Utilities ["Utilities"]
|
28
|
+
Logger[Logger]
|
29
|
+
MimeUtils[MIME Utilities]
|
30
|
+
BuildTimer[Build Timer]
|
31
|
+
Slugify[URL Slugifier]
|
32
|
+
end
|
33
|
+
|
34
|
+
Logger -.-> CLI
|
35
|
+
Logger -.-> Core
|
36
|
+
Logger -.-> Recursive
|
37
|
+
MimeUtils -.-> Extractor
|
38
|
+
MimeUtils -.-> Parser
|
39
|
+
BuildTimer -.-> CLI
|
40
|
+
BuildTimer -.-> API
|
41
|
+
Slugify -.-> MultipageBundler
|
42
|
+
```
|
43
|
+
|
44
|
+
## Entry Points
|
45
|
+
|
46
|
+
### CLI Interface
|
47
|
+
|
48
|
+
The command-line interface provides a convenient way to use PortaPack through terminal commands:
|
49
|
+
|
50
|
+
| Component | Purpose |
|
51
|
+
|-----------|---------|
|
52
|
+
| `cli-entry.ts` | Executable entry point with shebang support |
|
53
|
+
| `cli.ts` | Main runner that processes args and manages execution |
|
54
|
+
| `options.ts` | Parses command-line arguments and normalizes options |
|
55
|
+
|
56
|
+
### API Interface
|
57
|
+
|
58
|
+
The programmatic API enables developers to integrate PortaPack into their applications:
|
59
|
+
|
60
|
+
| Component | Purpose |
|
61
|
+
|-----------|---------|
|
62
|
+
| `index.ts` | Exports public functions like `pack()` with TypeScript types |
|
63
|
+
| `types.ts` | Defines shared interfaces and types for the entire system |
|
64
|
+
|
65
|
+
## Core Pipeline
|
66
|
+
|
67
|
+
The bundling process follows a clear four-stage pipeline:
|
68
|
+
|
69
|
+
### 1. HTML Parser (`parser.ts`)
|
70
|
+
|
71
|
+
The parser reads and analyzes the input HTML:
|
72
|
+
- Uses Cheerio for robust HTML parsing
|
73
|
+
- Identifies linked assets through element attributes (href, src, etc.)
|
74
|
+
- Creates an initial asset list with URLs and inferred types
|
75
|
+
- Handles both local file paths and remote URLs
|
76
|
+
|
77
|
+
### 2. Asset Extractor (`extractor.ts`)
|
78
|
+
|
79
|
+
The extractor resolves and fetches all referenced assets:
|
80
|
+
- Resolves relative URLs against the base context
|
81
|
+
- Fetches content for all discovered assets
|
82
|
+
- Recursively extracts nested assets from CSS (@import, url())
|
83
|
+
- Handles protocol-relative URLs and different origins
|
84
|
+
- Provides detailed logging of asset discovery
|
85
|
+
|
86
|
+
### 3. Asset Minifier (`minifier.ts`)
|
87
|
+
|
88
|
+
The minifier reduces the size of all content:
|
89
|
+
- Minifies HTML using html-minifier-terser
|
90
|
+
- Minifies CSS using clean-css
|
91
|
+
- Minifies JavaScript using terser
|
92
|
+
- Preserves original content if minification fails
|
93
|
+
- Configurable through command-line flags
|
94
|
+
|
95
|
+
### 4. HTML Packer (`packer.ts`)
|
96
|
+
|
97
|
+
The packer combines everything into a single file:
|
98
|
+
- Inlines CSS into `<style>` tags
|
99
|
+
- Embeds JavaScript into `<script>` tags
|
100
|
+
- Converts binary assets to data URIs
|
101
|
+
- Handles srcset attributes properly
|
102
|
+
- Ensures proper HTML structure with base tag
|
103
|
+
|
104
|
+
## Advanced Features
|
105
|
+
|
106
|
+
### Web Fetcher (`web-fetcher.ts`)
|
107
|
+
|
108
|
+
For remote content, the web fetcher provides crawling capabilities:
|
109
|
+
- Uses Puppeteer for fully-rendered page capture
|
110
|
+
- Crawls websites recursively to specified depth
|
111
|
+
- Respects same-origin policy by default
|
112
|
+
- Manages browser instances efficiently
|
113
|
+
- Provides detailed logging of the crawl process
|
114
|
+
|
115
|
+
### Multipage Bundler (`bundler.ts`)
|
116
|
+
|
117
|
+
For bundling multiple pages into a single file:
|
118
|
+
- Combines multiple HTML documents into one
|
119
|
+
- Creates a client-side router for navigation
|
120
|
+
- Generates a navigation interface
|
121
|
+
- Uses slugs for routing between pages
|
122
|
+
- Handles page templates and content swapping
|
123
|
+
|
124
|
+
## Utilities
|
125
|
+
|
126
|
+
### Logger (`logger.ts`)
|
127
|
+
- Customizable log levels (debug, info, warn, error)
|
128
|
+
- Consistent logging format across the codebase
|
129
|
+
- Optional timestamps and colored output
|
130
|
+
|
131
|
+
### MIME Utilities (`mime.ts`)
|
132
|
+
- Maps file extensions to correct MIME types
|
133
|
+
- Categorizes assets by type (CSS, JS, image, font)
|
134
|
+
- Provides fallbacks for unknown extensions
|
135
|
+
|
136
|
+
### Build Timer (`meta.ts`)
|
137
|
+
- Tracks build performance metrics
|
138
|
+
- Records asset counts and page counts
|
139
|
+
- Captures output size and build duration
|
140
|
+
- Collects errors and warnings for reporting
|
141
|
+
|
142
|
+
### URL Slugifier (`slugify.ts`)
|
143
|
+
- Converts URLs to safe HTML IDs
|
144
|
+
- Handles special characters and normalization
|
145
|
+
- Prevents slug collisions in multipage bundles
|
146
|
+
|
147
|
+
## Asynchronous Processing
|
148
|
+
|
149
|
+
PortaPack uses modern async patterns throughout:
|
150
|
+
|
151
|
+
- **Promise-based Pipeline**: Each stage returns promises that are awaited
|
152
|
+
- **Sequential Processing**: Assets are processed in order to avoid overwhelming resources
|
153
|
+
- **Error Boundaries**: Individual asset failures don't break the entire pipeline
|
154
|
+
- **Resource Management**: Browser instances and file handles are properly closed
|
155
|
+
|
156
|
+
## Build System
|
157
|
+
|
158
|
+
PortaPack uses a dual build configuration:
|
159
|
+
|
160
|
+
| Build Target | Format | Purpose |
|
161
|
+
|--------------|--------|---------|
|
162
|
+
| CLI | CommonJS (.cjs) | Works with Node.js and npx |
|
163
|
+
| API | ESModule (.js) | Modern import/export support |
|
164
|
+
|
165
|
+
TypeScript declarations (.d.ts) are generated for API consumers, and source maps support debugging.
|
166
|
+
|
167
|
+
## Current Limitations
|
168
|
+
|
169
|
+
### Script Execution Issues
|
170
|
+
|
171
|
+
- Inlined scripts with `async`/`defer` attributes lose their intended loading behavior
|
172
|
+
- ES Modules with import/export statements may fail after bundling
|
173
|
+
- Script execution order can change, breaking dependencies
|
174
|
+
|
175
|
+
### Content Limitations
|
176
|
+
|
177
|
+
- CORS policies may prevent access to some cross-origin resources
|
178
|
+
- Only initially rendered content from SPAs is captured by default
|
179
|
+
- Very large sites produce impractically large HTML files
|
180
|
+
|
181
|
+
### Technical Constraints
|
182
|
+
|
183
|
+
- No streaming API or WebSocket support
|
184
|
+
- Service worker capabilities are not preserved
|
185
|
+
- Memory pressure with large sites
|
186
|
+
- Limited support for authenticated content
|
package/docs/cli.md
CHANGED
@@ -26,25 +26,25 @@ Where `[input]` is the path to a local HTML file or a remote URL.
|
|
26
26
|
|
27
27
|
## Options
|
28
28
|
|
29
|
-
| Option
|
30
|
-
|
31
|
-
| `[input]`
|
32
|
-
| `--output <file>`
|
33
|
-
| `--recursive [depth]` | `-r`
|
34
|
-
| `--max-depth <n>`
|
35
|
-
| `--minify`
|
36
|
-
| `--no-minify`
|
37
|
-
| `--no-minify-html`
|
38
|
-
| `--no-minify-css`
|
39
|
-
| `--no-minify-js`
|
40
|
-
| `--embed-assets`
|
41
|
-
| `--no-embed-assets`
|
42
|
-
| `--base-url <url>`
|
43
|
-
| `--log-level <level>` |
|
44
|
-
| `--verbose`
|
45
|
-
| `--dry-run`
|
46
|
-
| `--help`
|
47
|
-
| `--version`
|
29
|
+
| Option | Shorthand | Description | Default |
|
30
|
+
| --------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------ |
|
31
|
+
| `[input]` | | Required. Input local file path or remote URL (http/https) to process. | - |
|
32
|
+
| `--output <file>` | `-o` | Output file path for the bundled HTML. | `{input-basename}.packed.html` |
|
33
|
+
| `--recursive [depth]` | `-r` | Recursively bundle links up to depth. If depth omitted, defaults to true (no limit). Only applies to remote URLs. | `false` (disabled) |
|
34
|
+
| `--max-depth <n>` | | Set maximum depth for recursive crawling (alternative to `-r <n>`). | - |
|
35
|
+
| `--minify` | `-m` | Enable all minification (HTML, CSS, JS). | - |
|
36
|
+
| `--no-minify` | | Disable all asset minification (HTML, CSS, JS). | `false` |
|
37
|
+
| `--no-minify-html` | | Disable only HTML minification. | `false` |
|
38
|
+
| `--no-minify-css` | | Disable only CSS minification. | `false` |
|
39
|
+
| `--no-minify-js` | | Disable only JavaScript minification. | `false` |
|
40
|
+
| `--embed-assets` | `-e` | Embed external assets (CSS, JS, images, fonts) as data URIs or inline content. | `true` |
|
41
|
+
| `--no-embed-assets` | | Keep external assets as links (requires network access when viewing). | `false` |
|
42
|
+
| `--base-url <url>` | `-b` | Base URL for resolving relative URLs found in the input HTML. | Input path/URL |
|
43
|
+
| `--log-level <level>` | | Set logging level (debug, info, warn, error, silent, none). | `info` |
|
44
|
+
| `--verbose` | `-v` | Enable verbose logging (shortcut for `--log-level debug`). | `false` |
|
45
|
+
| `--dry-run` | `-d` | Perform all steps except writing the output file. Logs intended actions. | `false` |
|
46
|
+
| `--help` | `-h` | Show help information and exit. | - |
|
47
|
+
| `--version` | | Show PortaPack CLI version number and exit. | - |
|
48
48
|
|
49
49
|
## Examples
|
50
50
|
|
@@ -169,12 +169,12 @@ npx portapack ./index.html -o bundle.html
|
|
169
169
|
## Exit Codes
|
170
170
|
|
171
171
|
| Code | Description |
|
172
|
-
|
173
|
-
| 0
|
174
|
-
| 1
|
172
|
+
| ---- | ----------- |
|
173
|
+
| 0 | Success |
|
174
|
+
| 1 | Error |
|
175
175
|
|
176
176
|
## Related Resources
|
177
177
|
|
178
178
|
- [Getting Started](https://manicinc.github.io/portapack/getting-started)
|
179
179
|
- [API Reference](https://manicinc.github.io/portapack/api/)
|
180
|
-
- [Configuration Guide](https://manicinc.github.io/portapack/configuration)
|
180
|
+
- [Configuration Guide](https://manicinc.github.io/portapack/configuration)
|
package/docs/code-of-conduct.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
## Our Pledge
|
4
4
|
|
5
5
|
We are committed to providing a friendly, safe, and welcoming environment for all contributors, regardless of:
|
6
|
+
|
6
7
|
- Age
|
7
8
|
- Body size
|
8
9
|
- Disability
|
@@ -18,6 +19,7 @@ We are committed to providing a friendly, safe, and welcoming environment for al
|
|
18
19
|
## Our Standards
|
19
20
|
|
20
21
|
### Positive Behavior
|
22
|
+
|
21
23
|
- Using welcoming and inclusive language
|
22
24
|
- Being respectful of differing viewpoints
|
23
25
|
- Gracefully accepting constructive criticism
|
@@ -25,6 +27,7 @@ We are committed to providing a friendly, safe, and welcoming environment for al
|
|
25
27
|
- Showing empathy towards other community members
|
26
28
|
|
27
29
|
### Unacceptable Behavior
|
30
|
+
|
28
31
|
- Trolling, insulting/derogatory comments
|
29
32
|
- Public or private harassment
|
30
33
|
- Publishing others' private information
|
@@ -33,6 +36,7 @@ We are committed to providing a friendly, safe, and welcoming environment for al
|
|
33
36
|
## Enforcement Responsibilities
|
34
37
|
|
35
38
|
Community leaders are responsible for:
|
39
|
+
|
36
40
|
- Clarifying acceptable behavior standards
|
37
41
|
- Providing fair and consistent feedback
|
38
42
|
- Removing, editing, or rejecting contributions that violate this Code of Conduct
|
@@ -40,6 +44,7 @@ Community leaders are responsible for:
|
|
40
44
|
## Reporting Issues
|
41
45
|
|
42
46
|
If you experience or witness unacceptable behavior:
|
47
|
+
|
43
48
|
1. Email [conduct@manicinc.com](mailto:conduct@manicinc.com)
|
44
49
|
2. Provide:
|
45
50
|
- Your contact information
|
@@ -50,6 +55,7 @@ If you experience or witness unacceptable behavior:
|
|
50
55
|
## Consequences
|
51
56
|
|
52
57
|
Violations may result in:
|
58
|
+
|
53
59
|
- Temporary or permanent ban from community spaces
|
54
60
|
- Removal of contributions
|
55
61
|
- Public or private warnings
|
@@ -62,4 +68,4 @@ This Code of Conduct is adapted from the [Contributor Covenant][homepage], versi
|
|
62
68
|
|
63
69
|
## License
|
64
70
|
|
65
|
-
This Code of Conduct is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).
|
71
|
+
This Code of Conduct is licensed under a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).
|
package/docs/configuration.md
CHANGED
@@ -36,7 +36,7 @@ import { pack } from 'portapack';
|
|
36
36
|
async function bundleLocalSite() {
|
37
37
|
const result = await pack('./index.html');
|
38
38
|
console.log(result.html);
|
39
|
-
|
39
|
+
|
40
40
|
// Access metadata about the build
|
41
41
|
console.log(`Output size: ${result.metadata.outputSize} bytes`);
|
42
42
|
console.log(`Build time: ${result.metadata.buildTimeMs} ms`);
|
@@ -49,9 +49,9 @@ async function bundleWithOptions() {
|
|
49
49
|
minifyCss: true,
|
50
50
|
minifyJs: true,
|
51
51
|
baseUrl: 'https://example.com',
|
52
|
-
embedAssets: true
|
52
|
+
embedAssets: true,
|
53
53
|
});
|
54
|
-
|
54
|
+
|
55
55
|
// Use or save the bundled HTML
|
56
56
|
console.log(result.html);
|
57
57
|
}
|
@@ -59,12 +59,12 @@ async function bundleWithOptions() {
|
|
59
59
|
// Recursive bundling of a website
|
60
60
|
async function bundleWebsite() {
|
61
61
|
const result = await pack('https://example.com', {
|
62
|
-
recursive: 2,
|
62
|
+
recursive: 2, // Crawl up to 2 levels deep
|
63
63
|
minifyHtml: true,
|
64
64
|
minifyCss: true,
|
65
|
-
minifyJs: true
|
65
|
+
minifyJs: true,
|
66
66
|
});
|
67
|
-
|
67
|
+
|
68
68
|
console.log(`Bundled ${result.metadata.pagesBundled} pages`);
|
69
69
|
}
|
70
70
|
```
|
@@ -83,18 +83,18 @@ import {
|
|
83
83
|
|
84
84
|
// Bundle a single HTML file or URL
|
85
85
|
const singleResult = await generatePortableHTML('./index.html', {
|
86
|
-
minifyHtml: true
|
86
|
+
minifyHtml: true,
|
87
87
|
});
|
88
88
|
|
89
89
|
// Recursively bundle a site
|
90
90
|
const recursiveResult = await generateRecursivePortableHTML('https://example.com', 2, {
|
91
|
-
minifyCss: true
|
91
|
+
minifyCss: true,
|
92
92
|
});
|
93
93
|
|
94
94
|
// Create multi-page bundle
|
95
95
|
const multiPageBundle = await bundleMultiPageHTML([
|
96
96
|
{ path: '/', html: '<html>...</html>' },
|
97
|
-
{ path: '/about', html: '<html>...</html>' }
|
97
|
+
{ path: '/about', html: '<html>...</html>' },
|
98
98
|
]);
|
99
99
|
```
|
100
100
|
|
@@ -117,7 +117,7 @@ For details, see the [CLI Reference](https://manicinc.github.io/portapack/cli).
|
|
117
117
|
|
118
118
|
- 📖 [Explore CLI Options](https://manicinc.github.io/portapack/cli)
|
119
119
|
- 🛠 [Advanced Configuration](https://manicinc.github.io/portapack/configuration)
|
120
|
-
- 💻 [API Reference](https://manicinc.github.io/portapack/api/)
|
120
|
+
- 💻 [API Reference](https://manicinc.github.io/portapack/api/README.html)
|
121
121
|
|
122
122
|
## Troubleshooting
|
123
123
|
|
@@ -126,6 +126,7 @@ Encountering issues? Check our [Troubleshooting Guide](https://manicinc.github.i
|
|
126
126
|
## Contributing
|
127
127
|
|
128
128
|
Interested in improving PortaPack?
|
129
|
+
|
129
130
|
- [View Contributing Guidelines](https://manicinc.github.io/portapack/contributing)
|
130
131
|
|
131
132
|
## Support
|
@@ -133,4 +134,4 @@ Interested in improving PortaPack?
|
|
133
134
|
- 🐛 [Report an Issue](https://github.com/manicinc/portapack/issues)
|
134
135
|
- 💬 [Community Support](https://discord.gg/DzNgXdYm)
|
135
136
|
|
136
|
-
Built by [Manic.agency](https://manic.agency)
|
137
|
+
Built by [Manic.agency](https://manic.agency)
|