add precommit hook, react eslint rules

This commit is contained in:
k88hudson 2016-02-01 13:20:30 -05:00
Родитель 6984dbe13a
Коммит 51897e1753
12 изменённых файлов: 209 добавлений и 61 удалений

1
.eslintignore Normal file
Просмотреть файл

@ -0,0 +1 @@
data/content/

Просмотреть файл

@ -1,7 +1,8 @@
{
// When adding items to this file please check for effects on sub-directories.
"plugins": [
"mozilla"
"mozilla",
"react"
],
"rules": {
"mozilla/components-imports": 1,
@ -11,6 +12,9 @@
"semi": [2, "always"],
"no-undef": 2,
},
"ecmaFeatures": {
"jsx": true
},
"env": {
"es6": true,
"node": true,
@ -20,5 +24,6 @@
"require": true,
"StopIteration": true,
"exports": true,
},
"__CONFIG__": true
}
}

2
.gitignore поставляемый
Просмотреть файл

@ -4,4 +4,4 @@ npm-debug.log
*.sw[po]
dist/
data/bundle.js
data/content/bundle.js

Просмотреть файл

@ -4,42 +4,7 @@
<meta charset="utf8">
</head>
<body>
<p>Activity Streams!</p>
<h2>Initial Links</h2>
<div id="initial-links">
</div>
<h2>Places Changes</h2>
<ol id="places-changes">
</ol>
<script>
window.dispatchEvent(new CustomEvent("content-to-addon", {
detail: JSON.stringify({type: "REQUEST_TOP_FRECENT_SITES"}),
}));
window.addEventListener("addon-to-content", payload => {
let msg = payload.detail;
let initialLinks = document.querySelector('#initial-links');
let placesChanges = document.querySelector('#places-changes');
if (!msg.type) {
console.warn(`Page.dispatch error: unknown message type`);
return;
}
switch(msg.type) {
case "RECEIVE_TOP_FRECENT_SITES":
initialLinks.innerHTML = `<pre>${JSON.stringify(msg.data, null, 2)}</pre>`;
break;
case "RECEIVE_PLACES_CHANGES":
var newListItem = document.createElement("li");
var newPre = document.createElement("pre");
newPre.innerText = JSON.stringify(msg.data, null, 2);
newListItem.appendChild(newPre);
placesChanges.appendChild(newListItem);
break;
}
});
</script>
<div id="root"></div>
<script src="http://localhost:1963/bundle.js"></script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,3 @@
{
}

Просмотреть файл

@ -36,22 +36,28 @@
"babel-preset-react": "^6.3.13",
"eslint": "^1.10.3",
"eslint-plugin-mozilla": "0.0.3",
"eslint-plugin-react": "^3.16.1",
"husky": "^0.10.2",
"jpm": "^1.0.5",
"json-loader": "^0.5.4",
"live-server": "^0.9.1",
"npm-run-all": "^1.5.1",
"webpack": "^2.0.6-beta",
"webpack-notifier": "^1.2.1",
"yamljs": "^0.2.4",
"yamscripts": "0.0.1"
"yamscripts": "^0.0.2"
},
"scripts": {
"start": "npm-run-all --parallel start:*",
"start:webpack": "webpack -w",
"start:jpm": "jpm run /usr/bin/firefox --prefs dev-prefs.json",
"package": "jpm xpi && mv @activity-streams-$npm_package_version.xpi dist/activity-streams-$npm_package_version.xpi",
"start:server": "live-server data/content --port=1963 --no-browser",
"run": "jpm run -b nightly",
"test": "npm-run-all test:*",
"test:lint": "eslint .",
"test:jpm": "jpm test",
"package": "jpm xpi && mv @activity-streams-$npm_package_version.xpi dist/activity-streams-$npm_package_version.xpi",
"precommit": "npm run test:lint && npm run yamscripts",
"prepush": "npm run test",
"help": "yamscripts help",
"yamscripts": "yamscripts compile",
"__": "# NOTE: THESE SCRIPTS ARE COMPILED!!! EDIT yamscripts.yml instead!!!"

Просмотреть файл

@ -1,11 +1,20 @@
const React = require("react");
const {connect} = require("react-redux");
const Main = (props) => {
return (<div>
Hello world!
</div>);
};
const Main = React.createClass({
render() {
const props = this.props;
return (<div>
Hello world!
<pre>
{JSON.stringify(props.Sites.frecent, null, 2)}
{JSON.stringify(props.Sites.changes, null, 2)}
</pre>
</div>);
}
});
function select(state) {
return state;

125
src/lib/redux-channel.js Normal file
Просмотреть файл

@ -0,0 +1,125 @@
const DEFAULT_TIMEOUT = 5000;
class Channel {
constructor(options = {}) {
Object.keys(options).forEach(key => {
this[key] = options[key];
});
this.callbacks = new Set();
this.timeouts = new Map();
window.addEventListener(this.incoming, this.runCallbacks.bind(this));
}
on(cb) {
this.callbacks.add(cb);
}
off(cb) {
if (cb) {
this.callbacks.delete(cb);
} else {
this.callbacks.clear();
}
}
runCallbacks(event) {
const action = event.detail;
this.callbacks.forEach(cb => cb(action));
}
broadcast(action) {
const event = new CustomEvent(this.outgoing, {detail: action});
window.dispatchEvent(event);
}
get connectStore() {
return reduxConnectStore => {
return function (reducer, initialState, enhancer) {
const store = reduxConnectStore(reducer, initialState, enhancer);
this.on(action => store.dispatch(action));
return store;
}.bind(this);
};
}
get middleware() {
return store => next => function (action) {
const meta = action.meta || {};
const timeouts = this.timeouts;
next(action.toJSON ? action.toJSON() : action);
if (timeouts.has(action.type)) {
clearTimeout(timeouts.get(action.type));
timeouts.delete(action.type);
}
if (meta.expect) {
const time = meta.timeout || DEFAULT_TIMEOUT;
const timeout = setTimeout(() => {
const error = new Error(`Expecting ${meta.expect} but it timed out after ${time}ms`);
error.name = "E_TIMEOUT";
store.dispatch({type: meta.expect, error: true, data: error});
}, time);
timeouts.set(meta.expect, timeout);
this.broadcast(action);
}
}.bind(this);
}
}
class ChannelAction {
// TODO
// marshalArgs(args, defn) {
//
// }
toJSON() {
const plainObject = {};
Object.keys(this).forEach(key => {
plainObject[key] = this[key];
});
return plainObject;
}
}
class RequestExpect extends ChannelAction {
constructor(type, query, expectType, timeout = RequestExpect.DEFAULT_TIMEOUT) {
super();
this.type = type;
this.query = this.query;
this.meta = {expect: expectType, timeout};
}
}
RequestExpect.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
class Request extends ChannelAction {
constructor(type, query) {
super();
this.type = type;
if (typeof query !== 'undefined') this.query = query;
}
}
class ResponseSuccess extends ChannelAction {
constructor(type, data) {
super();
this.type = type;
if (typeof data !== "undefined") this.data = data;
}
}
class ResponseError extends ChannelAction {
constructor(type, error) {
super();
this.type = type;
this.data = error;
this.error = true;
}
}
module.exports = {
Channel,
ActionTypes: {Request, RequestExpect, ResponseSuccess, ResponseError}
};

Просмотреть файл

@ -13,5 +13,19 @@ const Root = React.createClass({
}
});
// TODO: clean this up
window.dispatchEvent(new CustomEvent("content-to-addon", {
detail: JSON.stringify({type: "REQUEST_TOP_FRECENT_SITES"}),
}));
window.addEventListener("addon-to-content", payload => {
let msg = payload.detail;
if (!msg.type) {
console.warn(`Page.dispatch error: unknown message type`);
return;
}
store.dispatch(msg);
});
module.exports = Root;
// ReactDOM.render(<Root />, document.getElementById("root"));
ReactDOM.render(<Root />, document.getElementById("root"));

Просмотреть файл

@ -1,6 +1,15 @@
module.exports = {
// This is just placeholder for now
Main: (prevState = {}, action) => {
return prevState;
Sites: (prevState = {frecent: [], changes: []}, action) => {
const state = {};
switch(action.type) {
case "RECEIVE_TOP_FRECENT_SITES":
state.frecent = action.data;
break;
case "RECEIVE_PLACES_CHANGES":
state.changes = prevState.changes.concat(action.data);
break;
}
return Object.assign({}, prevState, state);
}
};

Просмотреть файл

@ -5,10 +5,10 @@ const path = require("path");
const yaml = require("yamljs");
const absolute = (relPath) => path.join(__dirname, relPath);
const srcDir = absolute("./src");
// const srcDir = absolute("./src");
const srcPath = absolute("./src/main.js");
const outputDir = absolute("./data");
const outputFilename = "bundle.js"
const outputDir = absolute("./data/content");
const outputFilename = "bundle.js";
let config = yaml.load("config.default.yml");
try {

Просмотреть файл

@ -1,16 +1,27 @@
scripts:
# This file compiles to package.json scripts.
# When you add or modify anything, you *MUST* run npm run yamscripts
# to compile your changes
scripts:
# start: Start watching/compiling assets,
# launch addon with jpm run
start:
_parallel: true
webpack: 'webpack -w'
jpm: 'jpm run /usr/bin/firefox --prefs dev-prefs.json'
webpack: webpack -w
server: live-server data/content --port=1963 --no-browser
# package: Build add-on
package: 'jpm xpi && mv @activity-streams-$npm_package_version.xpi dist/activity-streams-$npm_package_version.xpi'
run: jpm run -b nightly
# test: Run tests with eslint, jpm
test:
lint: 'eslint .'
jpm: 'jpm test'
lint: eslint .
jpm: jpm test
# package: Build add-on
package: jpm xpi && mv @activity-streams-$npm_package_version.xpi dist/activity-streams-$npm_package_version.xpi
# This is just to make sure we don't make commits with failing tests
# or uncompiled yamscripts.yml. Run automatically with husky.
precommit: =>test:lint && =>yamscripts
prepush: =>test