Skip to content

Commit

Permalink
Merge pull request #8 from homer0/next
Browse files Browse the repository at this point in the history
v2.0.0
  • Loading branch information
Leonardo Apiwan committed Apr 3, 2018
2 parents 38d4d2f + c9cb71b commit 58958f1
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 37 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,32 @@ If for some reason you are overwriting the [Babel](https://babeljs.io) configura
- `transform-es2015-classes`
- `transform-es2015-parameters`

### Default HTML

If you didn't create an HTML file for your AngularJS app, projext will create one for you and this plugin will take care of updating the contents of that HTML so you can run your app right away.

Now, there are a few options you can change in order to customize the way the HTML is generated: You can create a `frameworkOptions` property on your target configuration and set the following values:

```js
{
frameworkOptions: {
title: null,
appName: null,
strict: true,
cloak: true,
useBody: true,
mainComponent: 'main',
}
}
```

- `title`: A custom title for the HTML file. By default, projext, uses the name of the target.
- `appName`: A custom name of the [`ng-app` attribute](https://docs.angularjs.org/api/ng/directive/ngApp). By default, the plugin will convert te target name to `lowerCamelCase` and use that.
- `strict`: Whether or not you want to use the [`ng-strict-di` directive](https://docs.angularjs.org/api/ng/directive/ngApp#with-ngstrictdi-).
- `cloak`: Whether or not you want to use the [`ng-cloak` directive](https://docs.angularjs.org/api/ng/directive/ngCloak).
- `useBody`: Whether to add the `ng-app` attribute and the directives on the `<body />` or on a `<div />` inside it.
- `mainComponent`: The tag name of a component that should be inside the _"app tag"_.

## Development

Before doing anything, install the repository hooks:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "projext-plugin-webpack-angularjs",
"description": "Allows you to bundle an AngularJS project with projext using the webpack build engine.",
"homepage": "https://homer0.github.io/projext-plugin-webpack-angularjs/",
"version": "1.0.1",
"version": "2.0.0",
"repository": "homer0/projext-plugin-webpack-angularjs",
"author": "Leonardo Apiwan (@homer0) <me@homer0.com>",
"license": "MIT",
Expand Down
113 changes: 110 additions & 3 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,46 @@ class ProjextAngularJSPlugin {
* to update it.
* @type {string}
*/
this.eventName = 'webpack-js-rules-configuration-for-browser';
this.rulesEventName = 'webpack-js-rules-configuration-for-browser';
/**
* The name of the reducer event this service uses to intercept a browser target default HTML
* file settings and update them.
* @type {string}
*/
this.htmlSettingsEventName = 'target-default-html-settings';
/**
* The required value a target `framework` setting needs to have in order for the service to
* take action.
* @type {string}
*/
this.frameworkProperty = 'angularjs';
/**
* The default values for the options a target can use to customize the default HTML projext
* generates.
* @type {Object}
* @property {?string} title A custom value for the `<title />` tag. If the target
* doesn't define it, the plugin will use the one projext
* sets by default (The name of the target).
* @property {?string} appName The value of the `ng-app` attribute. If the target
* doesn't define it, the plugin will convert the name of
* the target to `lowerCamelCase` and use that instead.
* @property {boolean} strict Whether the app tag should include the `ng-strict-di`
* directive or not.
* @property {boolean} cloak Whether the app tag should include the `ng-cloak`
* directive or not.
* @property {boolean} useBody Whether or not the `body` should be used as the app tag
* (`ng-app`).
* @property {?string} mainComponent The name of a component that should be added inside the
* app tag.
*/
this.frameworkOptions = {
title: null,
appName: null,
strict: true,
cloak: true,
useBody: true,
mainComponent: 'main',
};
/**
* The name of the loader the plugin adds to the Webpack configuration.
* @type {string}
Expand All @@ -44,15 +77,22 @@ class ProjextAngularJSPlugin {
}
/**
* This is the method called when the plugin is loaded by projext. It just gets the events service
* and registers a listener for the reducer event that handles JS rules for browser targets.
* and registers the listeners for the reducer events that handle the JS rules for browser
* targets and generate a target the default HTML file.
* @param {Projext} app The projext main container.
*/
register(app) {
const events = app.get('events');
// Rules event.
events.on(
this.eventName,
this.rulesEventName,
(rules, params) => this.updateRules(rules, params.target)
);
// HTML event.
events.on(
this.htmlSettingsEventName,
(settings, target) => this.updateHTMLSettings(settings, target)
);
}
/**
* This method gets called when Projext reduces the JS rules for browser targets. It
Expand Down Expand Up @@ -95,6 +135,73 @@ class ProjextAngularJSPlugin {

return updatedRules;
}
/**
* Read the settings projext is using to build browser target default HTML file and update them
* based on the framework options defined by the target in order to run an AngularJS app.
* @param {TargetDefaultHTMLSettings} currentSettings The settings projext uses to build a target
* default HTML file.
* @param {Target} target The target information.
* @return {TargetDefaultHTMLSettings}
*/
updateHTMLSettings(currentSettings, target) {
let updatedSettings;
// If the target has a valid type and the right `framework`...
if (target.is.browser && target.framework === this.frameworkProperty) {
// ...copy the list of rules.
updatedSettings = Object.assign({}, currentSettings);
// Get a lowerCamelCase name for the AngularJS app by parsing the target name.
const appName = target.name.replace(/-(\w)/ig, (match, letter) => letter.toUpperCase());
// Merge the default options with any overwrite the target may have.
const options = Object.assign(
{},
this.frameworkOptions,
{ appName },
(target.frameworkOptions || {})
);
// If there's a custom title on the options, set it.
if (options.title) {
updatedSettings.title = options.title;
}

// Define the attributes list of the app tag.
const attributesList = [`ng-app="${options.appName}"`];
// - Check if the app will run with strict mode.
if (options.strict) {
attributesList.push('ng-strict-di');
}
// - Check if the app should hide the template while rendering.
if (options.cloak) {
attributesList.push('ng-cloak');
}
// Format the attributes list into a string.
const attributes = attributesList.join(' ');
/**
* If a main component was defined, generate an opening and closing tag for it, otherwise just
* keep it as an empty string.
*/
const mainComponent = options.mainComponent ?
`<${options.mainComponent}></${options.mainComponent}>` :
'';
// If the app tag should be the `body`...
if (options.useBody) {
// ...set the app tag attributes to the `body`.
updatedSettings.bodyAttributes = attributes;
// Set the main component as the contents of the `body`.
updatedSettings.bodyContents = mainComponent;
} else {
/**
* ...otherwise, create `div` with the app tag attributes, with the main component inside it
* and set it as the content of the `body`.
*/
updatedSettings.bodyContents = `<div id="app" ${attributes}>${mainComponent}</div>`;
}
} else {
// ...otherwise, just set to return the received settings.
updatedSettings = currentSettings;
}
// Return the updated settings.
return updatedSettings;
}
/**
* Finds the index of the Babel loader on a list of loaders.
* @param {Array} loaders The list of loaders.
Expand Down
5 changes: 5 additions & 0 deletions src/typedef.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@
* @external {Target}
* https://homer0.github.io/projext/typedef/index.html#static-typedef-Target
*/

/**
* @external {TargetDefaultHTMLSettings}
* https://homer0.github.io/projext/typedef/index.html#static-typedef-TargetDefaultHTMLSettings
*/
Loading

0 comments on commit 58958f1

Please sign in to comment.