Skip to content

Support custom page icons and image overrides #417

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
14 changes: 14 additions & 0 deletions src/components/DocumentationTopic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:enhanceBackground="enhanceBackground"
:shortHero="shortHero"
:shouldShowLanguageSwitcher="shouldShowLanguageSwitcher"
:iconOverride="references[pageIcon]"
>
<template #above-content>
<slot name="above-hero-content" />
Expand Down Expand Up @@ -270,6 +271,10 @@ export default {
type: Object,
required: false,
},
pageImages: {
type: Array,
required: false,
},
},
provide() {
// NOTE: this is not reactive: if this.references change, the provided value
Expand Down Expand Up @@ -350,6 +355,15 @@ export default {
|| (primaryContentSections && primaryContentSections.length)
),
tagName: ({ isSymbolDeprecated }) => (isSymbolDeprecated ? 'Deprecated' : 'Beta'),
/**
* Finds the page icon in the `pageImages` array
* @param {Array} pageImages
* @returns {String|null}
*/
pageIcon: ({ pageImages = [] }) => {
const icon = pageImages.find(({ type }) => type === 'icon');
return icon ? icon.identifier : null;
},
},
methods: {
normalizePath(path) {
Expand Down
14 changes: 10 additions & 4 deletions src/components/DocumentationTopic/DocumentationHero.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
:style="styles"
>
<div class="icon">
<NavigatorLeafIcon
v-if="enhanceBackground" :type="type"
<TopicTypeIcon
v-if="enhanceBackground"
:type="type"
:image-override="iconOverride"
key="first" class="background-icon first-icon" with-colors
/>
</div>
Expand All @@ -36,14 +38,14 @@

<script>

import NavigatorLeafIcon from 'docc-render/components/Navigator/NavigatorLeafIcon.vue';
import TopicTypeIcon from 'docc-render/components/TopicTypeIcon.vue';
import { TopicTypes, TopicTypeAliases } from 'docc-render/constants/TopicTypes';
import { HeroColorsMap, HeroColors } from 'docc-render/constants/HeroColors';
import { TopicRole } from 'docc-render/constants/roles';

export default {
name: 'DocumentationHero',
components: { NavigatorLeafIcon },
components: { TopicTypeIcon },
props: {
role: {
type: String,
Expand All @@ -61,6 +63,10 @@ export default {
type: Boolean,
required: true,
},
iconOverride: {
type: Object,
required: false,
},
},
computed: {
// get the alias, if any, and fallback to the `teal` color
Expand Down
23 changes: 20 additions & 3 deletions src/components/DocumentationTopic/TopicLinkBlockIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@
-->

<template>
<div class="topic-icon-wrapper" v-if="icon">
<component :is="icon" class="topic-icon" />
</div>
<IconOverrideProvider
:imageOverride="imageOverride"
#default="{ shouldUseOverride, themeId, iconUrl }"
>
<div class="topic-icon-wrapper" v-if="icon || shouldUseOverride">
<SVGIcon
v-if="shouldUseOverride"
v-bind="{ themeId, iconUrl }"
class="topic-icon"
/>
<component v-else :is="icon" class="topic-icon" />
</div>
</IconOverrideProvider>
</template>

<script>
Expand All @@ -21,7 +31,9 @@ import ApiCollectionIcon from 'theme/components/Icons/APIReferenceIcon.vue';
import EndpointIcon from 'theme/components/Icons/EndpointIcon.vue';
import PathIcon from 'theme/components/Icons/PathIcon.vue';
import TutorialIcon from 'theme/components/Icons/TutorialIcon.vue';
import SVGIcon from 'docc-render/components/SVGIcon.vue';
import { TopicRole } from 'docc-render/constants/roles';
import IconOverrideProvider from 'docc-render/components/IconOverrideProvider.vue';

const TopicRoleIcons = {
[TopicRole.article]: ArticleIcon,
Expand All @@ -36,11 +48,16 @@ const TopicRoleIcons = {
};

export default {
components: { IconOverrideProvider, SVGIcon },
props: {
role: {
type: String,
required: true,
},
imageOverride: {
type: Object,
default: null,
},
},

computed: {
Expand Down
15 changes: 12 additions & 3 deletions src/components/DocumentationTopic/TopicsLinkBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
class="link"
ref="apiChangesDiff"
>
<TopicLinkBlockIcon v-if="topic.role && !change" :role="topic.role" />
<TopicLinkBlockIcon
v-if="topic.role && !change"
:role="topic.role"
:imageOverride="references[iconOverride]"
/>
<DecoratedTopicTitle v-if="topic.fragments" :tokens="topic.fragments" />
<WordBreak v-else :tag="titleTag">{{ topic.title }}</WordBreak>
<span v-if="change" class="visuallyhidden">- {{ changeName }}</span>
Expand Down Expand Up @@ -66,7 +70,8 @@ import WordBreak from 'docc-render/components/WordBreak.vue';
import ContentNode from 'docc-render/components/DocumentationTopic/ContentNode.vue';
import TopicLinkBlockIcon from 'docc-render/components/DocumentationTopic/TopicLinkBlockIcon.vue';
import DecoratedTopicTitle from 'docc-render/components/DocumentationTopic/DecoratedTopicTitle.vue';
import ConditionalConstraints from 'docc-render/components/DocumentationTopic/ConditionalConstraints.vue';
import ConditionalConstraints
from 'docc-render/components/DocumentationTopic/ConditionalConstraints.vue';
import RequirementMetadata

from 'docc-render/components/DocumentationTopic/Description/RequirementMetadata.vue';
Expand Down Expand Up @@ -98,7 +103,7 @@ export default {
RequirementMetadata,
ConditionalConstraints,
},
inject: ['store'],
inject: ['store', 'references'],
mixins: [getAPIChanges, APIChangesMultipleLines],
constants: {
ReferenceType,
Expand Down Expand Up @@ -208,6 +213,10 @@ export default {
),
// pick only the first available tag
tags: ({ topic }) => (topic.tags || []).slice(0, 1),
iconOverride: ({ topic: { images = [] } }) => {
const icon = images.find(({ type }) => type === 'icon');
return icon ? icon.identifier : null;
},
},
};
</script>
Expand Down
35 changes: 35 additions & 0 deletions src/components/IconOverrideProvider.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
-->

<script>
export default {
name: 'IconOverrideProvider',
props: {
imageOverride: {
type: Object,
default: null,
},
},
computed: {
imageOverrideVariant: ({ imageOverride }) => (imageOverride ? imageOverride.variants[0] : null),
iconUrl: ({ imageOverrideVariant }) => imageOverrideVariant && imageOverrideVariant.url,
themeId: ({ imageOverrideVariant }) => imageOverrideVariant && imageOverrideVariant.svgID,
shouldUseOverride: ({ iconUrl, themeId }) => !!(iconUrl && themeId),
},
render() {
const { shouldUseOverride, iconUrl, themeId } = this;
return this.$scopedSlots.default({
shouldUseOverride,
iconUrl,
themeId,
});
},
};
</script>
6 changes: 6 additions & 0 deletions src/components/Navigator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
:api-changes="apiChanges"
:allow-hiding="allowHiding"
:enableQuickNavigation="enableQuickNavigation"
:navigator-references="navigatorReferences"
@close="$emit('close')"
/>
<NavigatorCardInner v-else class="loading-placeholder">
Expand Down Expand Up @@ -55,6 +56,7 @@ import { getSetting } from 'docc-render/utils/theme-settings';
* @property {number} uid - generated UID
* @property {string} title - title of symbol
* @property {string} type - symbol type, used for the icon
* @property {string} icon - an image reference to override the type icon
* @property {array} abstract - symbol abstract
* @property {string} path - path to page, used in navigation
* @property {number} parent - parent UID
Expand Down Expand Up @@ -101,6 +103,10 @@ export default {
type: Object,
default: () => {},
},
navigatorReferences: {
type: Object,
default: () => {},
},
scrollLockID: {
type: String,
default: '',
Expand Down
5 changes: 5 additions & 0 deletions src/components/Navigator/NavigatorCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
:api-change="apiChangesObject[item.path]"
:isFocused="focusedIndex === index"
:enableFocus="!externalFocusChange"
:navigator-references="navigatorReferences"
@toggle="toggle"
@toggle-full="toggleFullTree"
@toggle-siblings="toggleSiblings"
Expand Down Expand Up @@ -253,6 +254,10 @@ export default {
type: Boolean,
default: true,
},
navigatorReferences: {
type: Object,
default: () => {},
},
},
mixins: [
keyboardNavigation,
Expand Down
11 changes: 8 additions & 3 deletions src/components/Navigator/NavigatorCardItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@
/>
</button>
</div>
<NavigatorLeafIcon
<TopicTypeIcon
v-if="!isGroupMarker && !apiChange"
:type="item.type"
:image-override="item.icon ? navigatorReferences[item.icon] : null"
class="navigator-icon"
/>
<span
Expand Down Expand Up @@ -93,7 +94,7 @@

<script>
import InlineChevronRightIcon from 'theme/components/Icons/InlineChevronRightIcon.vue';
import NavigatorLeafIcon from 'docc-render/components/Navigator/NavigatorLeafIcon.vue';
import TopicTypeIcon from 'docc-render/components/TopicTypeIcon.vue';
import HighlightMatches from 'docc-render/components/Navigator/HighlightMatches.vue';
import Reference from 'docc-render/components/ContentNode/Reference.vue';
import Badge from 'docc-render/components/Badge.vue';
Expand All @@ -111,7 +112,7 @@ export default {
],
components: {
HighlightMatches,
NavigatorLeafIcon,
TopicTypeIcon,
InlineChevronRightIcon,
Reference,
Badge,
Expand Down Expand Up @@ -154,6 +155,10 @@ export default {
type: Boolean,
default: true,
},
navigatorReferences: {
type: Object,
default: () => ({}),
},
},
idState() {
return {
Expand Down
5 changes: 4 additions & 1 deletion src/components/Navigator/NavigatorDataProvider.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default {
navigationIndex: {
[Language.swift.key.url]: [],
},
navigationReferences: {},
diffs: null,
};
},
Expand Down Expand Up @@ -73,8 +74,9 @@ export default {
async fetchIndexData() {
try {
this.isFetching = true;
const { interfaceLanguages } = await fetchIndexPathsData();
const { interfaceLanguages, references } = await fetchIndexPathsData();
this.navigationIndex = Object.freeze(interfaceLanguages);
this.navigationReferences = Object.freeze(references);
} catch (e) {
this.errorFetching = true;
} finally {
Expand All @@ -89,6 +91,7 @@ export default {
errorFetching: this.errorFetching,
isFetchingAPIChanges: this.isFetchingAPIChanges,
apiChanges: this.diffs,
references: this.navigationReferences,
});
},
};
Expand Down
21 changes: 19 additions & 2 deletions src/components/SVGIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,30 @@
aria-hidden="true"
class="svg-icon"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<slot />
<use v-if="themeOverrideURL" :href="`${themeOverrideURL}#${themeId}`" />
<slot v-else />
</svg>
</template>

<script>
export default { name: 'SVGIcon' };
export default {
name: 'SVGIcon',
props: {
themeId: {
type: String,
required: false,
},
iconUrl: {
type: String,
default: null,
},
},
computed: {
themeOverrideURL: ({ iconUrl }) => iconUrl,
},
};
</script>

<style scoped lang="scss">
Expand Down
Loading