Skip to content

Commit cd09da8

Browse files
marinaaisaDobromir Hristov
andauthored
Refactor: URL utils (#596)
* [rdar://96841531] refactor: normalize urls * [rdar://96841531] fix: data url * [rdar://96841531] fix: address feedback * [rdar://96841531] test: fix calls `fetchData` with a configurable base url test * fix: issue with navigator not being fetched properly. Fix JSDoc comments. Properly assert navigator data fetching in test --------- Co-authored-by: Dobromir Hristov <[email protected]>
1 parent 81138c8 commit cd09da8

File tree

16 files changed

+190
-120
lines changed

16 files changed

+190
-120
lines changed

src/components/DocumentationTopic.vue

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
import Language from 'docc-render/constants/Language';
150150
import metadata from 'theme/mixins/metadata.js';
151151
import { buildUrl } from 'docc-render/utils/url-helper';
152+
import { normalizeRelativePath } from 'docc-render/utils/assets';
152153
153154
import Aside from 'docc-render/components/ContentNode/Aside.vue';
154155
import BetaLegalText from 'theme/components/DocumentationTopic/BetaLegalText.vue';
@@ -382,14 +383,13 @@ export default {
382383
};
383384
},
384385
computed: {
385-
normalizedSwiftPath: ({ normalizePath, swiftPath }) => (normalizePath(swiftPath)),
386+
normalizedSwiftPath: ({ swiftPath }) => (normalizeRelativePath(swiftPath)),
386387
normalizedObjcPath: ({
387-
normalizePath,
388388
objcPath,
389389
swiftPath,
390390
}) => (
391391
// do not append language query parameter if no swiftPath exists
392-
normalizePath((objcPath && swiftPath) ? buildUrl(objcPath, {
392+
normalizeRelativePath((objcPath && swiftPath) ? buildUrl(objcPath, {
393393
language: Language.objectiveC.key.url,
394394
}) : objcPath)
395395
),
@@ -517,12 +517,6 @@ export default {
517517
},
518518
},
519519
methods: {
520-
normalizePath(path) {
521-
// Sometimes `paths` data from `variants` are prefixed with a leading
522-
// slash and sometimes they aren't
523-
if (!path) return path;
524-
return path.startsWith('/') ? path : `/${path}`;
525-
},
526520
extractProps(json) {
527521
const {
528522
abstract,
@@ -618,7 +612,7 @@ export default {
618612
619613
this.$nextTick().then(() => {
620614
this.$router.replace({
621-
path: this.normalizePath(this.objcPath),
615+
path: normalizeRelativePath(this.objcPath),
622616
query: {
623617
...query,
624618
language: Language.objectiveC.key.url,

src/components/DocumentationTopic/DocumentationNav/LanguageToggle.vue

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484

8585
<script>
8686
import { waitFrames } from 'docc-render/utils/loading';
87+
import { normalizeRelativePath } from 'docc-render/utils/assets';
8788
import Language from 'docc-render/constants/Language';
8889
import throttle from 'docc-render/utils/throttle';
8990
import NavMenuItemBase from 'docc-render/components/NavMenuItemBase.vue';
@@ -164,7 +165,7 @@ export default {
164165
return {
165166
// make sure we dont loose any extra query params on the way
166167
query: { ...this.$route.query, language },
167-
path: this.isCurrentPath(route.path) ? null : this.normalizePath(route.path),
168+
path: this.isCurrentPath(route.path) ? null : normalizeRelativePath(route.path),
168169
};
169170
},
170171
async pushRoute(route) {
@@ -182,11 +183,6 @@ export default {
182183
// include a leading slash, while the router provided path does
183184
return this.$route.path.replace(/^\//, '') === path;
184185
},
185-
normalizePath(path) {
186-
// Sometimes `paths` data from `variants` are prefixed with a leading
187-
// slash and sometimes they aren't
188-
return path.startsWith('/') ? path : `/${path}`;
189-
},
190186
/**
191187
* Calculated the width of the select by fetching it from the faux select.
192188
* @return {Promise<void>}

src/components/DocumentationTopic/Summary/LanguageSwitcher.vue

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
<script>
3636
import { buildUrl } from 'docc-render/utils/url-helper';
37+
import { normalizeRelativePath } from 'docc-render/utils/assets';
3738
import Language from 'docc-render/constants/Language';
3839
3940
import LanguageSwitcherLink from './LanguageSwitcherLink.vue';
@@ -81,26 +82,24 @@ export default {
8182
// current URL.
8283
objc: ({
8384
interfaceLanguage,
84-
normalizePath,
8585
objcPath,
8686
$route: { query },
8787
}) => ({
8888
...Language.objectiveC,
8989
active: Language.objectiveC.key.api === interfaceLanguage,
90-
url: buildUrl(normalizePath(objcPath), {
90+
url: buildUrl(normalizeRelativePath(objcPath), {
9191
...query,
9292
language: Language.objectiveC.key.url,
9393
}),
9494
}),
9595
swift: ({
9696
interfaceLanguage,
97-
normalizePath,
9897
swiftPath,
9998
$route: { query },
10099
}) => ({
101100
...Language.swift,
102101
active: Language.swift.key.api === interfaceLanguage,
103-
url: buildUrl(normalizePath(swiftPath), {
102+
url: buildUrl(normalizeRelativePath(swiftPath), {
104103
...query,
105104
language: undefined,
106105
}),
@@ -114,11 +113,6 @@ export default {
114113
115114
this.$router.push(language.url);
116115
},
117-
normalizePath(path) {
118-
// Sometimes `paths` data from `variants` are prefixed with a leading
119-
// slash and sometimes they aren't
120-
return path.startsWith('/') ? path : `/${path}`;
121-
},
122116
},
123117
};
124118
</script>

src/components/ImageAsset.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,20 @@ import imageAsset from 'docc-render/mixins/imageAsset';
6262
import AppStore from 'docc-render/stores/AppStore';
6363
import ColorScheme from 'docc-render/constants/ColorScheme';
6464
import noImage from 'theme/assets/img/[email protected]';
65-
import { getIntrinsicDimensions, normalizeAssetUrl } from 'docc-render/utils/assets';
65+
import { getIntrinsicDimensions, normalizePath } from 'docc-render/utils/assets';
6666
6767
const RADIX_DECIMAL = 10;
6868
6969
function constructAttributes(sources) {
7070
if (!sources.length) {
7171
return null;
7272
}
73-
const srcSet = sources.map(s => `${normalizeAssetUrl(s.src)} ${s.density}`).join(', ');
73+
const srcSet = sources.map(s => `${normalizePath(s.src)} ${s.density}`).join(', ');
7474
const defaultSource = sources[0];
7575
7676
const attrs = {
7777
srcSet,
78-
src: normalizeAssetUrl(defaultSource.src),
78+
src: normalizePath(defaultSource.src),
7979
};
8080
8181
// All the variants should have the same size, so use the size of the first

src/components/Tutorial/Hero.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ import LinkableElement from 'docc-render/components/LinkableElement.vue';
7373
7474
import GenericModal from 'docc-render/components/GenericModal.vue';
7575
import PlayIcon from 'theme/components/Icons/PlayIcon.vue';
76-
import { normalizeAssetUrl, toCSSUrl } from 'docc-render/utils/assets';
76+
import { normalizePath, toCSSUrl } from 'docc-render/utils/assets';
7777
import referencesProvider from 'docc-render/mixins/referencesProvider';
7878
import HeroMetadata from './HeroMetadata.vue';
7979
@@ -141,10 +141,10 @@ export default {
141141
variant.traits.includes('light')
142142
));
143143
144-
return (lightVariant || {}).url;
144+
return normalizePath((lightVariant || {}).url);
145145
},
146146
projectFilesUrl() {
147-
return this.projectFiles ? normalizeAssetUrl(this.references[this.projectFiles].url) : null;
147+
return this.projectFiles ? normalizePath(this.references[this.projectFiles].url) : null;
148148
},
149149
bgStyle() {
150150
return {

src/components/VideoAsset.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@
3333
is handled with JavaScript media query listeners unlike the `<source>`
3434
based implementation being used for image assets.
3535
-->
36-
<source :src="normalizeAssetUrl(videoAttributes.url)">
36+
<source :src="normalizePath(videoAttributes.url)">
3737
</video>
3838
</ConditionalWrapper>
3939
</template>
4040

4141
<script>
4242
import {
4343
separateVariantsByAppearance,
44-
normalizeAssetUrl,
44+
normalizePath,
4545
getIntrinsicDimensions,
4646
extractDensities,
4747
} from 'docc-render/utils/assets';
@@ -142,7 +142,7 @@ export default {
142142
: variants.light[0] || {}
143143
),
144144
normalisedPosterPath: ({ defaultPosterAttributes }) => (
145-
normalizeAssetUrl(defaultPosterAttributes.src)
145+
normalizePath(defaultPosterAttributes.src)
146146
),
147147
videoAttributes: ({
148148
darkVideoVariantAttributes,
@@ -160,7 +160,7 @@ export default {
160160
},
161161
},
162162
methods: {
163-
normalizeAssetUrl,
163+
normalizePath,
164164
async getPosterDimensions(path) {
165165
if (!path) {
166166
this.optimalWidth = null;

src/utils/assets.js

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@
88
* See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
/**
12-
* Utility functions for working with Assets
13-
*/
14-
import { baseUrl } from 'docc-render/utils/theme-settings';
15-
1611
/**
1712
* Separate array of variants by light/dark mode
1813
* @param {array} variants
@@ -65,23 +60,37 @@ export function pathJoin(parts) {
6560
}
6661

6762
/**
68-
* Normalizes asset urls, by prefixing the baseUrl path to them.
69-
* @param {String} url
70-
* @return {String}
63+
* Normalizes paths, by prefixing the baseUrl path to them.
64+
* @param {string | string[]} rawPath
65+
* @return {string}
7166
*/
72-
export function normalizeAssetUrl(url) {
73-
if (!url || typeof url !== 'string' || url.startsWith(baseUrl) || !url.startsWith('/')) {
74-
return url;
67+
export function normalizePath(rawPath) {
68+
const { baseUrl } = window;
69+
const path = Array.isArray(rawPath) ? pathJoin(rawPath) : rawPath;
70+
if (!path || typeof path !== 'string' || path.startsWith(baseUrl) || !path.startsWith('/')) {
71+
return path;
7572
}
76-
return pathJoin([baseUrl, url]);
73+
return pathJoin([baseUrl, path]);
74+
}
75+
76+
/**
77+
* Normalizes relative paths, by making them start with /.
78+
* @param {string} path
79+
* @return {string}
80+
*/
81+
export function normalizeRelativePath(path) {
82+
// Sometimes `paths` data from `variants` are prefixed with a leading
83+
// slash and sometimes they aren't
84+
if (!path) return path;
85+
return path.startsWith('/') ? path : `/${path}`;
7786
}
7887

7988
/**
8089
* Transforms a URL string into a normalized css `url(/path)` format.
8190
* @param {String} url
8291
* @returns {string|undefined}
8392
*/
84-
export function toCSSUrl(url) { return url ? `url('${normalizeAssetUrl(url)}')` : undefined; }
93+
export function toCSSUrl(url) { return url ? `url('${normalizePath(url)}')` : undefined; }
8594

8695
/**
8796
* Loads an image and gets its dimensions

src/utils/data.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
* See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
import { pathJoin } from 'docc-render/utils/assets';
12-
import { queryStringForParams, areEquivalentLocations } from 'docc-render/utils/url-helper';
11+
import { normalizePath } from 'docc-render/utils/assets';
12+
import {
13+
queryStringForParams, areEquivalentLocations, getAbsoluteUrl,
14+
} from 'docc-render/utils/url-helper';
1315
import emitWarningForSchemaVersionMismatch from 'docc-render/utils/schema-version-check';
14-
import { baseUrl } from 'docc-render/utils/theme-settings';
1516
import RedirectError from 'docc-render/errors/RedirectError';
1617
import FetchError from 'docc-render/errors/FetchError';
1718

@@ -30,7 +31,7 @@ export async function fetchData(path, params = {}, options = {}) {
3031
return !response.ok;
3132
}
3233

33-
const url = new URL(path, window.location.href);
34+
const url = getAbsoluteUrl(path);
3435
const queryString = queryStringForParams(params);
3536
if (queryString) {
3637
url.search = queryString;
@@ -56,7 +57,7 @@ export async function fetchData(path, params = {}, options = {}) {
5657

5758
function createDataPath(path) {
5859
const dataPath = path.replace(/\/$/, '');
59-
return `${pathJoin([baseUrl, 'data', dataPath])}.json`;
60+
return `${normalizePath(['/data', dataPath])}.json`;
6061
}
6162

6263
/**
@@ -137,6 +138,6 @@ export function clone(jsonObject) {
137138
}
138139

139140
export async function fetchIndexPathsData({ slug }) {
140-
const path = new URL(`${pathJoin([baseUrl, 'index/', slug, 'index.json'])}`, window.location.href);
141+
const path = getAbsoluteUrl(['/index/', slug, 'index.json']);
141142
return fetchData(path);
142143
}

src/utils/theme-settings.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
import get from 'docc-render/utils/get';
12+
import { resolveAbsoluteUrl } from 'docc-render/utils/url-helper';
1213

1314
/**
1415
* Theme settings state.
@@ -27,8 +28,8 @@ export const { baseUrl } = window;
2728
* @return {Promise<{}>}
2829
*/
2930
export async function fetchThemeSettings() {
30-
const url = new URL(`${baseUrl}theme-settings.json`, window.location.href);
31-
return fetch(url.href)
31+
const url = resolveAbsoluteUrl('/theme-settings.json');
32+
return fetch(url)
3233
.then(r => r.json())
3334
.catch(() => ({}));
3435
}

0 commit comments

Comments
 (0)