add precommit hook, react eslint rules
This commit is contained in:
Родитель
6984dbe13a
Коммит
51897e1753
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@
|
|||
{
|
||||
|
||||
}
|
12
package.json
12
package.json
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
};
|
16
src/main.js
16
src/main.js
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче