Compare commits
7 commits
bdb2e4e02f
...
a027ba64a2
Author | SHA1 | Date | |
---|---|---|---|
a027ba64a2 | |||
ac76bf6715 | |||
6c72e6200f | |||
68378b1e86 | |||
84ada4d843 | |||
f734303a26 | |||
f1906b03cd |
23 changed files with 3496 additions and 40 deletions
|
@ -2,5 +2,8 @@
|
||||||
"name": "SilverStripe Environment",
|
"name": "SilverStripe Environment",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "silverstripe",
|
"service": "silverstripe",
|
||||||
"workspaceFolder": "/vscode/src/mantra"
|
"workspaceFolder": "/vscode/src/mantra",
|
||||||
|
"extensions": [
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin"
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ version: '3'
|
||||||
services:
|
services:
|
||||||
silverstripe:
|
silverstripe:
|
||||||
image: manuth/silverstripe-dev
|
image: manuth/silverstripe-dev
|
||||||
env_file: .env
|
env_file: devcontainer.env
|
||||||
ports:
|
ports:
|
||||||
- 8080:80
|
- 8080:80
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -11,6 +11,6 @@ services:
|
||||||
- ../test/website:/var/www/html
|
- ../test/website:/var/www/html
|
||||||
db:
|
db:
|
||||||
image: mysql:5
|
image: mysql:5
|
||||||
env_file: .env
|
env_file: devcontainer.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./mysql-data:/var/lib/mysql
|
- ./mysql-data:/var/lib/mysql
|
15
.gitignore
vendored
15
.gitignore
vendored
|
@ -51,9 +51,15 @@ typings/
|
||||||
# Output of 'npm pack'
|
# Output of 'npm pack'
|
||||||
*.tgz
|
*.tgz
|
||||||
|
|
||||||
|
# Output of 'composer archive'
|
||||||
|
*.tar
|
||||||
|
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
.cache
|
.cache
|
||||||
|
|
||||||
|
@ -77,3 +83,12 @@ vendor/
|
||||||
|
|
||||||
# MySQL cache
|
# MySQL cache
|
||||||
.devcontainer/mysql-data
|
.devcontainer/mysql-data
|
||||||
|
|
||||||
|
# Build files
|
||||||
|
/javascript/
|
||||||
|
/css/
|
||||||
|
/templates/
|
||||||
|
/assets/
|
||||||
|
|
||||||
|
# Test-theme
|
||||||
|
/test/website/themes/mantra
|
||||||
|
|
240
.gulp/Settings.ts
Normal file
240
.gulp/Settings.ts
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
import Path = require("upath");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides settings for building the project.
|
||||||
|
*/
|
||||||
|
export class Settings
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A value indicating whether the project should be built in watched mode.
|
||||||
|
*/
|
||||||
|
public Watch = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The target of the project-build.
|
||||||
|
*/
|
||||||
|
public Target: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the source-code root.
|
||||||
|
*/
|
||||||
|
private sourceRoot = "src";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the typescript-project.
|
||||||
|
*/
|
||||||
|
private typeScriptProjectRoot = "App";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the typescript-source.
|
||||||
|
*/
|
||||||
|
private typeScriptSourceRoot = "src";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to save the javascript-code to.
|
||||||
|
*/
|
||||||
|
private libraryPath = "javascript";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the theme-source.
|
||||||
|
*/
|
||||||
|
private themeSource = "Theme";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to save the css-code to.
|
||||||
|
*/
|
||||||
|
private stylePath = "css";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the root of the template-source.
|
||||||
|
*/
|
||||||
|
private templateSource = "Templates";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to save the templates to.
|
||||||
|
*/
|
||||||
|
private templatePath = "templates";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the test-directory.
|
||||||
|
*/
|
||||||
|
private testPath = "test";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the test-website.
|
||||||
|
*/
|
||||||
|
private testWebsitePath = "website";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of the `Settings` class.
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* The target of the project-build.
|
||||||
|
*/
|
||||||
|
public constructor(target: string)
|
||||||
|
{
|
||||||
|
this.Target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value indicating whether the debug-mode is enabled.
|
||||||
|
*/
|
||||||
|
public get Debug()
|
||||||
|
{
|
||||||
|
return this.Target === "Debug";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the solution.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public RootPath(...path: string[])
|
||||||
|
{
|
||||||
|
return Path.join(Path.dirname(__dirname), ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the source-code.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public SourceRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.sourceRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the typescript-project.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TypeScriptProjectRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.SourceRoot(this.typeScriptProjectRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the typescript-source.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TypeScriptSourceRoot(...path: string[])
|
||||||
|
{
|
||||||
|
return this.TypeScriptProjectRoot(this.typeScriptSourceRoot, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the directory to save the javascript-code to.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public LibraryPath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.libraryPath, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the theme-source.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public ThemeSource(...path: string[])
|
||||||
|
{
|
||||||
|
return this.SourceRoot(this.themeSource, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the directory to save the css-code to.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public StylePath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.stylePath, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the root of the template-source.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TemplateSource(...path: string[])
|
||||||
|
{
|
||||||
|
return this.SourceRoot(this.templateSource, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the directory to save the templates to.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TemplatePath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.templatePath, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the test-directory.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TestPath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.RootPath(this.testPath, ...path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path relative to the test-website.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The path to join.
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
* The joined path.
|
||||||
|
*/
|
||||||
|
public TestWebsitePath(...path: string[])
|
||||||
|
{
|
||||||
|
return this.TestPath(this.testWebsitePath, ...path);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,8 @@ import { TaskFunction } from "gulp";
|
||||||
*/
|
*/
|
||||||
declare global
|
declare global
|
||||||
{
|
{
|
||||||
interface Function extends TaskFunction
|
// tslint:disable-next-line: completed-docs
|
||||||
|
interface Function extends Partial<TaskFunction>
|
||||||
{ }
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
.vscode/extensions.json
vendored
Normal file
15
.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"adrianhumphreys.silverstripe",
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||||
|
"ms-vscode-remote.remote-containers"
|
||||||
|
],
|
||||||
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
|
||||||
|
"javascript.format.placeOpenBraceOnNewLineForControlBlocks": true,
|
||||||
|
"javascript.format.placeOpenBraceOnNewLineForFunctions": true,
|
||||||
|
"typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
|
||||||
|
"typescript.format.placeOpenBraceOnNewLineForControlBlocks": true,
|
||||||
|
"typescript.format.placeOpenBraceOnNewLineForFunctions": true
|
||||||
|
}
|
|
@ -36,18 +36,26 @@
|
||||||
"archive": {
|
"archive": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"/*.tar",
|
"/*.tar",
|
||||||
|
".devcontainer",
|
||||||
|
".gulp",
|
||||||
".gitignore",
|
".gitignore",
|
||||||
|
".vscode/",
|
||||||
"gulpfile.ts",
|
"gulpfile.ts",
|
||||||
"node_modules/",
|
"node_modules/",
|
||||||
"package-lock.json",
|
"package-lock.json",
|
||||||
"package.json",
|
"package.json",
|
||||||
"test/"
|
"src/",
|
||||||
|
"test/",
|
||||||
|
"tsconfig.json",
|
||||||
|
"tslint.json"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"scripts-dev": {
|
"scripts-dev": {
|
||||||
"post-install-cmd": [
|
"post-install-cmd": [
|
||||||
"npm install"
|
"npm install",
|
||||||
|
"@initialize",
|
||||||
|
"composer --working-dir=./test/website install"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
composer.lock
generated
2
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "22068a23fc6b360469aeccc3a344ead6",
|
"content-hash": "848468c4f4ad00ed3629fa3cbf2bea5b",
|
||||||
"packages": [],
|
"packages": [],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
|
|
358
gulpfile.ts
358
gulpfile.ts
|
@ -1,11 +1,363 @@
|
||||||
|
import browserify = require("browserify");
|
||||||
|
import log = require("fancy-log");
|
||||||
|
import FileSystem = require("fs-extra");
|
||||||
|
import { TaskFunction } from "gulp";
|
||||||
|
import gulp = require("gulp");
|
||||||
|
import gulpIf = require("gulp-if");
|
||||||
|
import rename = require("gulp-rename");
|
||||||
|
import sass = require("gulp-sass");
|
||||||
|
import terser = require("gulp-terser");
|
||||||
|
import merge = require("merge-stream");
|
||||||
|
import minimist = require("minimist");
|
||||||
|
import { Server, Socket } from "net";
|
||||||
|
import PromiseQueue = require("promise-queue");
|
||||||
|
import { parseArgsStringToArgv } from "string-argv";
|
||||||
|
import Path = require("upath");
|
||||||
|
import buffer = require("vinyl-buffer");
|
||||||
|
import vinylSourceStream = require("vinyl-source-stream");
|
||||||
|
import Watchify = require("watchify");
|
||||||
|
import { Settings } from "./.gulp/Settings";
|
||||||
import "./.gulp/TaskFunction";
|
import "./.gulp/TaskFunction";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port to listen for stop-requests.
|
||||||
|
*/
|
||||||
|
const watchConnectorPort = 50958;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message that is printed when starting the compilation in watch mode.
|
||||||
|
*/
|
||||||
|
const watchStartMessage = "Starting compilation in watch mode...";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message that is printed when starting an incremental compilation.
|
||||||
|
*/
|
||||||
|
const incrementalMessage = "File change detected. Starting incremental compilation...";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the message that is printed after finishing a compilation in watch mode.
|
||||||
|
*
|
||||||
|
* @param errorCount
|
||||||
|
* The number of errors which occurred.
|
||||||
|
*/
|
||||||
|
const watchFinishMessage = (errorCount: number) =>
|
||||||
|
{
|
||||||
|
return `Found ${errorCount} errors. Watching for file changes.`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments passed by the user.
|
||||||
|
*/
|
||||||
|
let options = ParseArgs(process.argv.slice(2));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the specified arguments.
|
||||||
|
*
|
||||||
|
* @param args
|
||||||
|
* The arguments to parse.
|
||||||
|
*/
|
||||||
|
function ParseArgs(args: string[])
|
||||||
|
{
|
||||||
|
return minimist(
|
||||||
|
args,
|
||||||
|
{
|
||||||
|
string: [
|
||||||
|
"target"
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
target: "t"
|
||||||
|
},
|
||||||
|
default: {
|
||||||
|
target: "Debug"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings for building the project.
|
||||||
|
*/
|
||||||
|
let settings = new Settings(options["target"]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the project.
|
* Initializes the project.
|
||||||
*/
|
*/
|
||||||
export function Initialize(done: () => void)
|
export async function Initialize()
|
||||||
{
|
{
|
||||||
done();
|
let directories = [
|
||||||
|
"javascript",
|
||||||
|
"css",
|
||||||
|
"templates",
|
||||||
|
"assets"
|
||||||
|
];
|
||||||
|
|
||||||
|
let themePath = settings.TestWebsitePath("themes", Path.basename(settings.RootPath()));
|
||||||
|
|
||||||
|
for (let directory of directories)
|
||||||
|
{
|
||||||
|
await FileSystem.emptyDir(settings.RootPath(directory));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await FileSystem.pathExists(themePath))
|
||||||
|
{
|
||||||
|
await FileSystem.remove(themePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
await require("create-symlink")(settings.RootPath(), themePath, { type: "junction" });
|
||||||
}
|
}
|
||||||
|
|
||||||
Initialize.description = "Initializes the project.";
|
Initialize.description = "Initializes the project.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the project in watched mode.
|
||||||
|
*/
|
||||||
|
export let Watch: TaskFunction = (done) =>
|
||||||
|
{
|
||||||
|
settings.Watch = true;
|
||||||
|
Build();
|
||||||
|
|
||||||
|
let server = new Server(
|
||||||
|
(socket) =>
|
||||||
|
{
|
||||||
|
socket.on(
|
||||||
|
"data",
|
||||||
|
(data) =>
|
||||||
|
{
|
||||||
|
let args = parseArgsStringToArgv(data.toString());
|
||||||
|
socket.destroy();
|
||||||
|
|
||||||
|
if (args[0] === "stop")
|
||||||
|
{
|
||||||
|
let options = ParseArgs(args.slice(1));
|
||||||
|
|
||||||
|
if (options["target"] === settings.Target)
|
||||||
|
{
|
||||||
|
server.close();
|
||||||
|
done();
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(watchConnectorPort);
|
||||||
|
};
|
||||||
|
|
||||||
|
Watch.description = "Builds the project in watched mode.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the project.
|
||||||
|
*/
|
||||||
|
export async function Build()
|
||||||
|
{
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
log.info(watchStartMessage);
|
||||||
|
gulp.watch(settings.ThemeSource("**"), Theme);
|
||||||
|
gulp.watch(settings.TemplateSource("**"), Templates);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
[
|
||||||
|
Library(),
|
||||||
|
Theme(),
|
||||||
|
Templates()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the TypeScript- and JavaScript-library.
|
||||||
|
*/
|
||||||
|
export async function Library()
|
||||||
|
{
|
||||||
|
let streams: Array<Promise<NodeJS.ReadWriteStream>> = [];
|
||||||
|
let queue = new PromiseQueue();
|
||||||
|
let tsConfigFile = settings.TypeScriptProjectRoot("tsconfig.json");
|
||||||
|
let tsConfig = require(tsConfigFile);
|
||||||
|
|
||||||
|
let optionBase: browserify.Options = {
|
||||||
|
...Watchify.args,
|
||||||
|
node: true,
|
||||||
|
ignoreMissing: true,
|
||||||
|
debug: settings.Debug
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let errorMessages: string[] = [];
|
||||||
|
let files = (tsConfig.files as string[]).map(
|
||||||
|
(file) => Path.relative(settings.TypeScriptSourceRoot(), settings.TypeScriptProjectRoot(file)));
|
||||||
|
|
||||||
|
for (let file of files)
|
||||||
|
{
|
||||||
|
let bundler = browserify(
|
||||||
|
{
|
||||||
|
...optionBase,
|
||||||
|
basedir: settings.LibraryPath(Path.dirname(file)),
|
||||||
|
entries: [
|
||||||
|
settings.TypeScriptSourceRoot(file)
|
||||||
|
],
|
||||||
|
standalone: Path.join(Path.dirname(file), Path.parse(file).name)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
bundler = Watchify(bundler);
|
||||||
|
}
|
||||||
|
|
||||||
|
bundler.plugin(
|
||||||
|
require("tsify"),
|
||||||
|
{
|
||||||
|
project: tsConfigFile
|
||||||
|
});
|
||||||
|
|
||||||
|
let bundle = async () =>
|
||||||
|
{
|
||||||
|
return new Promise<NodeJS.ReadWriteStream>(
|
||||||
|
(resolve) =>
|
||||||
|
{
|
||||||
|
let stream = bundler.bundle().on(
|
||||||
|
"error",
|
||||||
|
(error) =>
|
||||||
|
{
|
||||||
|
let message: string = error.message;
|
||||||
|
|
||||||
|
if (!errorMessages.includes(message))
|
||||||
|
{
|
||||||
|
errorMessages.push(message);
|
||||||
|
log.error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).pipe(
|
||||||
|
vinylSourceStream(Path.changeExt(file, "js"))
|
||||||
|
).pipe(
|
||||||
|
buffer()
|
||||||
|
).pipe(
|
||||||
|
gulpIf(
|
||||||
|
!settings.Debug,
|
||||||
|
terser()
|
||||||
|
)
|
||||||
|
).pipe(
|
||||||
|
gulp.dest(settings.LibraryPath())
|
||||||
|
);
|
||||||
|
|
||||||
|
stream.on(
|
||||||
|
"end",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if (settings.Watch && ((queue.getQueueLength() + queue.getPendingLength()) === 1))
|
||||||
|
{
|
||||||
|
log.info(watchFinishMessage(errorMessages.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMessages.splice(0, errorMessages.length);
|
||||||
|
resolve(stream);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (settings.Watch)
|
||||||
|
{
|
||||||
|
bundler.on(
|
||||||
|
"update",
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
if ((queue.getQueueLength() + queue.getPendingLength()) === 0)
|
||||||
|
{
|
||||||
|
log.info(incrementalMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.add(
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
return bundle();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let build = () => queue.add(bundle);
|
||||||
|
build.displayName = Build.displayName;
|
||||||
|
build.description = Build.description;
|
||||||
|
streams.push(build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return merge(await Promise.all(streams)) as NodeJS.ReadWriteStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Library.description = "Builds the TypeScript- and JavaScript-library.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the theme.
|
||||||
|
*/
|
||||||
|
export async function Theme()
|
||||||
|
{
|
||||||
|
return gulp.src(
|
||||||
|
settings.ThemeSource("main.scss"),
|
||||||
|
{
|
||||||
|
sourcemaps: settings.Debug,
|
||||||
|
base: settings.StylePath()
|
||||||
|
}).pipe(
|
||||||
|
sass({ importer: require("node-sass-tilde-importer") })
|
||||||
|
).pipe(
|
||||||
|
rename(
|
||||||
|
(parsedPath) =>
|
||||||
|
{
|
||||||
|
parsedPath.dirname = "";
|
||||||
|
parsedPath.basename = "mantra";
|
||||||
|
})
|
||||||
|
).pipe(
|
||||||
|
gulp.dest(
|
||||||
|
settings.StylePath(),
|
||||||
|
settings.Debug ?
|
||||||
|
{
|
||||||
|
sourcemaps: true
|
||||||
|
}
|
||||||
|
:
|
||||||
|
undefined)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Theme.description = "Builds the theme.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the templates.
|
||||||
|
*/
|
||||||
|
export function Templates()
|
||||||
|
{
|
||||||
|
return gulp.src(
|
||||||
|
settings.TemplateSource("**")).pipe(
|
||||||
|
gulp.dest(settings.TemplatePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Templates.description = "Builds the templates.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops a watch-task.
|
||||||
|
*/
|
||||||
|
export async function Stop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await new Promise(
|
||||||
|
(resolve, reject) =>
|
||||||
|
{
|
||||||
|
let client = new Socket();
|
||||||
|
|
||||||
|
client.connect(
|
||||||
|
watchConnectorPort,
|
||||||
|
"localhost",
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
client.write(`stop -t ${settings.Target}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on("close", resolve);
|
||||||
|
client.on("error", reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
log.info("The specified task is not running.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop.description = "Stops a watch-task";
|
2694
package-lock.json
generated
2694
package-lock.json
generated
File diff suppressed because it is too large
Load diff
43
package.json
43
package.json
|
@ -5,9 +5,50 @@
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@manuth/tsconfig": "^1.2.2",
|
||||||
|
"@manuth/tslint-presets": "^1.0.4",
|
||||||
|
"@types/bootstrap": "^4.3.1",
|
||||||
|
"@types/browserify": "^12.0.36",
|
||||||
|
"@types/fancy-log": "^1.3.1",
|
||||||
|
"@types/fs-extra": "^8.0.0",
|
||||||
"@types/gulp": "^4.0.6",
|
"@types/gulp": "^4.0.6",
|
||||||
|
"@types/gulp-if": "0.0.33",
|
||||||
|
"@types/gulp-rename": "0.0.33",
|
||||||
|
"@types/gulp-sass": "^4.0.0",
|
||||||
|
"@types/gulp-terser": "^1.2.0",
|
||||||
|
"@types/jquery": "^3.3.31",
|
||||||
|
"@types/merge-stream": "^1.1.2",
|
||||||
|
"@types/minimist": "^1.2.0",
|
||||||
|
"@types/node": "^12.7.11",
|
||||||
|
"@types/promise-queue": "^2.2.0",
|
||||||
|
"@types/vinyl-buffer": "^1.0.0",
|
||||||
|
"@types/vinyl-source-stream": "0.0.30",
|
||||||
|
"@types/watchify": "^3.7.4",
|
||||||
|
"bootstrap": "^4.3.1",
|
||||||
|
"browserify": "^16.5.0",
|
||||||
|
"create-symlink": "^1.0.0",
|
||||||
|
"fancy-log": "^1.3.3",
|
||||||
|
"fs-extra": "^8.1.0",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
|
"gulp-if": "^3.0.0",
|
||||||
|
"gulp-rename": "^1.4.0",
|
||||||
|
"gulp-sass": "^4.0.2",
|
||||||
|
"gulp-terser": "^1.2.0",
|
||||||
|
"jquery": "^3.4.1",
|
||||||
|
"merge-stream": "^2.0.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"node-sass-tilde-importer": "^1.0.2",
|
||||||
|
"popper.js": "^1.15.0",
|
||||||
|
"promise-queue": "^2.2.5",
|
||||||
|
"string-argv": "^0.3.1",
|
||||||
"ts-node": "^8.4.1",
|
"ts-node": "^8.4.1",
|
||||||
"typescript": "^3.6.3"
|
"tsify": "^4.0.1",
|
||||||
|
"tslint": "^5.20.0",
|
||||||
|
"typescript": "^3.6.3",
|
||||||
|
"typescript-tslint-plugin": "^0.5.4",
|
||||||
|
"upath": "^1.2.0",
|
||||||
|
"vinyl-buffer": "^1.0.1",
|
||||||
|
"vinyl-source-stream": "^2.0.0",
|
||||||
|
"watchify": "^3.11.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3
src/App/src/main.ts
Normal file
3
src/App/src/main.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import "bootstrap";
|
||||||
|
import "jquery";
|
||||||
|
import "popper.js";
|
13
src/App/tsconfig.json
Normal file
13
src/App/tsconfig.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"src/main.ts"
|
||||||
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "src",
|
||||||
|
"lib": [
|
||||||
|
"es7",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"target": "es5"
|
||||||
|
}
|
||||||
|
}
|
0
src/Templates/Layout/Page.ss
Normal file
0
src/Templates/Layout/Page.ss
Normal file
45
src/Templates/Page.ss
Normal file
45
src/Templates/Page.ss
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html class="h-100">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<% base_tag %>
|
||||||
|
$MetaTags()
|
||||||
|
<% require themedCSS("mantra") %>
|
||||||
|
<% require themedJavascript("mantra") %>
|
||||||
|
</head>
|
||||||
|
<body class="d-flex flex-column h-100">
|
||||||
|
<% if $Menu(1) %>
|
||||||
|
<div class="col-1">
|
||||||
|
<nav>
|
||||||
|
<div class="active">
|
||||||
|
<a>
|
||||||
|
$Title
|
||||||
|
</a>
|
||||||
|
<ul class="nav bd-sidenav">
|
||||||
|
<% loop $Menu(1) %>
|
||||||
|
<li class="$LinkingMode">
|
||||||
|
<a href="$Link">
|
||||||
|
$MenuTitle
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<% end_loop %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<% end_if %>
|
||||||
|
<main role="main" class="col-11 flex-shrink-0">
|
||||||
|
<div class="container">
|
||||||
|
<% loop $Menu(1) %>
|
||||||
|
<li><a class="$LinkingMode" href="$Link" title="Go to the $Title page">$MenuTitle</a></li>
|
||||||
|
<% end_loop %>
|
||||||
|
<h1 class="display-4">
|
||||||
|
$MenuTitle
|
||||||
|
</h1>
|
||||||
|
$Content
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
src/Theme/main.scss
Normal file
1
src/Theme/main.scss
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import "~bootstrap/scss/bootstrap";
|
|
@ -3,6 +3,6 @@ Name: mytheme
|
||||||
---
|
---
|
||||||
SilverStripe\View\SSViewer:
|
SilverStripe\View\SSViewer:
|
||||||
themes:
|
themes:
|
||||||
|
- 'mantra'
|
||||||
- '$public'
|
- '$public'
|
||||||
- 'simple'
|
|
||||||
- '$default'
|
- '$default'
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
"phpunit/phpunit": "^5.7"
|
"phpunit/phpunit": "^5.7"
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
|
"expose": [
|
||||||
|
"themes/mantra/assets",
|
||||||
|
"themes/mantra/css",
|
||||||
|
"themes/mantra/javascript"
|
||||||
|
],
|
||||||
"resources-dir": "_resources",
|
"resources-dir": "_resources",
|
||||||
"project-files-installed": [
|
"project-files-installed": [
|
||||||
"app/.htaccess",
|
"app/.htaccess",
|
||||||
|
|
44
test/website/composer.lock
generated
44
test/website/composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "7ff31cbd9aa5ee75c9624d2bb8c3bc5f",
|
"content-hash": "0ab3e4aaf71526993c3dbb3ea6179605",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bramus/ansi-php",
|
"name": "bramus/ansi-php",
|
||||||
|
@ -2216,16 +2216,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v3.4.31",
|
"version": "v3.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache.git",
|
"url": "https://github.com/symfony/cache.git",
|
||||||
"reference": "6a9cc3ed7f61c6c2bc042d0594cdb807b6fea62c"
|
"reference": "5c7bd827617fcb9b13e04e423c31c0fb0bcf0160"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache/zipball/6a9cc3ed7f61c6c2bc042d0594cdb807b6fea62c",
|
"url": "https://api.github.com/repos/symfony/cache/zipball/5c7bd827617fcb9b13e04e423c31c0fb0bcf0160",
|
||||||
"reference": "6a9cc3ed7f61c6c2bc042d0594cdb807b6fea62c",
|
"reference": "5c7bd827617fcb9b13e04e423c31c0fb0bcf0160",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2282,20 +2282,20 @@
|
||||||
"caching",
|
"caching",
|
||||||
"psr6"
|
"psr6"
|
||||||
],
|
],
|
||||||
"time": "2019-08-26T07:52:58+00:00"
|
"time": "2019-09-29T21:19:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/config",
|
"name": "symfony/config",
|
||||||
"version": "v3.4.31",
|
"version": "v3.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/config.git",
|
"url": "https://github.com/symfony/config.git",
|
||||||
"reference": "24a60c0d7ad98a0fa5d1f892e9286095a389404f"
|
"reference": "717ad66b5257e9752ae3c5722b5810bb4c40b236"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/config/zipball/24a60c0d7ad98a0fa5d1f892e9286095a389404f",
|
"url": "https://api.github.com/repos/symfony/config/zipball/717ad66b5257e9752ae3c5722b5810bb4c40b236",
|
||||||
"reference": "24a60c0d7ad98a0fa5d1f892e9286095a389404f",
|
"reference": "717ad66b5257e9752ae3c5722b5810bb4c40b236",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2346,11 +2346,11 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Config Component",
|
"description": "Symfony Config Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2019-08-26T07:52:57+00:00"
|
"time": "2019-09-19T15:32:51+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/filesystem",
|
"name": "symfony/filesystem",
|
||||||
"version": "v4.3.4",
|
"version": "v4.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/filesystem.git",
|
"url": "https://github.com/symfony/filesystem.git",
|
||||||
|
@ -2400,16 +2400,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/finder",
|
"name": "symfony/finder",
|
||||||
"version": "v3.4.31",
|
"version": "v3.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/finder.git",
|
"url": "https://github.com/symfony/finder.git",
|
||||||
"reference": "1fcad80b440abcd1451767349906b6f9d3961d37"
|
"reference": "2b6a666d6ff7fb65d10b97d817c8e7930944afb9"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/finder/zipball/1fcad80b440abcd1451767349906b6f9d3961d37",
|
"url": "https://api.github.com/repos/symfony/finder/zipball/2b6a666d6ff7fb65d10b97d817c8e7930944afb9",
|
||||||
"reference": "1fcad80b440abcd1451767349906b6f9d3961d37",
|
"reference": "2b6a666d6ff7fb65d10b97d817c8e7930944afb9",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2445,7 +2445,7 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2019-08-14T09:39:58+00:00"
|
"time": "2019-09-01T21:32:23+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-apcu",
|
"name": "symfony/polyfill-apcu",
|
||||||
|
@ -2686,16 +2686,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/yaml",
|
"name": "symfony/yaml",
|
||||||
"version": "v3.4.31",
|
"version": "v3.4.32",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/yaml.git",
|
"url": "https://github.com/symfony/yaml.git",
|
||||||
"reference": "3dc414b7db30695bae671a1d86013d03f4ae9834"
|
"reference": "768f817446da74a776a31eea335540f9dcb53942"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/3dc414b7db30695bae671a1d86013d03f4ae9834",
|
"url": "https://api.github.com/repos/symfony/yaml/zipball/768f817446da74a776a31eea335540f9dcb53942",
|
||||||
"reference": "3dc414b7db30695bae671a1d86013d03f4ae9834",
|
"reference": "768f817446da74a776a31eea335540f9dcb53942",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -2741,7 +2741,7 @@
|
||||||
],
|
],
|
||||||
"description": "Symfony Yaml Component",
|
"description": "Symfony Yaml Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"time": "2019-08-20T13:31:17+00:00"
|
"time": "2019-09-10T10:38:46+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webonyx/graphql-php",
|
"name": "webonyx/graphql-php",
|
||||||
|
|
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"extends": "@manuth/tsconfig/recommended",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": [
|
||||||
|
"es7"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "typescript-tslint-plugin"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"target": "es5"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"./gulpfile.ts"
|
||||||
|
]
|
||||||
|
}
|
6
tslint.json
Normal file
6
tslint.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"extends": "@manuth/tslint-presets/recommended",
|
||||||
|
"rules": {
|
||||||
|
"interface-name": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue