(cb = noop)
| 82 | } |
| 83 | |
| 84 | _fetch(cb = noop) { |
| 85 | const { query } = this.route; |
| 86 | let { path } = this.route; |
| 87 | |
| 88 | // Prevent loading remote content via URL hash |
| 89 | // Ex: https://foo.com/#//bar.com/file.md |
| 90 | if (isExternal(path)) { |
| 91 | history.replaceState(null, '', '#'); |
| 92 | this.router.normalize(); |
| 93 | } else { |
| 94 | const qs = stringifyQuery(query, ['id']); |
| 95 | const { loadNavbar, requestHeaders, loadSidebar } = this.config; |
| 96 | // Abort last request |
| 97 | |
| 98 | const file = this.router.getFile(path); |
| 99 | |
| 100 | this.isRemoteUrl = isExternal(file); |
| 101 | // Current page is html |
| 102 | this.isHTML = /\.html$/g.test(file); |
| 103 | |
| 104 | // create a handler that should be called if content was fetched successfully |
| 105 | const contentFetched = (text, opt) => { |
| 106 | this._renderMain( |
| 107 | text, |
| 108 | opt, |
| 109 | this._loadSideAndNav(path, qs, loadSidebar, cb) |
| 110 | ); |
| 111 | }; |
| 112 | |
| 113 | // and a handler that is called if content failed to fetch |
| 114 | const contentFailedToFetch = _ => { |
| 115 | this._fetchFallbackPage(path, qs, cb) || this._fetch404(file, qs, cb); |
| 116 | }; |
| 117 | |
| 118 | // attempt to fetch content from a virtual route, and fallback to fetching the actual file |
| 119 | if (!this.isRemoteUrl) { |
| 120 | this.matchVirtualRoute(path).then(contents => { |
| 121 | if (typeof contents === 'string') { |
| 122 | contentFetched(contents); |
| 123 | } else { |
| 124 | request(file + qs, true, requestHeaders).then( |
| 125 | contentFetched, |
| 126 | contentFailedToFetch |
| 127 | ); |
| 128 | } |
| 129 | }); |
| 130 | } else { |
| 131 | // if the requested url is not local, just fetch the file |
| 132 | request(file + qs, true, requestHeaders).then( |
| 133 | contentFetched, |
| 134 | contentFailedToFetch |
| 135 | ); |
| 136 | } |
| 137 | |
| 138 | // Load nav |
| 139 | loadNavbar && |
| 140 | loadNested( |
| 141 | path, |
no test coverage detected