Skip to content

Commit

Permalink
Merged release/1.0.0 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Igloczek committed Oct 24, 2016
2 parents 2c78d70 + ff0a34b commit ec556b0
Show file tree
Hide file tree
Showing 22 changed files with 9,844 additions and 12,149 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{js, json}]
indent_style = space
indent_size = 2
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
^4.0.0
>=6.9.1 <7.0.0
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: node_js
node_js: 4
node_js: 6
cache:
directories:
- test/node_modules
Expand Down
44 changes: 24 additions & 20 deletions readme.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,38 @@ Set of front-end tools for Magento 2, based on Gulp.js
## Questions
If you have any questions about this project let's go to offical Magento forum - [Less to Sass Community Project](https://community.magento.com/t5/Less-to-Sass-Community-Project/bd-p/less-to-sass)

## LESS themes support
LESS support was droped in version 1.0.0. Fell free to use older version (0.11.4 and lower) or create fork and customize newer versions to fit your needs.

## NPM and Yarn support
Up from version 1.0.0 we are supporting both Node.js packages managers. We are using `npm-shrinkwrap.json` and `yarn.lock` to keep modules in safe versions all the time.

## Requirements
* `node >= 4.0.0` - heavily recommend using current LTS (v4 branch), not a latest version.
Using [avn](https://github.com/wbyoung/avn) or [nvm](https://github.com/creationix/nvm)? Great! We've included a `.node-version` file for you.
* Gulp CLI global package - `npm install -g gulp-cli`
* Magento 2 project :smile:
* Node.js LTS version (v6 branch). We recommend to use [avn](https://github.com/wbyoung/avn) to automate version switching. Required configuration is already added to repository as `.node-version` file.
* Gulp CLI global package - `npm install -g gulp-cli` or `yarn global add gulp-cli`
* Magento 2 project with SASS based theme i.e. [SASS version of "Blank"](https://github.com/SnowdogApps/magento2-theme-blank-sass)

## Installation
1. Run `composer require snowdog/frontools`
2. Go to package directory `/vendor/snowdog/frontools`
3. Run `npm install`
3. Run `npm install` or `yarn`
4. Decide where you want to keep your config files.
You can store them in frontools `config` dir or `/dev/tools/frontools/config`.
There is a `gulp setup` task to copy all sample config files from the `config` to `/dev/tools/frontools/config` and create a convenient symlink in project root.
If you want to keep config files inside frontools `config` dir, you have to handle this manually.
5. Define your themes in `themes.json`

## Optional steps
## `themes.json` structure
First of all check `config/themes.json.sample`
- `src` - full path to theme
- `dest` - full path to `pub/static/[theme_area]/[theme_vendor]/[theme_name]`
- `parent` - name of parent theme
- `locale` - array of available locales
- `localeOverwrites` - set to `true` only if your theme have per locale customizations
- `lang` - define styles lang want to use for processing, should be same as files extension. Out of the box Frontools supports only `scss`
- `postcss` - (optional) PostCSS plugins config - have to be an array

## Optional configurations for 3rd party plugins
* Create [browserSync](https://www.browsersync.io/) configuration
* Create [eslint](https://github.com/adametry/gulp-eslint) configuration
* Create [sass-lint](https://github.com/sasstools/sass-lint) configuration
Expand All @@ -32,10 +47,10 @@ If you want to keep config files inside frontools `config` dir, you have to hand
* `browser-sync` - run [browserSync](https://www.browsersync.io/)- do not run this task separately, it's just a part of `dev` task
* `clean` - Removes `/pub/static` folder
* `default` - type `gulp` to see this readme in console
* `deploy` - Resolve theme inheritance of static assets (i.e. fonts, images) symlinking them to `pub` dir. For default LESS themes it's just a wrapper of `bin/magento dev:source-theme:deploy`.
* `deploy` - Resolve theme inheritance of static assets (i.e. fonts, images) symlinking them to `pub` dir.
* `--theme name` - Deploy single theme
* `--prod` - Copy files instead of making symlinks
* `dev` - Runs `browser-sync` and `watch` tasks
* `dev` - Runs `browser-sync`, `inheritance` and `watch` tasks
* `--theme name` - Process single theme
* `--maps` - Toggles source maps generation
* `--prod` - Production output - minifies styles
Expand All @@ -58,15 +73,4 @@ If you want to keep config files inside frontools `config` dir, you have to hand
* `sasslint` - Run [sass-lint](https://github.com/sasstools/sass-lint) based tests
* `--theme name` - Process single theme
* `--ci - Enable throwing errors, useful in CI/CD pipelines`

## `config/themes.json` structure
First of all check `config/themes.json.sample`
- `src` - full path to theme
- `dest` - full path to `pub/static/[theme_area]/[theme_vendor]/[theme_name]`
- `parent` - name of parent theme - not available in themes with `default` flag
- `locale` - array of available locales
- `lang` - define styles lang want to use for processing, should be same as files extension. Out of the box Frontools supports `less` and `scss`
- `default` - (required for default Magento LESS themes) if your theme use default PHP based processing via `bin/magento dev:source-theme:deploy` set this param to `true`
- `area`, `vendor`, `name` - (required for default Magento LESS themes) self-descriptive
- `files` - (required for default Magento LESS themes) Array of LESS files to process
- `postcss` - (optional) PostCSS plugins config - have to be an array
* `inheritance` - Create necessary symlinks to resolve theme styles inheritance and make base for styles processing. You have to run in before sytles compilation and after adding new files.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "snowdog/frontools",
"description": "Set of front-end tools for Magento 2, based on Gulp.js",
"version": "0.11.4",
"version": "1.0.0",
"license": "MIT",
"type": "magento2-component"
}
61 changes: 9 additions & 52 deletions config/themes.json.sample
Original file line number Diff line number Diff line change
@@ -1,61 +1,18 @@
{
"backend": {
"src" : "app/design/adminhtml/Magento/backend",
"dest" : "pub/static/adminhtml/Magento/backend",
"locale" : ["en_US"],
"lang" : "less",
"default": true,
"area" : "adminhtml",
"vendor" : "Magento",
"name" : "backend",
"files" : [
"css/styles-old",
"css/styles"
]
},
"blank": {
"src" : "app/design/frontend/Magento/blank",
"dest" : "pub/static/frontend/Magento/blank",
"locale" : ["en_US"],
"lang" : "less",
"default": true,
"area" : "frontend",
"vendor" : "Magento",
"name" : "blank",
"files" : [
"css/styles-m",
"css/styles-l",
"css/email",
"css/email-inline"
]
},
"luma": {
"src" : "app/design/frontend/Magento/luma",
"dest" : "pub/static/frontend/Magento/luma",
"locale" : ["en_US"],
"lang" : "less",
"default": true,
"area" : "frontend",
"vendor" : "Magento",
"name" : "luma",
"files" : [
"css/styles-m",
"css/styles-l"
]
},
"sass-blank": {
"src" : "vendor/snowdog/theme-blank-sass",
"dest" : "pub/static/frontend/Snowdog/blank",
"locale" : ["en_US", "pl_PL"],
"locale" : ["en_US"],
"lang" : "scss",
"postcss": ["plugins.autoprefixer()"]
},
"sass-custom": {
"src" : "vendor/snowdog/theme-custom",
"dest" : "pub/static/frontend/Snowdog/custom",
"parent" : "sass-blank",
"locale" : ["en_US", "pl_PL"],
"lang" : "scss",
"postcss": ["plugins.autoprefixer()"]
"custom": {
"src" : "vendor/snowdog/theme-custom",
"dest" : "pub/static/frontend/Snowdog/custom",
"parent" : "blank",
"locale" : ["en_US", "pl_PL"],
"localeOverwrites": true,
"lang" : "scss",
"postcss" : ["plugins.autoprefixer()"]
}
}
17 changes: 8 additions & 9 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ const gulp = require('gulp'),
rename : {
'browser-sync' : 'browserSync',
'fs-extra' : 'fs',
'gulp-multi-dest' : 'multiDest',
'js-yaml' : 'yaml',
'marked-terminal' : 'markedTerminal',
'postcss-reporter': 'reporter',
'run-sequence' : 'runSequence',
'js-yaml' : 'yaml'
'run-sequence' : 'runSequence'
}
}),
config = {
Expand All @@ -27,14 +28,12 @@ require('gulp-task-loader')({
configs: config
});

// Define task for each theme, locale, lang, processing type etc.
// Define task for each theme
// Gulp can't run same task in parallel, so we need different names
Object.keys(config.themes).forEach(name => {
const theme = config.themes[name];
theme.locale.forEach(locale => {
gulp.task(
theme.lang + ':' + name + ':' + locale,
require('./helper/' + theme.lang)(gulp, plugins, config, name, locale)
);
});
gulp.task(
theme.lang + ':' + name,
require('./helper/' + theme.lang)(gulp, plugins, config, name)
);
});
60 changes: 34 additions & 26 deletions helper/dependency-tree-builder.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
'use strict';
module.exports = function(theme, file, plugins) { // eslint-disable-line func-names
function findDependencies(file, dependencyTree) {
const content = plugins.fs.readFileSync(file, 'utf8'),
path = file.replace(/(.*)\/.*/g, '$1'),
regex = /(?:\n@import )(?:'|")(.*)(?:'|")/g;
if (plugins.fs.existsSync(file)) {
const content = plugins.fs.readFileSync(file, 'utf8'),
path = file.replace(/(.*)\/.*/g, '$1'),
regex = /(?:\n@import )(?:'|")(.*)(?:'|")/g;

let result = regex.exec(content),
imports = [];
let result = regex.exec(content),
imports = [];

while (result) {
let fullPath = '';
if (result[1].match(/\.\.\//g)) {
let parentPath = path,
filePath = result[1];
while (result) {
let fullPath = '';
if (result[1].includes('../')) {
let parentPath = path,
filePath = result[1];

while (filePath.match(/\.\.\//g)) {
parentPath = parentPath.replace(/\/[^\/]+$/g, '');
filePath = filePath.replace(/\.\.\//, '');
fullPath = parentPath + '/' + filePath;
while (filePath.includes('../')) {
parentPath = parentPath.replace(/\/[^\/]+$/g, '');
filePath = filePath.replace(/\.\.\//, '');
const filePathParts = /(.*)\/(.*)/g.exec(filePath);
fullPath = parentPath + '/' + filePathParts[1] + '/_' + filePathParts[filePathParts.length - 1] + '.' + theme.lang;
}
}
else {
if (result[1].includes('/')) {
const filePath = /(.*)\/(.*)/g.exec(result[1]);
fullPath = path + '/' + filePath[1] + '/_' + filePath[filePath.length - 1] + '.' + theme.lang;
}
else {
fullPath = path + '/_' + result[1] + '.' + theme.lang;
}
}
imports.push(fullPath);
result = regex.exec(content);
}
else {
fullPath = path + '/' + result[1];
}
imports.push(fullPath);
result = regex.exec(content);
}

imports.forEach(el => {
imports = imports.concat(findDependencies(el, dependencyTree));
});

dependencyTree = dependencyTree.concat(file);
dependencyTree = dependencyTree.concat(imports);
imports.forEach(el => {
imports = imports.concat(findDependencies(el, dependencyTree));
});

dependencyTree = dependencyTree.concat(file);
dependencyTree = dependencyTree.concat(imports);
}
return dependencyTree;
}

Expand Down
90 changes: 90 additions & 0 deletions helper/inheritance-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use strict';
module.exports = function(plugins, config, name) { // eslint-disable-line func-names
const theme = config.themes[name],
themeSrc = config.projectPath + theme.src,
themeDest = config.projectPath + 'var/view_preprocessed/frontools' + theme.dest.replace('pub/static', '');

// Clean destination dir before generating new symlinks
plugins.fs.removeSync(themeDest);

function createSymlink(srcPath, destPath) {
try {
plugins.fs.ensureFileSync(destPath);
plugins.fs.unlinkSync(destPath);
}
finally {
plugins.fs.symlinkSync(srcPath, destPath);
}
}

// Create symlinks for themes without any per locale modifcations
if (!theme.localeOverwrites) {
// If theme have parent, create symlinks to all avaliabe files and then overwite only neccessary
if (theme.parent) {
const parentSrc = config.projectPath + config.themes[theme.parent].src;
plugins.globby.sync([
parentSrc + '/**/*.' + theme.lang,
'!/**/node_modules/**'
]).forEach(srcPath => {
createSymlink(
srcPath,
themeDest + srcPath.replace(parentSrc, '').replace('/web', '')
);
});
}

// Create symlinks to all files in this theme. Will overwritte parent symlinks if exist.
plugins.globby.sync([
themeSrc + '/**/*.' + theme.lang,
'!/**/node_modules/**'
]).forEach(srcPath => {
createSymlink(
srcPath,
themeDest + srcPath.replace(themeSrc, '')
);
});
}
// Create symlinks for themes with per locale modifcations
else {
// We have to handle every locale independly, b/c of possible overwrites
theme.locale.forEach(locale => {
// If theme have parent, create symlinks to all avaliabe files and then overwitte only neccessary
if (theme.parent) {
const parentSrc = config.projectPath + config.themes[theme.parent].src;
plugins.globby.sync([
parentSrc + '/**/*.' + theme.lang,
'!/**/i18n/**',
'!/**/node_modules/**'
]).forEach(srcPath => {
createSymlink(
srcPath,
themeDest + '/' + locale + srcPath.replace(parentSrc, '').replace('/web', '')
);
});
}

// Create symlinks to all files in this theme. Will overwritte parent symlinks if exist.
plugins.globby.sync([
themeSrc + '/**/*.' + theme.lang,
'!/**/i18n/**',
'!/**/node_modules/**'
]).forEach(srcPath => {
createSymlink(
srcPath,
themeDest + '/' + locale + srcPath.replace(themeSrc, '')
);
});

// Overwritte parent/current theme symlinks with locale specific files
plugins.globby.sync([
themeSrc + '/**/i18n/' + locale + '/**/*.' + theme.lang,
'!/**/node_modules/**'
]).forEach(srcPath => {
createSymlink(
srcPath,
themeDest + '/' + locale + srcPath.replace(themeSrc, '').replace('/i18n/' + locale, '')
);
});
});
}
};
Loading

0 comments on commit ec556b0

Please sign in to comment.