diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/_data/badges.yaml | 44 | ||||
-rw-r--r-- | content/assets/javascripts/badges.js | 182 | ||||
-rw-r--r-- | content/assets/stylesheets/_tables.scss | 4 | ||||
-rw-r--r-- | content/assets/stylesheets/_typography.scss | 19 | ||||
-rw-r--r-- | content/assets/stylesheets/stylesheet.scss | 114 | ||||
-rw-r--r-- | content/frontend/default/components/docs_badges.vue | 71 | ||||
-rw-r--r-- | content/frontend/default/default.js | 49 | ||||
-rw-r--r-- | content/frontend/search/recently_viewed.js | 6 | ||||
-rw-r--r-- | content/frontend/shared/dom.js | 16 |
9 files changed, 192 insertions, 313 deletions
diff --git a/content/_data/badges.yaml b/content/_data/badges.yaml new file mode 100644 index 00000000..d27eabba --- /dev/null +++ b/content/_data/badges.yaml @@ -0,0 +1,44 @@ +badgeIndex: + # Tiers + - id: free + label: All tiers + type: tier + text: Free, Premium, and Ultimate + - id: premium + label: Premium + type: tier + link: https://about.gitlab.com/pricing/?glm_source=docs.gitlab.com&glm_content=badges-docs + - id: ultimate + label: Ultimate + type: tier + link: https://about.gitlab.com/pricing/?glm_source=docs.gitlab.com&glm_content=badges-docs + + # Offerings + - id: self + label: Self-managed + type: offering + - id: saas + label: SaaS + type: offering + - id: all + label: All offerings + type: offering + text: Self-managed and SaaS + + # Statuses + - id: experiment + label: Experiment + text: This feature is in the process of being developed. It's not production-ready but we encourage you to try it and provide feedback. + type: status + link: https://docs.gitlab.com/ee/policy/experiment-beta-support.html#experiment + - id: beta + label: Beta + text: This feature is not production-ready, but is unlikely to change drastically before it's released. We encourage you to try it and provide feedback. + type: status + link: https://docs.gitlab.com/ee/policy/experiment-beta-support.html#beta + + # Content tags + - id: contribute + label: Contribute + text: This content is about development of the GitLab product. + type: content diff --git a/content/assets/javascripts/badges.js b/content/assets/javascripts/badges.js deleted file mode 100644 index 9244526f..00000000 --- a/content/assets/javascripts/badges.js +++ /dev/null @@ -1,182 +0,0 @@ -(function() { - const classes = ['core-only', 'core', 'starter-only', 'premium-only', 'ultimate-only', 'starter', 'premium', 'ultimate', 'free-only' , 'bronze-only', 'silver-only', 'gold-only', 'free', 'free-saas', 'free-self', 'premium-saas', 'premium-self', 'ultimate-saas', 'ultimate-self', 'contribute']; - - const BADGES_TITLES = { - // Free - free: 'On GitLab self-managed and GitLab SaaS, available in all tiers.', - 'free-self': - 'On GitLab self-managed, available in all tiers. Not available on GitLab SaaS.', - 'free-only': - 'On GitLab SaaS, available in all tiers. Not available on self-managed.', - 'free-saas': - 'On GitLab SaaS, available in all tiers. Not available on self-managed.', - // Premium - premium: 'On GitLab self-managed and GitLab SaaS, available in Premium and Ultimate.', - 'premium-saas': - 'On GitLab SaaS, available in Premium and Ultimate. Not available on self-managed.', - 'silver-only': - 'On GitLab SaaS, available in Premium and Ultimate. Not available on self-managed.', - 'premium-only': - 'On GitLab self-managed, available in Premium and Ultimate. Not available on GitLab SaaS.', - 'premium-self': - 'On GitLab self-managed, available in Premium and Ultimate. Not available on GitLab SaaS.', - // Ultimate - ultimate: 'On GitLab self-managed and GitLab SaaS, available in Ultimate.', - 'ultimate-only': - 'On GitLab self-managed, available in Ultimate. Not available on GitLab SaaS.', - 'ultimate-self': - 'On GitLab self-managed, available in Ultimate. Not available on GitLab SaaS.', - 'ultimate-saas': - 'On GitLab SaaS, available in Ultimate. Not available on self-managed.', - 'gold-only': - 'On GitLab SaaS, available in Ultimate. Not available on self-managed.', - // Deprecated badges - core: 'On GitLab self-managed and GitLab SaaS, available in all tiers.', - 'core-only': - 'On GitLab self-managed, available in all tiers. Not available on GitLab SaaS.', - starter: 'Available on GitLab Starter, GitLab.com Bronze, and higher tiers.', - 'starter-only': - 'Available on GitLab Starter and higher tiers. Not available on GitLab.com.', - 'bronze-only': - 'Available on GitLab Bronze and higher tiers. Not available on self-managed.', - // Contributor page badge - 'contribute': - 'Use this content to contribute to GitLab development.' - }; - - const BADGES_MAPPING = { - // Free - core: ['all tiers'], - free: ['all tiers'], - 'core-only': ['all tiers', 'self-managed'], - 'free-self': ['all tiers', 'self-managed'], - 'free-only': ['all tiers', 'saas'], - 'free-saas': ['all tiers', 'saas'], - // Premium - premium: ['premium'], - 'silver-only': ['premium', 'saas'], - 'premium-only': ['premium', 'self-managed'], - 'premium-self': ['premium', 'self-managed'], - 'premium-saas': ['premium', 'saas'], - // Ultimate - ultimate: ['ultimate'], - 'ultimate-only': ['ultimate', 'self-managed'], - 'gold-only': ['ultimate', 'saas'], - 'ultimate-self': ['ultimate', 'self-managed'], - 'ultimate-saas': ['ultimate', 'saas'], - // Deprecated badges - starter: ['starter', 'bronze'], - 'starter-only': ['starter'], - 'bronze-only': ['bronze'], - // Contributor badge - contribute: ['contribute'] - }; - - const BADGES_CLASS = { - // Tier class - core: 'tier', - starter: 'tier', - premium: 'tier', - ultimate: 'tier', - 'all tiers': 'tier', - // Contributors - 'contribute': 'contribute', - // GitLab SaaS - bronze: 'saas', - silver: 'saas', - gold: 'saas', - saas: 'saas', - // GitLab self-managed - 'self-managed': 'self-managed', - }; - - // Check if the currently-viewed page is GitLab contributor documentation. - const isContributorDocs = () => { - const paths = ['/ee/development/', '/omnibus/development/', '/runner/development/', '/charts/development/']; - return paths.some(substr => window.location.pathname.startsWith(substr)) - } - - function init() { - // Insert markup for the "Contribute" badge if this is a contributor doc page. - if (isContributorDocs()) { - $('<span class="badge-trigger contribute"></span>').insertBefore('h1 a'); - } - - var $badges = $('.badge-trigger'); - - $badges.each(function() { - convertBadge($(this)); - }); - - $('[data-toggle="tooltip"]').tooltip(); - } - - function convertBadge($badge) { - var small = isSmall($badge); - var badgeType = retrieveBadgeType($badge); - - var smallBadgeTag = function(title) { - return $('<span>', { - class: 'badge-small', - html: '<%= icon("information-o", 14) %>', - 'data-title': title, - }); - }; - - var largeBadgeTag = function(badge, badgeClass) { - return $('<div>', { - class: 'badge-display badge-' + badgeClass, - text: badge, - }); - }; - - var template = function(title, badges) { - let container = $('<a>', { - class: 'badges-drop', - 'data-toggle': 'tooltip', - 'data-placement': 'top', - 'target': '_blank', - title: title, - href: 'https://about.gitlab.com/pricing/?glm_source=docs.gitlab.com&glm_content=badges-docs' - }); - if (isContributorDocs()) { - container.attr({href: "https://docs.gitlab.com/ee/development/"}) - } - container.append($('<span>').append(badges)); - return container; - }; - - var tags = []; - - if (small) { - tags.push(smallBadgeTag(BADGES_MAPPING[badgeType].join(' | '))); - } else { - $.each(BADGES_MAPPING[badgeType], function(i, badge) { - tags.push(largeBadgeTag(badge, BADGES_CLASS[badge])); - }); - } - - $badge.append($(template(BADGES_TITLES[badgeType], tags))); - } - - // Get the badge type from a specific list of expected values in element class - function retrieveBadgeType($badge) { - const classType = $badge.attr('class').split(' '); - const match = classes.filter(matchingClass => classType.includes(matchingClass)); - if (match) { - return match.pop(); - } - } - - // When badge is not in a HTML header, we use the small version - function isSmall($badge) { - return !$badge - .parent() - .prop('tagName') - .match(/H1|H2|H3|H4|H5/); - } - - $(function() { - init(); - }); -})(); diff --git a/content/assets/stylesheets/_tables.scss b/content/assets/stylesheets/_tables.scss index 1414859b..0f8a9ce0 100644 --- a/content/assets/stylesheets/_tables.scss +++ b/content/assets/stylesheets/_tables.scss @@ -57,10 +57,6 @@ table { border-bottom: 0 !important; /* stylelint-enable declaration-no-important */ } - - .badge-drop { - display: none; - } } } diff --git a/content/assets/stylesheets/_typography.scss b/content/assets/stylesheets/_typography.scss index 7a7fc7c4..6e1ce8a0 100644 --- a/content/assets/stylesheets/_typography.scss +++ b/content/assets/stylesheets/_typography.scss @@ -172,20 +172,6 @@ } } - // Badge tier - - .badge-tier { - color: $red-500; - font-size: 0.75rem; - font-weight: 800; - text-transform: uppercase; - - &:hover { - border-bottom-color: $red-700; - color: $red-700; - } - } - .introduced-in { border-left: 4px solid $theme-indigo-200; padding-left: 0.75rem; @@ -354,11 +340,6 @@ } } - .sm { - @include gl-font-size-markdown-sm; - @include gl-line-height-20; - } - .monospace { @include gl-font-monospace; @include gl-font-size-monospace; diff --git a/content/assets/stylesheets/stylesheet.scss b/content/assets/stylesheets/stylesheet.scss index ebaa60bd..3a1d074a 100644 --- a/content/assets/stylesheets/stylesheet.scss +++ b/content/assets/stylesheets/stylesheet.scss @@ -374,115 +374,25 @@ p.result-snippet { font-size: 0.875rem; } -//badges -.badges-drop { - display: inline-block; - cursor: pointer; - transition: background-color 0.5s ease-in-out; - /* stylelint-disable declaration-no-important */ - border-bottom: 0 !important; - /* stylelint-enable declaration-no-important */ - - &:hover { +// Badges +.docs-badges-wrapper { + a.gl-link { border-bottom: 0; + color: inherit; } - - .badge-tier, - .badge-self-managed, - .badge-saas, - .badge-contribute { - &::after { - content: ''; - display: block; - width: 0; - height: 1px; - transition: width 0.3s; - opacity: 0.5; - } - } - - .badge-tier, - .badge-contribute { - &::after { - background: $badge-tier; - } - } - - .badge-self-managed { - &::after { - background: $badge-self-managed; - } - } - - .badge-saas { - &::after { - background: $badge-saas; - } - } - &:hover { - .badge-tier, - .badge-self-managed, - .badge-saas, - .badge-contribute { - &::after { - width: 100%; - } - } - } -} - -.badge-tier { - color: $badge-tier; -} - -.badge-self-managed { - color: $badge-self-managed; - padding-left: 5px; -} - -.badge-saas { - color: $badge-saas; - padding-left: 5px; } - -.badge-contribute { - color: $badge-tier; - padding-left: 5px; +// Badges in headings +.badge-heading-true span.gl-badge { + vertical-align: super; } - -.badge-small { - color: $badge-self-managed; - opacity: 0.6; - transition: opacity 0.3s; - &:hover { - opacity: 1; - &::after { - content: attr(data-title); - text-transform: uppercase; - font-weight: 700; - font-size: 0.7em; - display: inline; - position: absolute; - padding: 1px 5px; - opacity: 1; - background-color: $white; - white-space: nowrap; - border-radius: 2px; - max-width: 150px; - } - } +// Badges in regular content +.badge-heading-false span.gl-badge { + vertical-align: middle; } -.badge-display { - text-transform: uppercase; - text-align: center; - display: inline-block; - margin-left: 2px; - border-radius: 2px; +// Tooltips +.tooltip { font-size: 0.75rem; - font-weight: 700; - letter-spacing: 0.02em; - line-height: 1.4; } //in-page styles diff --git a/content/frontend/default/components/docs_badges.vue b/content/frontend/default/components/docs_badges.vue new file mode 100644 index 00000000..d8722ac3 --- /dev/null +++ b/content/frontend/default/components/docs_badges.vue @@ -0,0 +1,71 @@ +<script> +import { GlBadge, GlTooltipDirective, GlLink } from '@gitlab/ui'; +import { badgeIndex } from '../../../_data/badges.yaml'; + +export default { + components: { + GlBadge, + GlLink, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + props: { + badgesData: { + type: Array, + required: true, + }, + isHeading: { + type: Boolean, + required: true, + }, + }, + data() { + return { + badges: [], + }; + }, + created() { + // Pull in more badge info from the badges.yaml file + this.badgesData.forEach((badge) => { + this.badges.push(badgeIndex.find((obj) => obj.id.includes(badge.text))); + }); + }, + methods: { + getBadgeVariant(type) { + const variantMapping = { + tier: 'tier', + offering: 'info', + status: 'neutral', + content: 'warning', + }; + return variantMapping[type] || ''; + }, + getBadgeSize(isHeading) { + return isHeading ? 'md' : 'sm'; + }, + }, +}; +</script> + +<template> + <span :class="`docs-badges-wrapper badge-heading-${isHeading} gl-ml-2`"> + <gl-badge + v-for="badge in badges" + :key="badge" + v-gl-tooltip.top + :variant="getBadgeVariant(badge.type)" + :title="badge.text" + class="gl-mr-2" + :size="getBadgeSize(isHeading)" + > + <component + :is="badge.link ? 'GlLink' : 'span'" + :href="badge.link" + class="docs-badge gl-font-sm" + > + {{ badge.label }} + </component> + </gl-badge> + </span> +</template> diff --git a/content/frontend/default/default.js b/content/frontend/default/default.js index 9b4b6053..f4c92c54 100644 --- a/content/frontend/default/default.js +++ b/content/frontend/default/default.js @@ -1,16 +1,63 @@ /* global Vue */ -import { getNextUntil } from '../shared/dom'; +import { getNextUntil, isContainedInHeading } from '../shared/dom'; import NavigationToggle from './components/navigation_toggle.vue'; import VersionBanner from './components/version_banner.vue'; import { setupTableOfContents } from './setup_table_of_contents'; import VersionsMenu from './components/versions_menu.vue'; import TabsSection from './components/tabs_section.vue'; +import DocsBadges from './components/docs_badges.vue'; /* eslint-disable no-new */ document.addEventListener('DOMContentLoaded', () => { setupTableOfContents(); /** + * Badge components + * + * Badges are typically added in markdown and rendered by Nanoc as spans. + * Contributor docs have a section-wide badge added here. + */ + const isContributorDocs = () => { + const paths = [ + '/ee/development/', + '/omnibus/development/', + '/runner/development/', + '/charts/development/', + ]; + return paths.some((substr) => window.location.pathname.startsWith(substr)); + }; + // Inject markup for our Contributor docs badge. + if (isContributorDocs()) { + document + .querySelector('h1 a') + .insertAdjacentHTML( + 'beforebegin', + ' <span data-component="docs-badges"><span data-type="content" data-value="contribute"></span></span>', + ); + } + document.querySelectorAll('[data-component="docs-badges"]').forEach((badgeSet) => { + const badges = badgeSet.querySelectorAll('span'); + + // Get badges that were added to the heading + const badgesData = Array.from(badges).map((badge) => ({ + type: badge.getAttribute('data-type'), + text: badge.getAttribute('data-value'), + })); + + new Vue({ + el: badgeSet, + components: { + DocsBadges, + }, + render(createElement) { + return createElement(DocsBadges, { + props: { badgesData, isHeading: isContainedInHeading(badgeSet) }, + }); + }, + }); + }); + + /** * Banner components */ const versionBanner = document.querySelector('#js-version-banner'); diff --git a/content/frontend/search/recently_viewed.js b/content/frontend/search/recently_viewed.js index 5a69ee3b..a16e0f52 100644 --- a/content/frontend/search/recently_viewed.js +++ b/content/frontend/search/recently_viewed.js @@ -31,10 +31,6 @@ export const getCookie = (name) => { // Writes page URLs to a cookie export const trackPageHistory = () => { - if (document.querySelector('h1') === null) { - return; - } - let pageHistory = []; const currentPath = window.location.pathname; const cookieValue = getCookie('pageHistory'); @@ -52,7 +48,7 @@ export const trackPageHistory = () => { // Add the current page URL to the beginning of the history array pageHistory.unshift({ path: currentPath, - title: document.querySelector('h1').textContent, + title: document.title.replace(' | GitLab', ''), }); // Keep only the designated amount of pages in history diff --git a/content/frontend/shared/dom.js b/content/frontend/shared/dom.js index 4e285a01..f632fe0d 100644 --- a/content/frontend/shared/dom.js +++ b/content/frontend/shared/dom.js @@ -29,3 +29,19 @@ export const getNextUntil = (el, selector) => { return siblings.join(''); }; + +/** + * Check if an element is contained within a heading. + * + * @param {Element} el + * @returns {Boolean} + */ +export const isContainedInHeading = (el) => { + // Loop upwards in the DOM through all parent elements, checking for headers. + for (let parent = el.parentNode; parent !== null; parent = parent.parentNode) { + if (parent.tagName && /^H\d$/.test(parent.tagName)) { + return true; + } + } + return false; +}; |