Skip to content

Commit 5aabef8

Browse files
author
Emmanuel Campait
committed
Initial release
Bootstrap 5 asset publisher for CodeIgniter 4
0 parents  commit 5aabef8

6 files changed

Lines changed: 287 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor/
2+
/composer.lock

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 domProjects
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# domProjects CodeIgniter 4 Bootstrap
2+
3+
Bootstrap 5 asset publisher for CodeIgniter 4.
4+
5+
This package adds a Spark command that publishes the Bootstrap distribution files from Composer dependencies into your public directory.
6+
7+
## Features
8+
9+
- Installs Bootstrap with Composer
10+
- Publishes only the Bootstrap production assets
11+
- Works with CodeIgniter 4 auto-discovery
12+
- Keeps Bootstrap asset publication explicit and framework-oriented
13+
14+
## Requirements
15+
16+
- PHP 8.2 or newer
17+
- CodeIgniter 4.7.2 or newer
18+
- Bootstrap 5.3.8 or newer within the 5.3 branch
19+
20+
## Installation
21+
22+
Install the package in your CodeIgniter 4 project:
23+
24+
```bash
25+
composer require domprojects/codeigniter4-bootstrap
26+
```
27+
28+
## Optional Automation Plugin
29+
30+
If you also want automatic publication after `composer install` and `composer update`, install the companion plugin:
31+
32+
```bash
33+
composer require domprojects/codeigniter4-bootstrap-plugin
34+
```
35+
36+
The plugin package is optional. This main package works on its own.
37+
38+
## Spark Command
39+
40+
Publish assets manually:
41+
42+
```bash
43+
php spark assets:publish-bootstrap
44+
```
45+
46+
Force overwrite existing files:
47+
48+
```bash
49+
php spark assets:publish-bootstrap --force
50+
```
51+
52+
## Published Files
53+
54+
The package publishes these files:
55+
56+
- `css/bootstrap.min.css`
57+
- `css/bootstrap.min.css.map`
58+
- `js/bootstrap.bundle.min.js`
59+
- `js/bootstrap.bundle.min.js.map`
60+
61+
## Destination
62+
63+
Files are published to:
64+
65+
```text
66+
public/assets/bootstrap
67+
```
68+
69+
## Usage in Views
70+
71+
Example in a CodeIgniter view:
72+
73+
```php
74+
<link rel="stylesheet" href="<?= base_url('assets/bootstrap/css/bootstrap.min.css') ?>">
75+
<script src="<?= base_url('assets/bootstrap/js/bootstrap.bundle.min.js') ?>"></script>
76+
```
77+
78+
## Package Structure
79+
80+
```text
81+
src/
82+
Commands/
83+
PublishBootstrap.php
84+
Publishers/
85+
BootstrapPublisher.php
86+
```
87+
88+
## Local Development
89+
90+
If you want to work on the package locally from another project, you can use a Composer `path` repository.
91+
92+
Example:
93+
94+
```json
95+
{
96+
"repositories": {
97+
"domprojects-codeigniter4-bootstrap": {
98+
"type": "path",
99+
"url": "packages/domprojects/codeigniter4-bootstrap",
100+
"options": {
101+
"symlink": false
102+
}
103+
}
104+
}
105+
}
106+
```
107+
108+
If you also test the automation plugin locally, add a second `path` repository for `packages/domprojects/codeigniter4-bootstrap-plugin`.
109+
110+
## Related Package
111+
112+
- `domprojects/codeigniter4-bootstrap-plugin`: optional Composer plugin for automatic publication
113+
114+
## Publish on Packagist
115+
116+
Recommended release flow for this package:
117+
118+
1. Push the repository to GitHub.
119+
2. Create a tag such as `v1.0.0`.
120+
3. Submit the GitHub repository URL to Packagist.
121+
122+
If you use the automation plugin, release and publish that repository separately.
123+
124+
## License
125+
126+
MIT

composer.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "domprojects/codeigniter4-bootstrap",
3+
"description": "Bootstrap 5 asset publisher for CodeIgniter 4 projects.",
4+
"type": "library",
5+
"license": "MIT",
6+
"keywords": [
7+
"codeigniter4",
8+
"codeigniter",
9+
"bootstrap",
10+
"assets",
11+
"publisher"
12+
],
13+
"homepage": "https://github.com/domProjects/codeigniter4-bootstrap",
14+
"support": {
15+
"issues": "https://github.com/domProjects/codeigniter4-bootstrap/issues",
16+
"source": "https://github.com/domProjects/codeigniter4-bootstrap"
17+
},
18+
"authors": [
19+
{
20+
"name": "domProjects",
21+
"homepage": "https://github.com/domProjects",
22+
"role": "Maintainer"
23+
}
24+
],
25+
"require": {
26+
"php": "^8.2",
27+
"codeigniter4/framework": "^4.7.2",
28+
"twbs/bootstrap": "^5.3.8"
29+
},
30+
"autoload": {
31+
"psr-4": {
32+
"domProjects\\CodeIgniterBootstrap\\": "src/"
33+
}
34+
},
35+
"extra": {
36+
"branch-alias": {
37+
"dev-main": "1.x-dev"
38+
}
39+
}
40+
}

src/Commands/PublishBootstrap.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace domProjects\CodeIgniterBootstrap\Commands;
4+
5+
use CodeIgniter\CLI\BaseCommand;
6+
use CodeIgniter\CLI\CLI;
7+
use domProjects\CodeIgniterBootstrap\Publishers\BootstrapPublisher;
8+
use Throwable;
9+
10+
class PublishBootstrap extends BaseCommand
11+
{
12+
protected $group = 'Bootstrap';
13+
protected $name = 'assets:publish-bootstrap';
14+
protected $description = 'Publishes Bootstrap 5 assets to public/assets/bootstrap.';
15+
protected $usage = 'assets:publish-bootstrap [--force]';
16+
protected $options = [
17+
'--force' => 'Overwrite existing files.',
18+
'-f' => 'Alias of --force.',
19+
];
20+
21+
public function run(array $params)
22+
{
23+
$force = array_key_exists('force', $params)
24+
|| array_key_exists('f', $params)
25+
|| CLI::getOption('force') !== null
26+
|| CLI::getOption('f') !== null;
27+
28+
$publisher = (new BootstrapPublisher())->setReplace($force);
29+
30+
CLI::write(
31+
'Publishing Bootstrap assets to ' . $publisher->getDestination() . ($force ? ' with overwrite...' : '...'),
32+
'yellow'
33+
);
34+
35+
try {
36+
if (! $publisher->publish()) {
37+
CLI::error('Bootstrap publish failed.');
38+
39+
foreach ($publisher->getErrors() as $file => $exception) {
40+
CLI::write($file);
41+
CLI::error($exception->getMessage());
42+
CLI::newLine();
43+
}
44+
45+
return EXIT_ERROR;
46+
}
47+
} catch (Throwable $e) {
48+
$this->showError($e);
49+
50+
return EXIT_ERROR;
51+
}
52+
53+
CLI::write('Bootstrap assets published successfully.', 'green');
54+
55+
return EXIT_SUCCESS;
56+
}
57+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace domProjects\CodeIgniterBootstrap\Publishers;
4+
5+
use CodeIgniter\Publisher\Publisher;
6+
use RuntimeException;
7+
8+
class BootstrapPublisher extends Publisher
9+
{
10+
protected $source = VENDORPATH . 'twbs/bootstrap/dist';
11+
protected $destination = FCPATH . 'assets/bootstrap';
12+
protected bool $replace = false;
13+
14+
public function __construct(?string $source = null, ?string $destination = null)
15+
{
16+
$destination ??= $this->destination;
17+
18+
if (! is_dir($destination) && ! mkdir($destination, 0775, true) && ! is_dir($destination)) {
19+
throw new RuntimeException('Unable to create Bootstrap asset destination: ' . $destination);
20+
}
21+
22+
parent::__construct($source ?? $this->source, $destination);
23+
}
24+
25+
public function setReplace(bool $replace): self
26+
{
27+
$this->replace = $replace;
28+
29+
return $this;
30+
}
31+
32+
public function publish(): bool
33+
{
34+
return $this->addPaths([
35+
'css/bootstrap.min.css',
36+
'css/bootstrap.min.css.map',
37+
'js/bootstrap.bundle.min.js',
38+
'js/bootstrap.bundle.min.js.map',
39+
])->merge($this->replace);
40+
}
41+
}

0 commit comments

Comments
 (0)