mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-29 23:22:34 +01:00
Updated build and versioning system
Added versioning file instead of using git tags (Step towards removing git as a dependancy in the future) Updated gulpfile to fit with verisioning system and cleaned up node dependancies. Fixes #108
This commit is contained in:
parent
a6c6c6e300
commit
ab468bac3c
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,4 +11,5 @@ Homestead.yaml
|
|||||||
/storage/images
|
/storage/images
|
||||||
_ide_helper.php
|
_ide_helper.php
|
||||||
/storage/debugbar
|
/storage/debugbar
|
||||||
.phpstorm.meta.php
|
.phpstorm.meta.php
|
||||||
|
yarn.lock
|
||||||
|
@ -17,10 +17,7 @@ class SettingController extends Controller
|
|||||||
$this->setPageTitle('Settings');
|
$this->setPageTitle('Settings');
|
||||||
|
|
||||||
// Get application version
|
// Get application version
|
||||||
$version = false;
|
$version = trim(file_get_contents(base_path('version')));
|
||||||
if (function_exists('exec')) {
|
|
||||||
$version = exec('git describe --always --tags ');
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('settings/index', ['version' => $version]);
|
return view('settings/index', ['version' => $version]);
|
||||||
}
|
}
|
||||||
|
@ -11,29 +11,20 @@ use BookStack\Ownable;
|
|||||||
*/
|
*/
|
||||||
function versioned_asset($file = '')
|
function versioned_asset($file = '')
|
||||||
{
|
{
|
||||||
// Don't require css and JS assets for testing
|
static $version = null;
|
||||||
if (config('app.env') === 'testing') return '';
|
|
||||||
|
|
||||||
static $manifest = null;
|
if (is_null($version)) {
|
||||||
$manifestPath = 'build/manifest.json';
|
$versionFile = base_path('version');
|
||||||
|
$version = trim(file_get_contents($versionFile));
|
||||||
if (is_null($manifest) && file_exists($manifestPath)) {
|
|
||||||
$manifest = json_decode(file_get_contents(public_path($manifestPath)), true);
|
|
||||||
} else if (!file_exists($manifestPath)) {
|
|
||||||
if (config('app.env') !== 'production') {
|
|
||||||
$path = public_path($manifestPath);
|
|
||||||
$error = "No {$path} file found, Ensure you have built the css/js assets using gulp.";
|
|
||||||
} else {
|
|
||||||
$error = "No {$manifestPath} file found, Ensure you are using the release version of BookStack";
|
|
||||||
}
|
|
||||||
throw new \Exception($error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($manifest[$file])) {
|
$additional = '';
|
||||||
return baseUrl($manifest[$file]);
|
if (config('app.env') === 'development') {
|
||||||
|
$additional = sha1_file(public_path($file));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
|
$path = $file . '?version=' . urlencode($version) . $additional;
|
||||||
|
return baseUrl($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,14 +129,14 @@ function sortUrl($path, $data, $overrideData = [])
|
|||||||
{
|
{
|
||||||
$queryStringSections = [];
|
$queryStringSections = [];
|
||||||
$queryData = array_merge($data, $overrideData);
|
$queryData = array_merge($data, $overrideData);
|
||||||
|
|
||||||
// Change sorting direction is already sorted on current attribute
|
// Change sorting direction is already sorted on current attribute
|
||||||
if (isset($overrideData['sort']) && $overrideData['sort'] === $data['sort']) {
|
if (isset($overrideData['sort']) && $overrideData['sort'] === $data['sort']) {
|
||||||
$queryData['order'] = ($data['order'] === 'asc') ? 'desc' : 'asc';
|
$queryData['order'] = ($data['order'] === 'asc') ? 'desc' : 'asc';
|
||||||
} else {
|
} else {
|
||||||
$queryData['order'] = 'asc';
|
$queryData['order'] = 'asc';
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($queryData as $name => $value) {
|
foreach ($queryData as $name => $value) {
|
||||||
$trimmedVal = trim($value);
|
$trimmedVal = trim($value);
|
||||||
if ($trimmedVal === '') continue;
|
if ($trimmedVal === '') continue;
|
||||||
@ -155,4 +146,4 @@ function sortUrl($path, $data, $overrideData = [])
|
|||||||
if (count($queryStringSections) === 0) return $path;
|
if (count($queryStringSections) === 0) return $path;
|
||||||
|
|
||||||
return baseUrl($path . '?' . implode('&', $queryStringSections));
|
return baseUrl($path . '?' . implode('&', $queryStringSections));
|
||||||
}
|
}
|
||||||
|
29
gulpfile.js
29
gulpfile.js
@ -1,27 +1,8 @@
|
|||||||
var elixir = require('laravel-elixir');
|
var elixir = require('laravel-elixir');
|
||||||
|
|
||||||
// Custom extensions
|
elixir(mix => {
|
||||||
var gulp = require('gulp');
|
mix.sass('styles.scss');
|
||||||
var Task = elixir.Task;
|
mix.sass('print-styles.scss');
|
||||||
var fs = require('fs');
|
mix.sass('export-styles.scss');
|
||||||
|
mix.browserify('global.js', './public/js/common.js');
|
||||||
elixir.extend('queryVersion', function(inputFiles) {
|
|
||||||
new Task('queryVersion', function() {
|
|
||||||
var manifestObject = {};
|
|
||||||
var uidString = Date.now().toString(16).slice(4);
|
|
||||||
for (var i = 0; i < inputFiles.length; i++) {
|
|
||||||
var file = inputFiles[i];
|
|
||||||
manifestObject[file] = file + '?version=' + uidString;
|
|
||||||
}
|
|
||||||
var fileContents = JSON.stringify(manifestObject, null, 1);
|
|
||||||
fs.writeFileSync('public/build/manifest.json', fileContents);
|
|
||||||
}).watch(['./public/css/*.css', './public/js/*.js']);
|
|
||||||
});
|
|
||||||
|
|
||||||
elixir(function(mix) {
|
|
||||||
mix.sass('styles.scss')
|
|
||||||
.sass('print-styles.scss')
|
|
||||||
.sass('export-styles.scss')
|
|
||||||
.browserify('global.js', 'public/js/common.js')
|
|
||||||
.queryVersion(['css/styles.css', 'css/print-styles.css', 'js/common.js']);
|
|
||||||
});
|
});
|
||||||
|
15
package.json
15
package.json
@ -1,18 +1,19 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"scripts": {
|
||||||
"gulp": "^3.9.0"
|
"prod": "gulp --production",
|
||||||
|
"dev": "gulp watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"angular": "^1.5.5",
|
"angular": "^1.5.5",
|
||||||
"angular-animate": "^1.5.5",
|
"angular-animate": "^1.5.5",
|
||||||
"angular-resource": "^1.5.5",
|
"angular-resource": "^1.5.5",
|
||||||
"angular-sanitize": "^1.5.5",
|
"angular-sanitize": "^1.5.5",
|
||||||
"angular-ui-sortable": "^0.14.0",
|
"angular-ui-sortable": "^0.15.0",
|
||||||
"babel-runtime": "^5.8.29",
|
|
||||||
"bootstrap-sass": "^3.0.0",
|
|
||||||
"dropzone": "^4.0.1",
|
"dropzone": "^4.0.1",
|
||||||
"laravel-elixir": "^5.0.0",
|
"gulp": "^3.9.0",
|
||||||
|
"laravel-elixir": "^6.0.0-11",
|
||||||
|
"laravel-elixir-browserify-official": "^0.1.3",
|
||||||
"marked": "^0.3.5",
|
"marked": "^0.3.5",
|
||||||
"moment": "^2.12.0",
|
"moment": "^2.12.0",
|
||||||
"zeroclipboard": "^2.2.0"
|
"zeroclipboard": "^2.2.0"
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
<env name="AUTH_METHOD" value="standard"/>
|
<env name="AUTH_METHOD" value="standard"/>
|
||||||
<env name="DISABLE_EXTERNAL_SERVICES" value="true"/>
|
<env name="DISABLE_EXTERNAL_SERVICES" value="true"/>
|
||||||
<env name="LDAP_VERSION" value="3"/>
|
<env name="LDAP_VERSION" value="3"/>
|
||||||
|
<env name="STORAGE_TYPE" value="local"/>
|
||||||
<env name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/>
|
<env name="GITHUB_APP_ID" value="aaaaaaaaaaaaaa"/>
|
||||||
<env name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/>
|
<env name="GITHUB_APP_SECRET" value="aaaaaaaaaaaaaa"/>
|
||||||
<env name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/>
|
<env name="GOOGLE_APP_ID" value="aaaaaaaaaaaaaa"/>
|
||||||
|
2
public/build/.gitignore
vendored
2
public/build/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
10
readme.md
10
readme.md
@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
[![GitHub release](https://img.shields.io/github/release/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/releases/latest)
|
[![GitHub release](https://img.shields.io/github/release/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/releases/latest)
|
||||||
[![license](https://img.shields.io/github/license/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/blob/master/LICENSE)
|
[![license](https://img.shields.io/github/license/ssddanbrown/BookStack.svg?maxAge=2592000)](https://github.com/ssddanbrown/BookStack/blob/master/LICENSE)
|
||||||
[![Build Status](https://travis-ci.org/ssddanbrown/BookStack.svg)](https://travis-ci.org/ssddanbrown/BookStack)
|
[![Build Status](https://travis-ci.org/BookStackApp/BookStack.svg)](https://travis-ci.org/BookStackApp/BookStack)
|
||||||
|
|
||||||
A platform for storing and organising information and documentation. General information and documentation for BookStack can be found at https://www.bookstackapp.com/.
|
A platform for storing and organising information and documentation. General information and documentation for BookStack can be found at https://www.bookstackapp.com/.
|
||||||
|
|
||||||
* [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation)
|
* [Installation Instructions](https://www.bookstackapp.com/docs/admin/installation)
|
||||||
* [Documentation](https://www.bookstackapp.com/docs)
|
* [Documentation](https://www.bookstackapp.com/docs)
|
||||||
* [Demo Instance](https://demo.bookstackapp.com) *(Login username: `admin@example.com`. Password: `password`)*
|
* [Demo Instance](https://demo.bookstackapp.com)
|
||||||
|
* *Username: `admin@example.com`*
|
||||||
|
* *Password: `password`*
|
||||||
* [BookStack Blog](https://www.bookstackapp.com/blog)
|
* [BookStack Blog](https://www.bookstackapp.com/blog)
|
||||||
|
|
||||||
## Development & Testing
|
## Development & Testing
|
||||||
@ -29,7 +31,7 @@ php artisan migrate --database=mysql_testing
|
|||||||
php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
|
php artisan db:seed --class=DummyContentSeeder --database=mysql_testing
|
||||||
```
|
```
|
||||||
|
|
||||||
Once done you can run `phpunit` (or `./vendor/bin/phpunit` if `phpunit` is not found) in the application root directory to run all tests.
|
Once done you can run `phpunit` in the application root directory to run all tests.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
@ -51,3 +53,5 @@ These are the great projects used to help build BookStack:
|
|||||||
* [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html)
|
* [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html)
|
||||||
* [Marked](https://github.com/chjj/marked)
|
* [Marked](https://github.com/chjj/marked)
|
||||||
* [Moment.js](http://momentjs.com/)
|
* [Moment.js](http://momentjs.com/)
|
||||||
|
|
||||||
|
Additionally, Thank you [BrowserStack](https://www.browserstack.com/) for supporting us and making cross-browser testing easy.
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<div class="dropzone-container">
|
|
||||||
<div class="dz-message">Drop files or click here to upload</div>
|
|
||||||
</div>
|
|
@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
<div class="image-picker">
|
|
||||||
<div>
|
|
||||||
<img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
|
|
||||||
<img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
|
|
||||||
</div>
|
|
||||||
<button class="button" type="button" ng-click="showImageManager()">Select Image</button>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<button class="text-button" ng-click="reset()" type="button">Reset</button>
|
|
||||||
<span ng-show="showRemove" class="sep">|</span>
|
|
||||||
<button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
|
|
||||||
|
|
||||||
<input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
|
|
||||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||||||
<div class="toggle-switch" ng-click="switch()" ng-class="{'active': isActive}">
|
|
||||||
<input type="hidden" ng-attr-name="{{name}}" ng-attr-value="{{value}}"/>
|
|
||||||
<div class="switch-handle"></div>
|
|
||||||
</div>
|
|
@ -1,6 +1,8 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const moment = require('moment');
|
import moment from 'moment';
|
||||||
|
import 'moment/locale/en-gb';
|
||||||
|
moment.locale('en-gb');
|
||||||
|
|
||||||
module.exports = function (ngApp, events) {
|
module.exports = function (ngApp, events) {
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ module.exports = function (ngApp, events) {
|
|||||||
$scope.imageDeleteSuccess = false;
|
$scope.imageDeleteSuccess = false;
|
||||||
$scope.uploadedTo = $attrs.uploadedTo;
|
$scope.uploadedTo = $attrs.uploadedTo;
|
||||||
$scope.view = 'all';
|
$scope.view = 'all';
|
||||||
|
|
||||||
$scope.searching = false;
|
$scope.searching = false;
|
||||||
$scope.searchTerm = '';
|
$scope.searchTerm = '';
|
||||||
|
|
||||||
@ -48,7 +50,7 @@ module.exports = function (ngApp, events) {
|
|||||||
$scope.hasMore = preSearchHasMore;
|
$scope.hasMore = preSearchHasMore;
|
||||||
}
|
}
|
||||||
$scope.cancelSearch = cancelSearch;
|
$scope.cancelSearch = cancelSearch;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs on image upload, Adds an image to local list of images
|
* Runs on image upload, Adds an image to local list of images
|
||||||
@ -437,7 +439,7 @@ module.exports = function (ngApp, events) {
|
|||||||
|
|
||||||
const pageId = Number($attrs.pageId);
|
const pageId = Number($attrs.pageId);
|
||||||
$scope.tags = [];
|
$scope.tags = [];
|
||||||
|
|
||||||
$scope.sortOptions = {
|
$scope.sortOptions = {
|
||||||
handle: '.handle',
|
handle: '.handle',
|
||||||
items: '> tr',
|
items: '> tr',
|
||||||
@ -729,20 +731,3 @@ module.exports = function (ngApp, events) {
|
|||||||
}]);
|
}]);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
const DropZone = require('dropzone');
|
const DropZone = require('dropzone');
|
||||||
const markdown = require('marked');
|
const markdown = require('marked');
|
||||||
|
|
||||||
const toggleSwitchTemplate = require('./components/toggle-switch.html');
|
|
||||||
const imagePickerTemplate = require('./components/image-picker.html');
|
|
||||||
const dropZoneTemplate = require('./components/drop-zone.html');
|
|
||||||
|
|
||||||
module.exports = function (ngApp, events) {
|
module.exports = function (ngApp, events) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,7 +12,12 @@ module.exports = function (ngApp, events) {
|
|||||||
ngApp.directive('toggleSwitch', function () {
|
ngApp.directive('toggleSwitch', function () {
|
||||||
return {
|
return {
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
template: toggleSwitchTemplate,
|
template: `
|
||||||
|
<div class="toggle-switch" ng-click="switch()" ng-class="{'active': isActive}">
|
||||||
|
<input type="hidden" ng-attr-name="{{name}}" ng-attr-value="{{value}}"/>
|
||||||
|
<div class="switch-handle"></div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
scope: true,
|
scope: true,
|
||||||
link: function (scope, element, attrs) {
|
link: function (scope, element, attrs) {
|
||||||
scope.name = attrs.name;
|
scope.name = attrs.name;
|
||||||
@ -77,7 +78,7 @@ module.exports = function (ngApp, events) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
element.find('button[type="submit"]').click(submitEvent);
|
element.find('button[type="submit"]').click(submitEvent);
|
||||||
|
|
||||||
function submitEvent(e) {
|
function submitEvent(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (attrs.subForm) scope.$eval(attrs.subForm);
|
if (attrs.subForm) scope.$eval(attrs.subForm);
|
||||||
@ -94,7 +95,22 @@ module.exports = function (ngApp, events) {
|
|||||||
ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
|
ngApp.directive('imagePicker', ['$http', 'imageManagerService', function ($http, imageManagerService) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
template: imagePickerTemplate,
|
template: `
|
||||||
|
<div class="image-picker">
|
||||||
|
<div>
|
||||||
|
<img ng-if="image && image !== 'none'" ng-src="{{image}}" ng-class="{{imageClass}}" alt="Image Preview">
|
||||||
|
<img ng-if="image === '' && defaultImage" ng-src="{{defaultImage}}" ng-class="{{imageClass}}" alt="Image Preview">
|
||||||
|
</div>
|
||||||
|
<button class="button" type="button" ng-click="showImageManager()">Select Image</button>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<button class="text-button" ng-click="reset()" type="button">Reset</button>
|
||||||
|
<span ng-show="showRemove" class="sep">|</span>
|
||||||
|
<button ng-show="showRemove" class="text-button neg" ng-click="remove()" type="button">Remove</button>
|
||||||
|
|
||||||
|
<input type="hidden" ng-attr-name="{{name}}" ng-attr-id="{{name}}" ng-attr-value="{{value}}">
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
scope: {
|
scope: {
|
||||||
name: '@',
|
name: '@',
|
||||||
resizeHeight: '@',
|
resizeHeight: '@',
|
||||||
@ -161,7 +177,11 @@ module.exports = function (ngApp, events) {
|
|||||||
ngApp.directive('dropZone', [function () {
|
ngApp.directive('dropZone', [function () {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
template: dropZoneTemplate,
|
template: `
|
||||||
|
<div class="dropzone-container">
|
||||||
|
<div class="dz-message">Drop files or click here to upload</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
scope: {
|
scope: {
|
||||||
uploadUrl: '@',
|
uploadUrl: '@',
|
||||||
eventSuccess: '=',
|
eventSuccess: '=',
|
||||||
@ -603,7 +623,7 @@ module.exports = function (ngApp, events) {
|
|||||||
let val = $input.val();
|
let val = $input.val();
|
||||||
let url = $input.attr('autosuggest');
|
let url = $input.attr('autosuggest');
|
||||||
let type = $input.attr('autosuggest-type');
|
let type = $input.attr('autosuggest-type');
|
||||||
|
|
||||||
// Add name param to request if for a value
|
// Add name param to request if for a value
|
||||||
if (type.toLowerCase() === 'value') {
|
if (type.toLowerCase() === 'value') {
|
||||||
let $nameInput = $input.closest('tr').find('[autosuggest-type="name"]').first();
|
let $nameInput = $input.closest('tr').find('[autosuggest-type="name"]').first();
|
||||||
@ -904,17 +924,3 @@ module.exports = function (ngApp, events) {
|
|||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user