UNPKG

next-csrf

Version:

CSRF mitigation library for Next.js

254 lines (201 loc) 7.12 kB
"use strict"; exports.__esModule = true; exports["default"] = void 0; var _stringHash = _interopRequireDefault(require("string-hash")); var _stylesheet = _interopRequireDefault(require("./lib/stylesheet")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var sanitize = function sanitize(rule) { return rule.replace(/\/style/gi, '\\/style'); }; var StyleSheetRegistry = /*#__PURE__*/ function () { function StyleSheetRegistry(_temp) { var _ref = _temp === void 0 ? {} : _temp, _ref$styleSheet = _ref.styleSheet, styleSheet = _ref$styleSheet === void 0 ? null : _ref$styleSheet, _ref$optimizeForSpeed = _ref.optimizeForSpeed, optimizeForSpeed = _ref$optimizeForSpeed === void 0 ? false : _ref$optimizeForSpeed, _ref$isBrowser = _ref.isBrowser, isBrowser = _ref$isBrowser === void 0 ? typeof window !== 'undefined' : _ref$isBrowser; this._sheet = styleSheet || new _stylesheet["default"]({ name: 'styled-jsx', optimizeForSpeed: optimizeForSpeed }); this._sheet.inject(); if (styleSheet && typeof optimizeForSpeed === 'boolean') { this._sheet.setOptimizeForSpeed(optimizeForSpeed); this._optimizeForSpeed = this._sheet.isOptimizeForSpeed(); } this._isBrowser = isBrowser; this._fromServer = undefined; this._indices = {}; this._instancesCounts = {}; this.computeId = this.createComputeId(); this.computeSelector = this.createComputeSelector(); } var _proto = StyleSheetRegistry.prototype; _proto.add = function add(props) { var _this = this; if (undefined === this._optimizeForSpeed) { this._optimizeForSpeed = Array.isArray(props.children); this._sheet.setOptimizeForSpeed(this._optimizeForSpeed); this._optimizeForSpeed = this._sheet.isOptimizeForSpeed(); } if (this._isBrowser && !this._fromServer) { this._fromServer = this.selectFromServer(); this._instancesCounts = Object.keys(this._fromServer).reduce(function (acc, tagName) { acc[tagName] = 0; return acc; }, {}); } var _this$getIdAndRules = this.getIdAndRules(props), styleId = _this$getIdAndRules.styleId, rules = _this$getIdAndRules.rules; // Deduping: just increase the instances count. if (styleId in this._instancesCounts) { this._instancesCounts[styleId] += 1; return; } var indices = rules.map(function (rule) { return _this._sheet.insertRule(rule); }) // Filter out invalid rules .filter(function (index) { return index !== -1; }); this._indices[styleId] = indices; this._instancesCounts[styleId] = 1; }; _proto.remove = function remove(props) { var _this2 = this; var _this$getIdAndRules2 = this.getIdAndRules(props), styleId = _this$getIdAndRules2.styleId; invariant(styleId in this._instancesCounts, "styleId: `" + styleId + "` not found"); this._instancesCounts[styleId] -= 1; if (this._instancesCounts[styleId] < 1) { var tagFromServer = this._fromServer && this._fromServer[styleId]; if (tagFromServer) { tagFromServer.parentNode.removeChild(tagFromServer); delete this._fromServer[styleId]; } else { this._indices[styleId].forEach(function (index) { return _this2._sheet.deleteRule(index); }); delete this._indices[styleId]; } delete this._instancesCounts[styleId]; } }; _proto.update = function update(props, nextProps) { this.add(nextProps); this.remove(props); }; _proto.flush = function flush() { this._sheet.flush(); this._sheet.inject(); this._fromServer = undefined; this._indices = {}; this._instancesCounts = {}; this.computeId = this.createComputeId(); this.computeSelector = this.createComputeSelector(); }; _proto.cssRules = function cssRules() { var _this3 = this; var fromServer = this._fromServer ? Object.keys(this._fromServer).map(function (styleId) { return [styleId, _this3._fromServer[styleId]]; }) : []; var cssRules = this._sheet.cssRules(); return fromServer.concat(Object.keys(this._indices).map(function (styleId) { return [styleId, _this3._indices[styleId].map(function (index) { return cssRules[index].cssText; }).join(_this3._optimizeForSpeed ? '' : '\n')]; }) // filter out empty rules .filter(function (rule) { return Boolean(rule[1]); })); } /** * createComputeId * * Creates a function to compute and memoize a jsx id from a basedId and optionally props. */ ; _proto.createComputeId = function createComputeId() { var cache = {}; return function (baseId, props) { if (!props) { return "jsx-" + baseId; } var propsToString = String(props); var key = baseId + propsToString; // return `jsx-${hashString(`${baseId}-${propsToString}`)}` if (!cache[key]) { cache[key] = "jsx-" + (0, _stringHash["default"])(baseId + "-" + propsToString); } return cache[key]; }; } /** * createComputeSelector * * Creates a function to compute and memoize dynamic selectors. */ ; _proto.createComputeSelector = function createComputeSelector(selectoPlaceholderRegexp) { if (selectoPlaceholderRegexp === void 0) { selectoPlaceholderRegexp = /__jsx-style-dynamic-selector/g; } var cache = {}; return function (id, css) { // Sanitize SSR-ed CSS. // Client side code doesn't need to be sanitized since we use // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod). if (!this._isBrowser) { css = sanitize(css); } var idcss = id + css; if (!cache[idcss]) { cache[idcss] = css.replace(selectoPlaceholderRegexp, id); } return cache[idcss]; }; }; _proto.getIdAndRules = function getIdAndRules(props) { var _this4 = this; var css = props.children, dynamic = props.dynamic, id = props.id; if (dynamic) { var styleId = this.computeId(id, dynamic); return { styleId: styleId, rules: Array.isArray(css) ? css.map(function (rule) { return _this4.computeSelector(styleId, rule); }) : [this.computeSelector(styleId, css)] }; } return { styleId: this.computeId(id), rules: Array.isArray(css) ? css : [css] }; } /** * selectFromServer * * Collects style tags from the document with id __jsx-XXX */ ; _proto.selectFromServer = function selectFromServer() { var elements = Array.prototype.slice.call(document.querySelectorAll('[id^="__jsx-"]')); return elements.reduce(function (acc, element) { var id = element.id.slice(2); acc[id] = element; return acc; }, {}); }; return StyleSheetRegistry; }(); exports["default"] = StyleSheetRegistry; function invariant(condition, message) { if (!condition) { throw new Error("StyleSheetRegistry: " + message + "."); } }