libre
Version:
World's lightest CMS
724 lines (555 loc) • 23.8 kB
JavaScript
(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 5);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = require("lodash");
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
exports.goto = goto;
var _reactRouter = __webpack_require__(11);
var _lodash = __webpack_require__(0);
var _lodash2 = _interopRequireDefault(_lodash);
var _reactGa = __webpack_require__(10);
var _reactGa2 = _interopRequireDefault(_reactGa);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function goto(path) {
_reactRouter.browserHistory.push(path);
};
var Packet = function () {
function Packet(_ref) {
var category = _ref.category,
action = _ref.action,
label = _ref.label,
data = _ref.data;
_classCallCheck(this, Packet);
_lodash2.default.assign(this, { category: category, action: action, label: label, data: data });
}
_createClass(Packet, [{
key: 'ga',
get: function get() {
return {
category: this.category,
action: this.action,
label: this.label,
value: this.data
};
}
}]);
return Packet;
}();
var Dealer = function () {
function Dealer() {
_classCallCheck(this, Dealer);
}
_createClass(Dealer, [{
key: 'init',
value: function init(gaID) {
_reactGa2.default.initialize(gaID);
}
}, {
key: 'call',
value: function call(packetData) {
var packet = new Packet(packetData);
_reactGa2.default.event(packet.ga);
// console.log('[DEALER] EVENT:', packet.ga);
}
}, {
key: 'page',
value: function page() {
_reactGa2.default.set({ page: window.location.pathname });
_reactGa2.default.pageview(window.location.pathname);
console.log('[LIBRE] PAGE: [' + window.location.pathname + ']');
}
}]);
return Dealer;
}();
var D = new Dealer();
exports.default = D;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _axios = __webpack_require__(6);
var _axios2 = _interopRequireDefault(_axios);
var _lodash = __webpack_require__(0);
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Libre = function () {
function Libre() {
_classCallCheck(this, Libre);
this.path = '/libre';
this.raw = {};
this.typed = {};
this.grouped = {};
this.typeMap = {};
this.plugins = {};
}
_createClass(Libre, [{
key: 'setup',
value: function setup(_ref) {
var typeMap = _ref.typeMap,
plugins = _ref.plugins;
if (typeMap) this.typeMap = typeMap;
if (plugins) this.plugins = plugins;
}
//retrieve a simple piece of content based on unique id
}, {
key: 'get',
value: function get(key, applyPlugins) {
var _this = this;
var c = this.raw[key];
if (c == null) return [];
if (!applyPlugins || !c.content) return c.content || [];
//if applyPlugins, also call process to run string interpolation plugins
//content is a special field and is an automatic array of lines (split on \n) from the source Sheet
//so we also use spread operator to flatten the output into a single array of pieces
var processed = [];
c.content.map(function (line) {
return processed.push.apply(processed, _toConsumableArray(_this.process(line)));
});
return processed;
}
//retrieve a model for structured content based on a path
}, {
key: 'getTyped',
value: function getTyped(path, type) {
var items = _lodash2.default.filter(this.typed, function (t) {
return t.path == path && t.constructor.name == type.name;
});
return items.length > 0 ? items[0] : {};
}
//create array of typed objects corresponding to a tab in the spreadsheet and given model class
}, {
key: 'model',
value: function model(sheet, type) {
var _this2 = this;
var raw = _lodash2.default.filter(this.raw, { sheet: sheet });
var items = [];
raw.map(function (json) {
var typed = new type(json, _this2);
_this2.typed[typed.id] = typed;
items.push(typed);
});
this.grouped[sheet] = items;
return items;
}
}, {
key: 'load',
value: function load(success) {
var _this3 = this;
_axios2.default.get(this.path).then(function (_ref2) {
var data = _ref2.data;
_this3.init(data);
if (typeof success == 'function') success(_this3);
});
}
}, {
key: 'push',
value: function push(tab, row, success) {
_axios2.default.post(this.path + '/push', { tab: tab, row: row }).then(function (result) {
if (typeof success == 'function') success(result);
});
}
}, {
key: 'init',
value: function init(data) {
var _this4 = this;
var loaded = [];
//add the sheet name to the source data
_lodash2.default.forOwn(data, function (tab, sheet) {
_lodash2.default.forOwn(tab, function (item) {
return item.sheet = sheet;
});
loaded.push(sheet);
//merge results into overall content store
_lodash2.default.assign(_this4.raw, tab);
});
console.log('[LIBRE] Content loaded for [' + loaded.join(', ') + ']');
//after all raw content is loaded
//create typed model classes of all content based on map in config.js
//TODO: add properties to routes because this is overly rigid (route key needs to match sheet name)
//typeMap config object tells us what model types to create for each sheet
_lodash2.default.forOwn(this.typeMap, function (type, sheet) {
return _this4.model(sheet, type);
});
}
//force sever to re-ingest static content from google doc
}, {
key: 'refresh',
value: function refresh(success) {
var _this5 = this;
//collect all sheets from what is currently loaded
var tabs = [];
_lodash2.default.forOwn(this.raw, function (c) {
if (tabs.indexOf(c.sheet) < 0) tabs.push(c.sheet);
});
console.log('[LIBRE] Refreshing cached content on server...');
_axios2.default.post('/libre/refresh', { tabs: tabs }).then(function (_ref3) {
var data = _ref3.data;
console.log('[LIBRE] Content refresh complete on server.');
_this5.init(data);
success(_this5);
});
}
//for given text, apply interpolation plugins and return array of pieces for rendering
}, {
key: 'process',
value: function process(text) {
var plugins = this.plugins;
if (!text || !plugins) return [];
var pieces = [],
ranges = [];
//1. run through all plugins to find matches to be replaced
_lodash2.default.forOwn(plugins, function (plugin, type) {
var pattern = plugin.pattern;
var match = void 0,
start = void 0,
end = void 0;
//each plugin can have multiple matches -- keep going to find them all
while ((match = pattern.exec(text)) !== null) {
start = match.index;
end = start + match[0].length;
ranges.push({ type: type, start: start, end: end, match: match });
}
});
//if we find nothing, just convert the whole thing to 1 plain piece
if (ranges.length == 0) return [{ type: 'plain', text: text }];
//2. sort by starting position
ranges = _lodash2.default.sortBy(ranges, 'start');
//3. fill in the gaps with plain text
for (var i = 0; i < ranges.length; i++) {
//if we're looking at a plain (added) piece or the last piece, skip
if (ranges[i].type == 'plain' || i + 1 == ranges.length) continue;
var plain = { type: 'plain', start: ranges[i].end, end: ranges[i + 1].start };
if (plain.end > plain.start) ranges.push(plain);
}
//4. sort again -- now we have everything from the first matched range to the last
ranges = _lodash2.default.sortBy(ranges, 'start');
//add plain piece at beginning and end if necessary (the above loop ignores these edge cases)
if (ranges[0].start > 0) ranges.splice(0, 0, { type: 'plain', start: 0, end: ranges[0].start });
if (ranges[ranges.length - 1].end < text.length) ranges.push({ type: 'plain', start: ranges[ranges.length - 1].end, end: text.length });
//5. now populate with the actual text content
ranges.map(function (r) {
return pieces.push({ type: r.type, text: text.substring(r.start, r.end), match: r.match });
});
return pieces;
}
}]);
return Libre;
}();
var libre = new Libre();
if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) == 'object') window.Libre = libre;
exports.default = libre;
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = __webpack_require__(8);
var _react2 = _interopRequireDefault(_react);
var _reactRouterDom = __webpack_require__(12);
var _history = __webpack_require__(7);
var _reactDom = __webpack_require__(9);
var _reactDom2 = _interopRequireDefault(_reactDom);
var _Libre = __webpack_require__(2);
var _Libre2 = _interopRequireDefault(_Libre);
var _Dealer = __webpack_require__(1);
var _Dealer2 = _interopRequireDefault(_Dealer);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Client = function (_Component) {
_inherits(Client, _Component);
function Client(props) {
_classCallCheck(this, Client);
var _this = _possibleConstructorReturn(this, (Client.__proto__ || Object.getPrototypeOf(Client)).call(this, props));
_this.state = {
refreshing: false,
libre: null
};
_this.globals = {
refresh: function refresh() {
return _this.refresh();
},
og: function og(tags) {
return _this.og(tags);
}
// push: (tab, row, success) => this.push(tab, row, success)
};
return _this;
}
_createClass(Client, [{
key: 'componentWillMount',
value: function componentWillMount() {
var _this2 = this;
_Libre2.default.load(function (libre) {
return _this2.setState({ libre: libre });
});
}
//to make content production easier, the client app can expose a refresh button
//pushing content to app state on load also causes components to re-render live
//(whether they use it or not)
//because App state is passed to all child components as props
}, {
key: 'refresh',
value: function refresh() {
var _this3 = this;
this.setState({ refreshing: true });
_Libre2.default.refresh(function (libre) {
return _this3.setState({ refreshing: false, libre: libre });
});
}
}, {
key: 'og',
value: function og(tags) {
if ((typeof document === 'undefined' ? 'undefined' : _typeof(document)) === 'object') {
if (tags.title) document.title = tags.title;
if (tags.description) {
var meta = document.querySelector('meta[name="description"]');
if (meta != null) meta.setAttribute('content', tags.description);
}
}
}
}, {
key: 'render',
value: function render() {
var _this4 = this;
var _props = this.props,
App = _props.App,
routes = _props.routes;
if (!this.state.libre) return null;
return _react2.default.createElement(_reactRouterDom.Route, { render: function render(r) {
return _react2.default.createElement(
App,
_extends({}, r, _this4.state, _this4.globals),
_react2.default.createElement(
_reactRouterDom.Switch,
null,
Object.keys(routes).map(function (key) {
return _this4.renderRoute(key, routes[key]);
})
)
);
} });
}
}, {
key: 'renderRoute',
value: function renderRoute(key, route) {
var _this5 = this;
var routeProps = { exact: key === '/', key: key, path: key };
var Component = route.component;
return _react2.default.createElement(_reactRouterDom.Route, _extends({}, routeProps, { render: function render(r) {
return _react2.default.createElement(Component, _extends({}, r, _this5.state, _this5.globals));
} }));
}
}], [{
key: 'run',
value: function run(App, routes, config, typeMap, plugins) {
if (config.GA_ID) _Dealer2.default.init(config.GA_ID);
_Libre2.default.setup({ typeMap: typeMap, plugins: plugins });
//pass other config data into app instance via route props
var renderProps = { config: config, typeMap: typeMap, App: App, routes: routes };
var history = (0, _history.createBrowserHistory)();
//track current (first) page, and listen for subsequent updates
_Dealer2.default.page();
history.listen(function (location) {
_Dealer2.default.page();
});
_reactDom2.default.render(_react2.default.createElement(
_reactRouterDom.Router,
{ history: history },
_react2.default.createElement(Client, renderProps)
), document.querySelector('#app'));
}
}]);
return Client;
}(_react.Component);
exports.default = Client;
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _lodash = __webpack_require__(0);
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Item = function () {
function Item(_ref, libre) {
var _this = this;
var id = _ref.id,
title = _ref.title,
links = _ref.links,
path = _ref.path;
_classCallCheck(this, Item);
this.libre = libre;
_lodash2.default.assign(this, { id: id, title: title, path: path });
this.links = [];
if (links && links != '') {
var lines = links.split('\n');
lines.map(function (link) {
var pieces = link.split('|');
if (pieces.length >= 2) _this.links.push({ title: pieces[0], url: pieces[1] });
});
}
}
//for a given field, split into sections based on line breaks (\n)
//ignoring empty (double) breaks
//auto run Libre.process() on sections, so this will return a section array of piece arrays (nested array)
_createClass(Item, [{
key: 'sections',
value: function sections(field) {
var _this2 = this;
var text = this[field];
if (!text) return [];
var sections = [];
text.split('\n').map(function (raw) {
if (raw.trim() != '') sections.push(_this2.libre.process(raw.trim()));
});
return sections;
}
}]);
return Item;
}();
exports.default = Item;
/***/ }),
/* 5 */
/***/ (function(module, exports, __webpack_require__) {
;
var _Client = __webpack_require__(3);
var _Client2 = _interopRequireDefault(_Client);
var _Item = __webpack_require__(4);
var _Item2 = _interopRequireDefault(_Item);
var _Dealer = __webpack_require__(1);
var _Dealer2 = _interopRequireDefault(_Dealer);
var _Libre = __webpack_require__(2);
var _Libre2 = _interopRequireDefault(_Libre);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
module.exports = {
Libre: _Libre2.default,
Item: _Item2.default,
Client: _Client2.default,
Dealer: _Dealer2.default
}; //probably remove this
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = require("axios");
/***/ }),
/* 7 */
/***/ (function(module, exports) {
module.exports = require("history");
/***/ }),
/* 8 */
/***/ (function(module, exports) {
module.exports = require("react");
/***/ }),
/* 9 */
/***/ (function(module, exports) {
module.exports = require("react-dom");
/***/ }),
/* 10 */
/***/ (function(module, exports) {
module.exports = require("react-ga");
/***/ }),
/* 11 */
/***/ (function(module, exports) {
module.exports = require("react-router");
/***/ }),
/* 12 */
/***/ (function(module, exports) {
module.exports = require("react-router-dom");
/***/ })
/******/ ])));