UNPKG

@tdb/web

Version:

Common condiguration for serving a web-site and testing web-based UI components.

241 lines (180 loc) 8.4 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime-corejs2/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify")); var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/typeof")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn")); var _getPrototypeOf3 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits")); var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/assertThisInitialized")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty")); var _url = require("url"); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _router = _interopRequireWildcard(require("./router")); var _utils = require("./utils"); /* global __NEXT_DATA__ */ function isLocal(href) { var url = (0, _url.parse)(href, false, true); var origin = (0, _url.parse)((0, _utils.getLocationOrigin)(), false, true); return !url.host || url.protocol === origin.protocol && url.host === origin.host; } function memoizedFormatUrl(formatUrl) { var lastHref = null; var lastAs = null; var lastResult = null; return function (href, as) { if (href === lastHref && as === lastAs) { return lastResult; } var result = formatUrl(href, as); lastHref = href; lastAs = as; lastResult = result; return result; }; } var Link = /*#__PURE__*/ function (_Component) { (0, _inherits2.default)(Link, _Component); function Link() { var _getPrototypeOf2; var _this; (0, _classCallCheck2.default)(this, Link); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(Link)).call.apply(_getPrototypeOf2, [this].concat(args))); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "formatUrls", memoizedFormatUrl(function (href, asHref) { return { href: href && (0, _typeof2.default)(href) === 'object' ? (0, _url.format)(href) : href, as: asHref && (0, _typeof2.default)(asHref) === 'object' ? (0, _url.format)(asHref) : asHref }; })); (0, _defineProperty2.default)((0, _assertThisInitialized2.default)((0, _assertThisInitialized2.default)(_this)), "linkClicked", function (e) { var _e$currentTarget = e.currentTarget, nodeName = _e$currentTarget.nodeName, target = _e$currentTarget.target; if (nodeName === 'A' && (target && target !== '_self' || e.metaKey || e.ctrlKey || e.shiftKey || e.nativeEvent && e.nativeEvent.which === 2)) { // ignore click for new tab / new window behavior return; } var _this$formatUrls = _this.formatUrls(_this.props.href, _this.props.as), href = _this$formatUrls.href, as = _this$formatUrls.as; if (!isLocal(href)) { // ignore click if it's outside our scope return; } var pathname = window.location.pathname; href = (0, _url.resolve)(pathname, href); as = as ? (0, _url.resolve)(pathname, as) : href; e.preventDefault(); // avoid scroll for urls with anchor refs var scroll = _this.props.scroll; if (scroll == null) { scroll = as.indexOf('#') < 0; } // replace state instead of push if prop is present var replace = _this.props.replace; var changeMethod = replace ? 'replace' : 'push'; // straight up redirect _router.default[changeMethod](href, as, { shallow: _this.props.shallow }).then(function (success) { if (!success) return; if (scroll) { window.scrollTo(0, 0); document.body.focus(); } }).catch(function (err) { if (_this.props.onError) _this.props.onError(err); }); }); return _this; } (0, _createClass2.default)(Link, [{ key: "componentDidMount", value: function componentDidMount() { this.prefetch(); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { if ((0, _stringify.default)(this.props.href) !== (0, _stringify.default)(prevProps.href)) { this.prefetch(); } } // The function is memoized so that no extra lifecycles are needed // as per https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html }, { key: "prefetch", value: function prefetch() { if (!this.props.prefetch) return; if (typeof window === 'undefined') return; // Prefetch the JSON page if asked (only in the client) var pathname = window.location.pathname; var _this$formatUrls2 = this.formatUrls(this.props.href, this.props.as), parsedHref = _this$formatUrls2.href; var href = (0, _url.resolve)(pathname, parsedHref); _router.default.prefetch(href); } }, { key: "render", value: function render() { var _this2 = this; var children = this.props.children; var _this$formatUrls3 = this.formatUrls(this.props.href, this.props.as), href = _this$formatUrls3.href, as = _this$formatUrls3.as; // Deprecated. Warning shown by propType check. If the childen provided is a string (<Link>example</Link>) we wrap it in an <a> tag if (typeof children === 'string') { children = _react.default.createElement("a", null, children); } // This will return the first child, if multiple are provided it will throw an error var child = _react.Children.only(children); var props = { onClick: function onClick(e) { if (child.props && typeof child.props.onClick === 'function') { child.props.onClick(e); } if (!e.defaultPrevented) { _this2.linkClicked(e); } } // If child is an <a> tag and doesn't have a href attribute, or if the 'passHref' property is // defined, we specify the current 'href', so that repetition is not needed by the user }; if (this.props.passHref || child.type === 'a' && !('href' in child.props)) { props.href = as || href; } // Add the ending slash to the paths. So, we can serve the // "<page>/index.html" directly. if (props.href && typeof __NEXT_DATA__ !== 'undefined' && __NEXT_DATA__.nextExport) { props.href = (0, _router._rewriteUrlForNextExport)(props.href); } return _react.default.cloneElement(child, props); } }]); return Link; }(_react.Component); if (process.env.NODE_ENV === 'development') { var warn = (0, _utils.execOnce)(console.error); // This module gets removed by webpack.IgnorePlugin var exact = require('prop-types-exact'); Link.propTypes = exact({ href: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]).isRequired, as: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.object]), prefetch: _propTypes.default.bool, replace: _propTypes.default.bool, shallow: _propTypes.default.bool, passHref: _propTypes.default.bool, scroll: _propTypes.default.bool, children: _propTypes.default.oneOfType([_propTypes.default.element, function (props, propName) { var value = props[propName]; if (typeof value === 'string') { warn("Warning: You're using a string directly inside <Link>. This usage has been deprecated. Please add an <a> tag as child of <Link>"); } return null; }]).isRequired }); } var _default = Link; exports.default = _default;