diff --git a/.gitlab/ci/build-images.gitlab-ci.yml b/.gitlab/ci/build-images.gitlab-ci.yml index cde1e2b75db..1e228fdafde 100644 --- a/.gitlab/ci/build-images.gitlab-ci.yml +++ b/.gitlab/ci/build-images.gitlab-ci.yml @@ -49,7 +49,7 @@ build-gdk-image: - .base-image-build-buildx - .build-images:rules:build-gdk-image tags: - - saas-linux-xlarge-amd64 + - docker stage: build-images needs: - job: retag-gdk-image diff --git a/.gitlab/ci/database.gitlab-ci.yml b/.gitlab/ci/database.gitlab-ci.yml index 293d6a8a22b..3102b863c16 100644 --- a/.gitlab/ci/database.gitlab-ci.yml +++ b/.gitlab/ci/database.gitlab-ci.yml @@ -45,9 +45,11 @@ db:rollback single-db: - .single-db - .rails:rules:single-db +# https://docs.gitlab.com/ee/development/database/dbmigrate:multi-version-upgrade-job.html db:migrate:multi-version-upgrade: extends: - .db-job-base + - .rails:rules:db:migrate:multi-version-upgrade script: - curl -o latest_upgrade_stop.gz https://gitlab.com/gitlab-org/quality/pg-dump-generator/-/raw/main/pg_dumps/ee/latest_upgrade_stop.gz - gunzip -c latest_upgrade_stop.gz > gitlabhq_production @@ -55,7 +57,6 @@ db:migrate:multi-version-upgrade: - apt-get update -qq && apt-get install -y -qq postgresql - psql --output /dev/null -v "ON_ERROR_STOP=1" -h postgres -U postgres -d gitlabhq_test < gitlabhq_production - bundle exec rake gitlab:db:configure - allow_failure: true db:migrate:reset: extends: .db-job-base diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index efbddf9091b..2944dd8afc8 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -156,10 +156,10 @@ if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' .if-dot-com-gitlab-org-and-security-merge-request: &if-dot-com-gitlab-org-and-security-merge-request - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org/security" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")' .if-dot-com-gitlab-org-and-security-tag: &if-dot-com-gitlab-org-and-security-tag - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG' + if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_COMMIT_TAG' .if-ruby-branch: &if-ruby-branch if: '$CI_COMMIT_BRANCH =~ /^ruby\d+(_\d)*$/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby\d+(_\d)*/' @@ -1904,6 +1904,12 @@ - <<: *if-merge-request changes: *decomposed-db-models-patterns +.rails:rules:db:migrate:multi-version-upgrade: + rules: + - if: '$DISABLE_DB_MULTI_VERSION_UPGRADE =~ /true|yes|1/i' + when: never + - !reference [".rails:rules:ee-and-foss-migration", rules] + .rails:rules:db-backup: rules: - <<: *if-merge-request-labels-pipeline-expedite diff --git a/app/assets/javascripts/achievements/components/achievements_app.vue b/app/assets/javascripts/achievements/components/achievements_app.vue index dc85b8699e7..d3e2cdf9741 100644 --- a/app/assets/javascripts/achievements/components/achievements_app.vue +++ b/app/assets/javascripts/achievements/components/achievements_app.vue @@ -7,7 +7,7 @@ import { GlKeysetPagination, GlLoadingIcon, } from '@gitlab/ui'; -import { groupBy } from 'lodash'; +import { uniqBy } from 'lodash'; import { s__ } from '~/locale'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; import { NEW_ROUTE_NAME } from '../constants'; @@ -103,9 +103,7 @@ export default { }; }, uniqueRecipients(userAchievements) { - return Object.entries(groupBy(userAchievements, 'user.id')).map(([, values]) => { - return values[0].user; - }); + return uniqBy(userAchievements, 'user.id').map(({ user }) => user); }, }, i18n: { diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js index 58b08772337..993dddcc6e6 100644 --- a/app/assets/javascripts/behaviors/markdown/render_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js @@ -14,7 +14,7 @@ function initPopovers(elements) { .catch(() => {}); } -// Render GitLab flavoured Markdown +// Render GitLab flavored Markdown export function renderGFM(element) { if (!element) { return; @@ -25,7 +25,7 @@ export function renderGFM(element) { '.js-render-kroki[hidden]', '.js-render-math', '.js-render-mermaid', - '[lang="json"][data-lang-params="table"]', + '[data-canonical-lang="json"][data-lang-params="table"]', '.gfm-project_member', '.gfm-issue, .gfm-work_item, .gfm-merge_request, .gfm-epic', ].map((selector) => Array.from(element.querySelectorAll(selector))); diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js index f80d0e5c1d9..ff11f7a5220 100644 --- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -261,8 +261,8 @@ export const GO_TO_PROJECT_FILES = { defaultKeys: ['g f'], // eslint-disable-line @gitlab/require-i18n-strings }; -export const GO_TO_PROJECT_FIND_FILE = { - id: 'project.goToFindFile', +export const START_SEARCH_PROJECT_FILE = { + id: 'project.startSearchFile', description: __('Go to find file'), defaultKeys: ['t'], }; @@ -588,7 +588,7 @@ const PROJECT_SHORTCUTS_GROUP = { GO_TO_PROJECT_ACTIVITY_FEED, GO_TO_PROJECT_RELEASES, GO_TO_PROJECT_FILES, - GO_TO_PROJECT_FIND_FILE, + START_SEARCH_PROJECT_FILE, GO_TO_PROJECT_COMMITS, GO_TO_PROJECT_REPO_GRAPH, GO_TO_PROJECT_REPO_CHARTS, diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js index e05694c0907..8ca7cb0d859 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js @@ -3,13 +3,14 @@ import { flatten } from 'lodash'; import Vue from 'vue'; import { Mousetrap, addStopCallback } from '~/lib/mousetrap'; import { getCookie, setCookie, parseBoolean } from '~/lib/utils/common_utils'; - +import { waitForElement } from '~/lib/utils/dom_utils'; import findAndFollowLink from '~/lib/utils/navigation_utility'; -import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility'; +import { refreshCurrentPage } from '~/lib/utils/url_utility'; import { keysFor, TOGGLE_KEYBOARD_SHORTCUTS_DIALOG, START_SEARCH, + START_SEARCH_PROJECT_FILE, FOCUS_FILTER_BAR, TOGGLE_PERFORMANCE_BAR, HIDE_APPEARING_CONTENT, @@ -23,7 +24,6 @@ import { GO_TO_YOUR_GROUPS, GO_TO_MILESTONE_LIST, GO_TO_YOUR_SNIPPETS, - GO_TO_PROJECT_FIND_FILE, GO_TO_YOUR_REVIEW_REQUESTS, } from './keybindings'; import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle'; @@ -75,6 +75,7 @@ export default class Shortcuts { this.addAll([ [TOGGLE_KEYBOARD_SHORTCUTS_DIALOG, this.onToggleHelp], + [START_SEARCH_PROJECT_FILE, Shortcuts.focusSearchFile], [START_SEARCH, Shortcuts.focusSearch], [FOCUS_FILTER_BAR, this.focusFilter.bind(this)], [TOGGLE_PERFORMANCE_BAR, Shortcuts.onTogglePerfBar], @@ -98,13 +99,6 @@ export default class Shortcuts { keysFor(TOGGLE_MARKDOWN_PREVIEW).includes(combo) ? false : undefined, ); - const findFileURL = document.body.dataset.findFile; - if (typeof findFileURL !== 'undefined' && findFileURL !== null) { - this.add(GO_TO_PROJECT_FIND_FILE, () => { - visitUrl(findFileURL); - }); - } - $(document).on('click', '.js-shortcuts-modal-trigger', this.onToggleHelp); if (shouldDisableShortcuts()) { @@ -263,6 +257,17 @@ export default class Shortcuts { } } + static async focusSearchFile(e) { + e?.preventDefault(); + document.querySelector('#super-sidebar-search')?.click(); + + const searchInput = await waitForElement('#super-sidebar-search-modal #search'); + if (!searchInput) return; + + searchInput.value = '~'; + searchInput.dispatchEvent(new Event('input')); + } + static hideAppearingContent(e) { const elements = document.querySelectorAll('.tooltip, .popover'); diff --git a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue index 3569119c7db..aaf25d1878c 100644 --- a/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue +++ b/app/assets/javascripts/ci/runner/admin_runners/admin_runners_app.vue @@ -66,9 +66,15 @@ export default { type: String, required: true, }, + allowRegistrationToken: { + type: Boolean, + required: false, + default: false, + }, registrationToken: { type: String, - required: true, + required: false, + default: null, }, }, data() { @@ -212,6 +218,7 @@ export default { {{ s__('Runners|New instance runner') }} { return null; } - const { newRunnerPath, registrationToken } = el.dataset; + const { newRunnerPath, allowRegistrationToken, registrationToken } = el.dataset; const { cacheConfig, typeDefs, localMutations } = createLocalState(); const apolloProvider = new VueApollo({ @@ -50,6 +51,7 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { return h(AdminRunnersApp, { props: { newRunnerPath, + allowRegistrationToken: parseBoolean(allowRegistrationToken), registrationToken, }, }); diff --git a/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue b/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue index 0154cd2a3ec..207c5513d26 100644 --- a/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue +++ b/app/assets/javascripts/ci/runner/components/registration/registration_dropdown.vue @@ -5,8 +5,10 @@ import { GlDisclosureDropdownItem, GlDisclosureDropdownGroup, GlIcon, + GlLink, + GlSprintf, } from '@gitlab/ui'; -import { s__ } from '~/locale'; +import { helpPagePath } from '~/helpers/help_page_helper'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import RunnerInstructionsModal from '~/vue_shared/components/runner_instructions/runner_instructions_modal.vue'; import { @@ -21,30 +23,34 @@ import { import RegistrationToken from './registration_token.vue'; import RegistrationTokenResetDropdownItem from './registration_token_reset_dropdown_item.vue'; +const REGISTRATION_TOKEN_ENABLED = 'REGISTRATION_TOKEN_ENABLED'; +const REGISTRATION_TOKEN_DISABLED = 'REGISTRATION_TOKEN_DISABLED'; +const REGISTRATION_TOKEN_HIDDEN = 'REGISTRATION_TOKEN_HIDDEN'; + export default { - i18n: { - showInstallationInstructions: s__( - 'Runners|Show runner installation and registration instructions', - ), - supportForRegistrationTokensDeprecated: s__( - 'Runners|Support for registration tokens is deprecated', - ), - }, components: { GlDisclosureDropdown, GlDisclosureDropdownItem, GlDisclosureDropdownGroup, GlDropdownForm, GlIcon, + GlLink, + GlSprintf, RegistrationToken, RunnerInstructionsModal, RegistrationTokenResetDropdownItem, }, mixins: [glFeatureFlagMixin()], props: { + allowRegistrationToken: { + type: Boolean, + required: false, + default: false, + }, registrationToken: { type: String, - required: true, + required: false, + default: null, }, type: { type: String, @@ -72,6 +78,23 @@ export default { return I18N_REGISTER_RUNNER; } }, + isRegistrationTokenPresent() { + return Boolean(this.registrationToken); + }, + state() { + if (this.registrationToken && this.allowRegistrationToken) { + // Legacy registration with registration token can be used, will be fully removed by 18.0 + return REGISTRATION_TOKEN_ENABLED; + } + if (!this.allowRegistrationToken) { + // If registration is disabled by admins or group owners, display the dropdown with a message + return REGISTRATION_TOKEN_DISABLED; + } + + // If registration is still enabled for the instance or group, but the user cannot see the + // token due to permissions, hide this control as they don't have access + return REGISTRATION_TOKEN_HIDDEN; + }, }, methods: { onShowInstructionsClick() { @@ -86,11 +109,18 @@ export default { this.$refs.runnerRegistrationDropdown.close(); }, }, + REGISTRATION_TOKEN_ENABLED, + REGISTRATION_TOKEN_DISABLED, + REGISTRATION_TOKEN_HIDDEN, + registrationTokenDisabledHelpPagePath: helpPagePath('ci/runners/new_creation_workflow.html', { + anchor: 'using-registration-tokens-after-gitlab-170', + }), }; diff --git a/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue index cafac061c12..40f67ac1ea5 100644 --- a/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue +++ b/app/assets/javascripts/ci/runner/group_runners/group_runners_app.vue @@ -65,6 +65,11 @@ export default { required: false, default: null, }, + allowRegistrationToken: { + type: Boolean, + required: false, + default: false, + }, registrationToken: { type: String, required: false, @@ -223,7 +228,7 @@ export default { {{ s__('Runners|New group runner') }} { } const { + allowRegistrationToken, registrationToken, runnerInstallHelpPage, newRunnerPath, @@ -44,9 +46,10 @@ export const initGroupRunners = (selector = '#js-group-runners') => { render(h) { return h(GroupRunnersApp, { props: { - registrationToken, groupFullPath, newRunnerPath, + allowRegistrationToken: parseBoolean(allowRegistrationToken), + registrationToken, }, }); }, diff --git a/app/assets/javascripts/ci/runner/project_runners/register/index.js b/app/assets/javascripts/ci/runner/project_runners/register/index.js index 9986c93c918..d07d13fd94c 100644 --- a/app/assets/javascripts/ci/runner/project_runners/register/index.js +++ b/app/assets/javascripts/ci/runner/project_runners/register/index.js @@ -3,6 +3,7 @@ import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; import RegistrationDropdown from '~/ci/runner/components/registration/registration_dropdown.vue'; import { PROJECT_TYPE } from '~/ci/runner/constants'; +import { parseBoolean } from '~/lib/utils/common_utils'; Vue.use(VueApollo); @@ -15,7 +16,7 @@ export const initProjectRunnersRegistrationDropdown = ( return null; } - const { registrationToken, projectId } = el.dataset; + const { allowRegistrationToken, registrationToken, projectId } = el.dataset; const apolloProvider = new VueApollo({ defaultClient: createDefaultClient(), @@ -30,6 +31,7 @@ export const initProjectRunnersRegistrationDropdown = ( render(h) { return h(RegistrationDropdown, { props: { + allowRegistrationToken: parseBoolean(allowRegistrationToken), registrationToken, type: PROJECT_TYPE, }, diff --git a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue index 7b3ed9ab084..48791bf8b84 100644 --- a/app/assets/javascripts/integrations/edit/components/dynamic_field.vue +++ b/app/assets/javascripts/integrations/edit/components/dynamic_field.vue @@ -140,6 +140,11 @@ export default { return !this.propsSource.editable; }, }, + watch: { + model(newValue) { + this.$emit('update', newValue); + }, + }, created() { if (this.isNonEmptyPassword) { this.model = null; diff --git a/app/assets/javascripts/integrations/edit/components/sections/configuration.vue b/app/assets/javascripts/integrations/edit/components/sections/configuration.vue index b162851d735..5bbbbe13b41 100644 --- a/app/assets/javascripts/integrations/edit/components/sections/configuration.vue +++ b/app/assets/javascripts/integrations/edit/components/sections/configuration.vue @@ -40,6 +40,7 @@ export default { v-bind="field" :field-class="fieldClass" :is-validated="isValidated" + @update="$emit('update', { value: $event, field })" /> diff --git a/app/assets/javascripts/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js index 5f54243d4e5..fa323d0e80e 100644 --- a/app/assets/javascripts/lib/utils/dom_utils.js +++ b/app/assets/javascripts/lib/utils/dom_utils.js @@ -1,4 +1,5 @@ import { has } from 'lodash'; +import { __ } from '~/locale'; import { isInIssuePage, isInMRPage, isInEpicPage } from './common_utils'; /** @@ -139,3 +140,39 @@ export const replaceCommentsWith = (el, tagName) => { commentNode = iterator.nextNode(); } }; + +/** + * Wait for an element to become available in the DOM + * @param {String} selector - the query selector for the target element + * @param {Number} timeoutDelay - how long to wait before timing out + * @returns {Promise} A promise that resolves when the element becomes available + */ +export const waitForElement = (selector, timeoutDelay = 5000) => + new Promise((resolve, reject) => { + let element; + + const findElement = () => { + // Set `element` here to prevent unnecessary DOM lookups + if (!element) element = document.querySelector(selector); + return element; + }; + + if (findElement()) { + resolve(findElement()); + } else { + let timeout; + const observer = new MutationObserver(() => { + if (findElement()) { + observer.disconnect(); + clearTimeout(timeout); + resolve(findElement()); + } + }); + + observer.observe(document.body, { childList: true, subtree: true }); + timeout = setTimeout(() => { + observer.disconnect(); + reject(__('Timeout: Element not found')); + }, timeoutDelay); // disconnect if no element was found + } + }); diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js index 1b772ff4d4c..a123a134ef3 100644 --- a/app/assets/javascripts/pages/projects/show/index.js +++ b/app/assets/javascripts/pages/projects/show/index.js @@ -1,6 +1,7 @@ import Vue from 'vue'; import { addShortcutsExtension } from '~/behaviors/shortcuts'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; +import { initFindFileShortcut } from '~/projects/behaviors'; import initClustersDeprecationAlert from '~/projects/clusters_deprecation_alert'; import leaveByUrl from '~/namespaces/leave_by_url'; import initTerraformNotification from '~/projects/terraform_notification'; @@ -82,3 +83,4 @@ const initCodeDropdown = () => { initCodeDropdown(); initSourceCodeDropdowns(); +initFindFileShortcut(); diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js index edecb798686..95c66d8899c 100644 --- a/app/assets/javascripts/pages/projects/tree/show/index.js +++ b/app/assets/javascripts/pages/projects/tree/show/index.js @@ -2,6 +2,7 @@ import $ from 'jquery'; import initTree from 'ee_else_ce/repository'; import { addShortcutsExtension } from '~/behaviors/shortcuts'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; +import { initFindFileShortcut } from '~/projects/behaviors'; import NewCommitForm from '~/new_commit_form'; import initAmbiguousRefModal from '~/ref/init_ambiguous_ref_modal'; @@ -9,3 +10,4 @@ new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new initTree(); initAmbiguousRefModal(); addShortcutsExtension(ShortcutsNavigation); +initFindFileShortcut(); diff --git a/app/assets/javascripts/projects/behaviors.js b/app/assets/javascripts/projects/behaviors.js new file mode 100644 index 00000000000..d01436aa5ef --- /dev/null +++ b/app/assets/javascripts/projects/behaviors.js @@ -0,0 +1,7 @@ +import Shortcuts from '~/behaviors/shortcuts/shortcuts'; + +export const initFindFileShortcut = () => { + const findFileButton = document.querySelector('.shortcuts-find-file'); + if (!findFileButton) return; + findFileButton.addEventListener('click', Shortcuts.focusSearchFile); +}; diff --git a/app/assets/javascripts/repository/components/blob_controls.vue b/app/assets/javascripts/repository/components/blob_controls.vue index ad182de17c7..af7dc9ecc2a 100644 --- a/app/assets/javascripts/repository/components/blob_controls.vue +++ b/app/assets/javascripts/repository/components/blob_controls.vue @@ -4,13 +4,14 @@ import { __ } from '~/locale'; import { createAlert } from '~/alert'; import getRefMixin from '~/repository/mixins/get_ref'; import initSourcegraph from '~/sourcegraph'; +import Shortcuts from '~/behaviors/shortcuts/shortcuts'; import { addShortcutsExtension } from '~/behaviors/shortcuts'; import { shouldDisableShortcuts } from '~/behaviors/shortcuts/shortcuts_toggle'; import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob'; import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater'; import { keysFor, - GO_TO_PROJECT_FIND_FILE, + START_SEARCH_PROJECT_FILE, PROJECT_FILES_GO_TO_PERMALINK, } from '~/behaviors/shortcuts/keybindings'; import { sanitize } from '~/lib/dompurify'; @@ -98,10 +99,10 @@ export default { return !this.blobInfo.storedExternally && this.blobInfo.externalStorage !== 'lfs'; }, findFileShortcutKey() { - return keysFor(GO_TO_PROJECT_FIND_FILE)[0]; + return keysFor(START_SEARCH_PROJECT_FILE)[0]; }, findFileTooltip() { - const { description } = GO_TO_PROJECT_FIND_FILE; + const { description } = START_SEARCH_PROJECT_FILE; const key = this.findFileShortcutKey; return shouldDisableShortcuts() ? null @@ -150,6 +151,9 @@ export default { document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'), ); }, + handleFindFile() { + Shortcuts.focusSearchFile(); + }, }, }; @@ -160,8 +164,8 @@ export default { v-gl-tooltip.html="findFileTooltip" :aria-keyshortcuts="findFileShortcutKey" data-testid="find" - :href="blobInfo.findFilePath" :class="$options.buttonClassList" + @click="handleFindFile" > {{ $options.i18n.findFile }} diff --git a/app/assets/javascripts/search/sidebar/components/app.vue b/app/assets/javascripts/search/sidebar/components/app.vue index 1b549b12e4f..0fb267a03f1 100644 --- a/app/assets/javascripts/search/sidebar/components/app.vue +++ b/app/assets/javascripts/search/sidebar/components/app.vue @@ -2,6 +2,7 @@ // eslint-disable-next-line no-restricted-imports import { mapState, mapGetters } from 'vuex'; import { __ } from '~/locale'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import ScopeSidebarNavigation from '~/search/sidebar/components/scope_sidebar_navigation.vue'; import SidebarPortal from '~/super_sidebar/components/sidebar_portal.vue'; import { toggleSuperSidebarCollapsed } from '~/super_sidebar/super_sidebar_collapsed_state_manager'; @@ -47,6 +48,7 @@ export default { MilestonesFilters, AllScopesStartFilters, }, + mixins: [glFeatureFlagsMixin()], computed: { ...mapState(['searchType']), ...mapGetters(['currentScope']), @@ -57,7 +59,9 @@ export default { return this.searchType === SEARCH_TYPE_ADVANCED; }, isZoektSearch() { - return this.searchType === SEARCH_TYPE_ZOEKT; + return ( + this.searchType === SEARCH_TYPE_ZOEKT && this.glFeatures.searchAddArchivedFilterToZoekt + ); }, showIssuesFilters() { return this.currentScope === SCOPE_ISSUES; diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue index 53c39f14313..084644a3091 100644 --- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue +++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue @@ -80,7 +80,7 @@ export default { }, computed: { issuableId() { - return getIdFromGraphQLId(this.issuable.id); + return getIdFromGraphQLId(this.issuable.id) || this.issuable.id; }, issuableIid() { return this.issuable.iid; diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index 3600a0fbed5..e92a2c81e80 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -10,7 +10,9 @@ class Groups::RunnersController < Groups::ApplicationController urgency :low def index + @allow_registration_token = @group.allow_runner_registration_token? @group_runner_registration_token = @group.runners_token if can?(current_user, :register_group_runners, group) + @group_new_runner_path = new_group_runner_path(@group) if can?(current_user, :create_runner, group) Gitlab::Tracking.event(self.class.name, 'index', user: current_user, namespace: @group) diff --git a/app/graphql/mutations/merge_requests/update.rb b/app/graphql/mutations/merge_requests/update.rb index 427e07e4a70..3d247a34512 100644 --- a/app/graphql/mutations/merge_requests/update.rb +++ b/app/graphql/mutations/merge_requests/update.rb @@ -66,3 +66,5 @@ module Mutations end end end + +Mutations::MergeRequests::Update.prepend_mod_with('Mutations::MergeRequests::Update') diff --git a/app/graphql/types/merge_requests/mergeability_check_status_enum.rb b/app/graphql/types/merge_requests/mergeability_check_status_enum.rb index d3b95316b67..a3649764a66 100644 --- a/app/graphql/types/merge_requests/mergeability_check_status_enum.rb +++ b/app/graphql/types/merge_requests/mergeability_check_status_enum.rb @@ -17,6 +17,10 @@ module Types value 'INACTIVE', value: 'inactive', description: 'Mergeability check is disabled via settings.' + + value 'WARNING', + value: 'warning', + description: 'Mergeability check has passed with a warning.' end end end diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb index f92352afaed..6de589286d5 100644 --- a/app/helpers/ci/runners_helper.rb +++ b/app/helpers/ci/runners_helper.rb @@ -59,6 +59,7 @@ module Ci # https://gitlab.com/gitlab-org/gitlab-runner runner_install_help_page: 'https://docs.gitlab.com/runner/install/', new_runner_path: new_admin_runner_path, + allow_registration_token: Gitlab::CurrentSettings.allow_runner_registration_token.to_s, registration_token: Gitlab::CurrentSettings.runners_registration_token, online_contact_timeout_secs: ::Ci::Runner::ONLINE_CONTACT_TIMEOUT.to_i, stale_timeout_secs: ::Ci::Runner::STALE_TIMEOUT.to_i, diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index b710cb11ec0..d3aecfbd04c 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -501,6 +501,8 @@ module ApplicationSettingImplementation end def runners_registration_token + return unless Gitlab::CurrentSettings.allow_runner_registration_token + ensure_runners_registration_token! end diff --git a/app/models/group.rb b/app/models/group.rb index 264fe57abfb..82e85c827df 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -776,6 +776,8 @@ class Group < Namespace # we do this on read since migrating all existing groups is not a feasible # solution. def runners_token + return unless allow_runner_registration_token? + ensure_runners_token! end diff --git a/app/models/project.rb b/app/models/project.rb index a5b92571bf8..82417988cc9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2249,6 +2249,8 @@ class Project < ApplicationRecord end def runners_token + return unless namespace.allow_runner_registration_token? + ensure_runners_token! end diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb index 7eaf35122a6..58b46a20386 100644 --- a/app/models/system_note_metadata.rb +++ b/app/models/system_note_metadata.rb @@ -24,7 +24,7 @@ class SystemNoteMetadata < ApplicationRecord opened closed merged duplicate locked unlocked outdated reviewer tag due_date start_date_or_due_date pinned_embed cherry_pick health_status approved unapproved status alert_issue_added relate unrelate new_alert_added severity contact timeline_event - issue_type relate_to_child unrelate_from_child relate_to_parent unrelate_from_parent + issue_type relate_to_child unrelate_from_child relate_to_parent unrelate_from_parent override ].freeze validates :note, presence: true, unless: :importing? diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index c145b44bbcc..9adfb0db8d8 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -110,6 +110,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy @subject.runner_registration_enabled? end + condition(:runner_registration_token_enabled, scope: :subject) do + @subject.allow_runner_registration_token? + end + condition(:raise_admin_package_to_owner_enabled) do Feature.enabled?(:raise_group_admin_package_permission_to_owner, @subject) end @@ -375,6 +379,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy prevent :create_runner end + rule { ~runner_registration_token_enabled }.policy do + prevent :register_group_runners + end + rule { migration_bot }.policy do enable :read_resource_access_tokens enable :destroy_resource_access_tokens diff --git a/app/services/ci/components/usages/create_service.rb b/app/services/ci/components/usages/create_service.rb new file mode 100644 index 00000000000..e6876ff0146 --- /dev/null +++ b/app/services/ci/components/usages/create_service.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Ci + module Components + module Usages + class CreateService + def initialize(component, used_by_project:) + @component = component + @used_by_project = used_by_project + end + + def execute + component_usage = Ci::Catalog::Resources::Components::Usage.new( + component: component, + catalog_resource: component.catalog_resource, + project: component.project, + used_by_project_id: used_by_project.id + ) + + if component_usage.valid? + component_usage.save + + return ServiceResponse.success(message: 'Usage recorded') + end + + errors = component_usage.errors + + if errors.size == 1 && errors.first.type == :taken # Only unique validation failed + ServiceResponse.success(message: 'Usage already recorded for today') + else + ServiceResponse.error(message: errors.full_messages.join(', ')) + end + end + + private + + attr_reader :component, :used_by_project + end + end + end +end diff --git a/app/services/ci/runners/register_runner_service.rb b/app/services/ci/runners/register_runner_service.rb index 0c13c32e236..4f585291e5f 100644 --- a/app/services/ci/runners/register_runner_service.rb +++ b/app/services/ci/runners/register_runner_service.rb @@ -53,6 +53,8 @@ module Ci strong_memoize_attr :attrs_from_token def registration_token_allowed?(attrs) + return false if registration_token.nil? + case attrs[:runner_type] when :group_type token_scope.allow_runner_registration_token? @@ -64,6 +66,8 @@ module Ci end def runner_registration_token_valid?(registration_token) + return false if registration_token.nil? + ActiveSupport::SecurityUtils.secure_compare(registration_token, Gitlab::CurrentSettings.runners_registration_token) end diff --git a/app/services/merge_requests/mergeability/check_base_service.rb b/app/services/merge_requests/mergeability/check_base_service.rb index 8f8ba812246..495e305806d 100644 --- a/app/services/merge_requests/mergeability/check_base_service.rb +++ b/app/services/merge_requests/mergeability/check_base_service.rb @@ -49,6 +49,11 @@ module MergeRequests .inactive(payload: default_payload(args)) end + def warning(**args) + Gitlab::MergeRequests::Mergeability::CheckResult + .warning(payload: default_payload(args)) + end + def default_payload(args) args.merge(identifier: self.class.identifier) end diff --git a/app/views/admin/application_settings/_runner_registrars_form.html.haml b/app/views/admin/application_settings/_runner_registrars_form.html.haml index 36bab2f6650..99bef033fec 100644 --- a/app/views/admin/application_settings/_runner_registrars_form.html.haml +++ b/app/views/admin/application_settings/_runner_registrars_form.html.haml @@ -15,13 +15,13 @@ %h5 = s_('Runners|Runner registration') %span.form-text.gl-mb-3.gl-mt-0 - = s_('Runners|If both settings are disabled, new runners cannot be registered.') - = link_to _('Learn more.'), help_page_path('administration/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer' - = hidden_field_tag "application_setting[valid_runner_registrars][]", nil - - ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES.each do |type| - = f.gitlab_ui_checkbox_component :valid_runner_registrars, s_("Runners|Members of the %{type} can register runners") % { type: type }, - checkbox_options: { multiple: true, checked: valid_runner_registrars.include?(type) }, - checked_value: type, - unchecked_value: nil + = f.gitlab_ui_checkbox_component :allow_runner_registration_token, s_("AdminSettings|Allow runner registration token"), help_text: s_("AdminSettings|When disabled, runner registration tokens are disabled from runner pages, and maintainers and owners cannot use registration tokens to register runners. They can use runner authentication tokens instead as the more secure runner registration method.") + + = hidden_field_tag "application_setting[valid_runner_registrars][]", nil + - ApplicationSetting::VALID_RUNNER_REGISTRAR_TYPES.each do |type| + = f.gitlab_ui_checkbox_component :valid_runner_registrars, s_("Runners|Members of the %{type} can create runners") % { type: type }, + checkbox_options: { multiple: true, checked: valid_runner_registrars.include?(type) }, + checked_value: type, + unchecked_value: nil = f.submit _('Save changes'), pajamas_button: true diff --git a/app/views/groups/runners/index.html.haml b/app/views/groups/runners/index.html.haml index d619635d3e0..ecd5b473a69 100644 --- a/app/views/groups/runners/index.html.haml +++ b/app/views/groups/runners/index.html.haml @@ -1,3 +1,3 @@ - page_title s_('Runners|Runners') -#js-group-runners{ data: group_runners_data_attributes(@group).merge({ registration_token: @group_runner_registration_token, new_runner_path: @group_new_runner_path }) } +#js-group-runners{ data: group_runners_data_attributes(@group).merge({ allow_registration_token: @allow_registration_token.to_s, registration_token: @group_runner_registration_token, new_runner_path: @group_new_runner_path }) } diff --git a/app/views/projects/_find_file_link.html.haml b/app/views/projects/_find_file_link.html.haml index 8fa285fe2b1..39e452cf66c 100644 --- a/app/views/projects/_find_file_link.html.haml +++ b/app/views/projects/_find_file_link.html.haml @@ -1,9 +1,3 @@ -- find_file_description = _('Go to find file') -- find_file_shortcut = 't' -- find_file_title = "#{find_file_description} " -= link_button_to _('Find file'), project_find_file_path(@project, @ref, ref_type: @ref_type), - 'aria-keyshortcuts': find_file_shortcut, - class: 'has-tooltip shortcuts-find-file', - 'data-html': true, - title: find_file_title, - rel: 'nofollow' +- find_file_title = "Go to file, press or " += render Pajamas::ButtonComponent.new(button_options: { class: 'has-tooltip shortcuts-find-file', title: find_file_title, 'aria-keyshortcuts': "/+~ t", 'data-html': true }) do + = _('Find file') diff --git a/app/views/projects/runners/_project_runners.html.haml b/app/views/projects/runners/_project_runners.html.haml index a5a83fe0309..65899c38f1c 100644 --- a/app/views/projects/runners/_project_runners.html.haml +++ b/app/views/projects/runners/_project_runners.html.haml @@ -8,7 +8,11 @@ = render Pajamas::ButtonComponent.new(href: new_project_runner_path(@project), variant: :confirm) do = s_('Runners|New project runner') .gl-display-inline - #js-project-runner-registration-dropdown{ data: { registration_token: @project.runners_token, project_id: @project.id } } + #js-project-runner-registration-dropdown{ data: { + allow_registration_token: @project.namespace.allow_runner_registration_token?.to_s, + registration_token: @project.runners_token, + project_id: @project.id + } } - else = _('Please contact an admin to create runners.') = link_to _('Learn more.'), help_page_path('administration/settings/continuous_integration', anchor: 'restrict-runner-registration-by-all-users-in-an-instance'), target: '_blank', rel: 'noopener noreferrer' diff --git a/config/feature_flags/development/ci_retry_on_exit_codes.yml b/config/feature_flags/development/ci_retry_on_exit_codes.yml index eb5f4abb618..37bf61858a2 100644 --- a/config/feature_flags/development/ci_retry_on_exit_codes.yml +++ b/config/feature_flags/development/ci_retry_on_exit_codes.yml @@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/430037 milestone: '16.7' type: development group: group::pipeline authoring -default_enabled: false +default_enabled: true diff --git a/config/initializers/action_view_patch.rb b/config/initializers/action_view_patch.rb new file mode 100644 index 00000000000..3bce965a432 --- /dev/null +++ b/config/initializers/action_view_patch.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# Even though `ActionView::Helpers::AssetTagHelper.preload_links_header` +# is set to false, `preload_link_tag` sends the Link header if the total +# header size to send is under 8K. However, this causes HTTP responses +# to fail in NGINX if the default `proxy_buffer_size` is set too low. +# +# Ironically because `app/views/layouts/_loading_hints.html.haml` is a +# cached partial, `preload_link_tag` generates the HTML, but only +# actually sends the `Link` header once a minute when the cache expires. +# This suggests that the `Link` header isn't really helping much, and it +# causes more trouble than it's worth. +# +# Rails 7.1 lowered the `preload_link_tag` limit to 1000 bytes in +# https://github.com/rails/rails/pull/48405, but that may not be +# sufficient. +# +# https://github.com/rails/rails/issues/51436 proposes to disable the +# sending of the Link header entirely. This patch does this by turning +# send_preload_links_header into a NOP. +# +# We can probably drop this patch for Rails 7.1 and up, but we might +# want to wait for https://github.com/rails/rails/pull/51441 or some +# mechanism that can disable the `Link` header. +if Gem::Version.new(ActionView.version) >= Gem::Version.new('7.1') + raise 'New version of ActionView detected. This patch can likely be removed.' +end + +require "action_view/helpers/asset_tag_helper" + +module ActionView + module Helpers + module AssetTagHelper + def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE); end + end + end +end diff --git a/db/docs/bulk_imports.yml b/db/docs/bulk_imports.yml index c5f41fdc896..86011dc032e 100644 --- a/db/docs/bulk_imports.yml +++ b/db/docs/bulk_imports.yml @@ -4,7 +4,8 @@ classes: - BulkImport feature_categories: - importers -description: Used to store and track the status of a bulk import request of groups or projects +description: Used to store and track the status of a bulk import request of groups + or projects introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42978 milestone: '13.5' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_clusterwide diff --git a/db/docs/error_tracking_error_events.yml b/db/docs/error_tracking_error_events.yml index 4e0d6b5a268..b5acb67795b 100644 --- a/db/docs/error_tracking_error_events.yml +++ b/db/docs/error_tracking_error_events.yml @@ -7,4 +7,19 @@ feature_categories: description: Persists error event data for the Error Tracking's GitLab backend introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64712 milestone: '14.1' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: error_id + table: error_tracking_errors + sharding_key: project_id + belongs_to: error diff --git a/db/docs/saved_replies.yml b/db/docs/saved_replies.yml index c1d4a51ce0d..147c3200368 100644 --- a/db/docs/saved_replies.yml +++ b/db/docs/saved_replies.yml @@ -7,4 +7,4 @@ feature_categories: description: Text templates used to populate comments using a quick action introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80807 milestone: '14.9' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_clusterwide diff --git a/db/docs/sentry_issues.yml b/db/docs/sentry_issues.yml index 25ff1ff9b8f..07049c7693c 100644 --- a/db/docs/sentry_issues.yml +++ b/db/docs/sentry_issues.yml @@ -7,4 +7,19 @@ feature_categories: description: Persists issue data for the Error Tracking's Sentry backend introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20629 milestone: '12.6' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + namespace_id: + references: namespaces + backfill_via: + parent: + foreign_key: issue_id + table: issues + sharding_key: namespace_id + belongs_to: issue diff --git a/db/migrate/20240327114933_add_override_changes_requested_to_merge_request.rb b/db/migrate/20240327114933_add_override_changes_requested_to_merge_request.rb new file mode 100644 index 00000000000..8d7ca328fd6 --- /dev/null +++ b/db/migrate/20240327114933_add_override_changes_requested_to_merge_request.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddOverrideChangesRequestedToMergeRequest < Gitlab::Database::Migration[2.2] + enable_lock_retries! + + milestone '16.11' + + def change + add_column :merge_requests, :override_requested_changes, :boolean, default: false, null: false + end +end diff --git a/db/schema_migrations/20240327114933 b/db/schema_migrations/20240327114933 new file mode 100644 index 00000000000..9190d4f16aa --- /dev/null +++ b/db/schema_migrations/20240327114933 @@ -0,0 +1 @@ +4df10234f382af204774214a1eaf7bbfc8d231ab8571ccf10b4fdc2caaedc9e5 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 693313a3158..f36df93bb7f 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11253,6 +11253,7 @@ CREATE TABLE merge_requests ( draft boolean DEFAULT false NOT NULL, prepared_at timestamp with time zone, merged_commit_sha bytea, + override_requested_changes boolean DEFAULT false NOT NULL, CONSTRAINT check_970d272570 CHECK ((lock_version IS NOT NULL)) ); diff --git a/doc/administration/settings/usage_statistics.md b/doc/administration/settings/usage_statistics.md index 23e88a7edd3..5a7f80dc3ca 100644 --- a/doc/administration/settings/usage_statistics.md +++ b/doc/administration/settings/usage_statistics.md @@ -153,10 +153,6 @@ The payload is available in the [Metrics and profiling](#manually-upload-service ### Through the configuration file -NOTE: -The method to disable Service Ping in the GitLab configuration file does not work in -GitLab versions 9.3 to 13.12.3. For more information about how to disable it, see [troubleshooting](../../development/internal_analytics/service_ping/troubleshooting.md#cannot-disable-service-ping-with-the-configuration-file). - To disable Service Ping and prevent it from being configured in the future through the Admin Area. @@ -209,9 +205,6 @@ For an example payload, see [Example Service Ping payload](../../development/int ## Manually upload Service Ping payload -> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7388) in GitLab 14.8 with a flag named `admin_application_settings_service_usage_data_center`. Disabled by default. -> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/83265) in GitLab 14.10. - You can upload the Service Ping payload to GitLab even if your instance doesn't have internet access, or if the Service Ping [cron job](../../development/internal_analytics/service_ping/index.md#how-service-ping-works) is not enabled. diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md index 5d8aef1ac58..aa28c70e375 100644 --- a/doc/api/error_tracking.md +++ b/doc/api/error_tracking.md @@ -10,8 +10,6 @@ DETAILS: **Tier:** Free, Premium, Ultimate **Offering:** GitLab.com, Self-managed, GitLab Dedicated -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34940) in GitLab 12.7. - ## Error Tracking project settings The project settings API allows you to retrieve the [Error Tracking](../operations/error_tracking.md) @@ -63,7 +61,7 @@ Supported attributes: | ------------ | ------- |----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | `id` | integer | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. | | `active` | boolean | yes | Pass `true` to enable the error tracking setting configuration or `false` to disable it. | -| `integrated` | boolean | yes | Pass `true` to enable the integrated error tracking backend. [Available in](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68260) GitLab 14.2 and later. | +| `integrated` | boolean | yes | Pass `true` to enable the integrated error tracking backend. | Example request: @@ -96,7 +94,7 @@ PATCH /projects/:id/error_tracking/settings | ------------ | ------- | -------- | --------------------- | | `id` | integer | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. | | `active` | boolean | yes | Pass `true` to enable the already configured error tracking settings or `false` to disable it. | -| `integrated` | boolean | no | Pass `true` to enable the integrated error tracking backend. [Available in](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68260) GitLab 14.2 and later. | +| `integrated` | boolean | no | Pass `true` to enable the integrated error tracking backend. | ```shell curl --request PATCH --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/1/error_tracking/settings?active=true" @@ -116,8 +114,6 @@ Example response: ## Error Tracking client keys -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68384) in GitLab 14.3. - For [integrated error tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) feature. Only for users with the Maintainer role for the project. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 541342f26a5..4ba6f276710 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -6079,6 +6079,7 @@ Input type: `MergeRequestUpdateInput` | `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | `description` | [`String`](#string) | Description of the merge request (Markdown rendered as HTML for caching). | | `iid` | [`String!`](#string) | IID of the merge request to mutate. | +| `overrideRequestedChanges` | [`Boolean`](#boolean) | Override all requested changes. Can only be set by users who have permissionto merge this merge request. | | `projectPath` | [`ID!`](#id) | Project the merge request to mutate is in. | | `state` | [`MergeRequestNewState`](#mergerequestnewstate) | Action to perform to change the state. | | `targetBranch` | [`String`](#string) | Target branch of the merge request. | @@ -32467,6 +32468,7 @@ Representation of whether a mergeability check passed, failed or is inactive. | `FAILED` | Mergeability check has failed. The merge request cannot be merged. | | `INACTIVE` | Mergeability check is disabled via settings. | | `SUCCESS` | Mergeability check has passed. | +| `WARNING` | Mergeability check has passed with a warning. | ### `MilestoneSort` diff --git a/doc/api/usage_data.md b/doc/api/usage_data.md index 98027fd3408..21b1629bf7d 100644 --- a/doc/api/usage_data.md +++ b/doc/api/usage_data.md @@ -46,8 +46,6 @@ Example response: ## Export metric definitions as a single YAML file -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57270) in GitLab 13.11. - Export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](https://metrics.gitlab.com/), for easier importing. ```plaintext diff --git a/doc/architecture/blueprints/disaster_recovery/regional.md b/doc/architecture/blueprints/disaster_recovery/regional.md index 0ae88d2a345..eeada087bbc 100644 --- a/doc/architecture/blueprints/disaster_recovery/regional.md +++ b/doc/architecture/blueprints/disaster_recovery/regional.md @@ -42,6 +42,8 @@ This bulkhead can be used as a launching pad for a full data restore from `us-ea ### Select an alternate region +We are going with **`us-central1`**. Discussion for this was done in + - Dependencies: none - Teams: Ops diff --git a/doc/ci/components/index.md b/doc/ci/components/index.md index 7efdee7d5f7..9cf372b5620 100644 --- a/doc/ci/components/index.md +++ b/doc/ci/components/index.md @@ -590,4 +590,4 @@ This GitLab CI configuration is invalid: component 'gitlab.com/my-namespace/my-p ``` The `~latest` behavior [was updated](https://gitlab.com/gitlab-org/gitlab/-/issues/442238) -in GitLab 16.11. It now refers to the latest semantic version of the catalog resource. To resolve this issue, [create a new release](#publish-a-new-release). +in GitLab 16.10. It now refers to the latest semantic version of the catalog resource. To resolve this issue, [create a new release](#publish-a-new-release). diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 25bac0df2ab..1c9697ac369 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -3975,10 +3975,7 @@ test: #### `retry:exit_codes` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/430037) in GitLab 16.10 [with a flag](../../administration/feature_flags.md) named `ci_retry_on_exit_codes`. Disabled by default. - -FLAG: -On self-managed GitLab, by default this feature is not available. To make it available, -an administrator can [enable the feature flag](../../administration/feature_flags.md) named `ci_retry_on_exit_codes`. +> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/430037) in GitLab 16.11. Use `retry:exit_codes` with `retry:max` to retry jobs for only specific failure cases. `retry:max` is the maximum number of retries, like [`retry`](#retry), and can be diff --git a/doc/development/ai_features/index.md b/doc/development/ai_features/index.md index c5978963e59..38d5b6c0f37 100644 --- a/doc/development/ai_features/index.md +++ b/doc/development/ai_features/index.md @@ -145,21 +145,23 @@ GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[ 1. Ensure you have followed [the process to obtain an EE license](https://handbook.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee-developer-licenses) for your local instance and you applied Ultimate license. 1. To verify that the license is applied go to **Admin Area** > **Subscription** and check the subscription plan. 1. Allow use of EE features for your instance. - 1. Go to **Admin Area** > **Settings** > **General** -> **Account and limit** - 1. Enable **Allow use of licensed EE features** + 1. Go to **Admin Area > Settings > General**. + 1. Expand the **Account and limit** section. + 1. Enable **Allow use of licensed EE features**. 1. Simulate the GDK to [simulate SaaS](../ee_features.md#simulate-a-saas-instance). 1. Ensure the group you want to test has an Ultimate license. - 1. Go to **Admin Area** > **Overview** > **Groups** + 1. Go to **Admin Area > Overview > Groups**. 1. Select **Edit** for your chosen group. - 1. Go to **Permissions and group features** + 1. Go to **Permissions and group features**. 1. Choose *Ultimate* from the **Plan** list. 1. Enable `Experiment & Beta features` for your group. - 1. Go to the group with the Ultimate license - 1. **Group Settings** > **General** -> **Permissions and group features** - 1. Enable **Experiment & Beta features** -1. Enable the specific feature flag for the feature you want to test -1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework -1. Setup [AI Gateway](#local-setup) + 1. Go to the group with the Ultimate license. + 1. Select **Settings > General**. + 1. Expand the **Permissions and group features** section. + 1. Enable **Experiment & Beta features**. +1. Enable the specific feature flag for the feature you want to test. +1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework. +1. Setup [AI Gateway](#local-setup). ### Bypass AI Gateway diff --git a/doc/development/cloud_connector/index.md b/doc/development/cloud_connector/index.md index 2e6da4c106a..07a3a3bc7d0 100644 --- a/doc/development/cloud_connector/index.md +++ b/doc/development/cloud_connector/index.md @@ -101,6 +101,7 @@ To add a new feature bound to a scope: token as a scope. + `backend` is the targeted backend service and will become the token audience. `service_start_time` is the cut-off date after which payment for this feature is required. diff --git a/doc/development/database/dbmigrate:multi-version-upgrade-job.md b/doc/development/database/dbmigrate:multi-version-upgrade-job.md new file mode 100644 index 00000000000..4d79bf5da00 --- /dev/null +++ b/doc/development/database/dbmigrate:multi-version-upgrade-job.md @@ -0,0 +1,41 @@ +--- +stage: Data Stores +group: Database +info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review. +--- + +# db:migrate:multi-version-upgrade job + +> - [Introduced](https://gitlab.com/groups/gitlab-org/quality/quality-engineering/-/epics/19) in GitLab 16.11. + +This job runs on the test stage of a merge request pipeline. It validates that migrations pass +for multi-version upgrade from the latest [required upgrade stop](../../update/index.md#required-upgrade-stops) +to the author's working branch. It achieves it by running `gitlab:db:configure` against PostgreSQL +dump created from the latest known [GitLab version stop](../../update/index.md#upgrade-paths) with test data. + +The database dump is generated and maintained with [PostgreSQL Dump Generator](https://gitlab.com/gitlab-org/quality/pg-dump-generator). +To seed database with data, the tool uses Data Seeder with [`bulk_data.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/db/seeds/data_seeder/bulk_data.rb) +configuration to seed all factories and uses `db:seed_fu` to seed all [`db/fixtures`](../development_seed_files.md). +Latest dump is generated automatically in scheduled pipelines for the latest patch +release of the required stop. + +## Troubleshooting + +### Database reconfigure failures + +This failure usually happens due to an actual migration error in your working branch. +To reproduce the failure locally follow [Migration upgrade testing](https://gitlab.com/gitlab-org/quality/pg-dump-generator#migration-upgrade-testing) +guidance. It outlines the steps how to import the latest PostgreSQL dump +in your local GitLab Development Kit or GitLab Docker instance. + +For a real-life example, refer to +[this failed job](https://gitlab.com/gitlab-org/gitlab/-/jobs/6418619509#L4970). + +### Database import failures + +If job is failing on setup stage prior to `gitlab:db:configure` +due to external dependencies, the job can be disabled by setting +`DISABLE_DB_MULTI_VERSION_UPGRADE=true` in GitLab project CI variables +to unblock the [broken master](https://handbook.gitlab.com/handbook/engineering/workflow/#broken-master). + +Reach out to [Self-Managed Platform team](https://handbook.gitlab.com/handbook/engineering/infrastructure/test-platform/self-managed-platform-team/) to expedite debugging. diff --git a/doc/development/internal_analytics/metrics/metrics_instrumentation.md b/doc/development/internal_analytics/metrics/metrics_instrumentation.md index 4bdb065a6a1..e4c5a0f4562 100644 --- a/doc/development/internal_analytics/metrics/metrics_instrumentation.md +++ b/doc/development/internal_analytics/metrics/metrics_instrumentation.md @@ -170,8 +170,6 @@ end #### Estimated batch counters -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7. - Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors when used through the provided `estimate_batch_distinct_count` method. Errors return a value of `-1`. @@ -284,16 +282,12 @@ options: ### Event sourced aggregated metrics -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. - To declare the aggregate of events collected with Internal Events, make sure `time_frame` does not include the `all` value, which is unavailable for Redis-sourced aggregated metrics. While it is possible to aggregate EE-only events together with events that occur in all GitLab editions, it's important to remember that doing so may produce high variance between data collected from EE and CE GitLab instances. ### Database sourced aggregated metrics -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52784) in GitLab 13.9. - To declare an aggregate of metrics based on events collected from database, follow these steps: diff --git a/doc/development/internal_analytics/service_ping/index.md b/doc/development/internal_analytics/service_ping/index.md index 69af2f8f360..787803cb7cb 100644 --- a/doc/development/internal_analytics/service_ping/index.md +++ b/doc/development/internal_analytics/service_ping/index.md @@ -6,9 +6,6 @@ info: Any user with at least the Maintainer role can merge updates to this conte # Service Ping development guidelines -> - Introduced in GitLab Ultimate 11.2, more statistics. -> - In GitLab 14.1, [renamed from Usage Ping to Service Ping](https://gitlab.com/groups/gitlab-org/-/epics/5990). In 14.0 and earlier, use the Usage Ping documentation for the Rails commands appropriate to your version. - Service Ping is a GitLab process that collects and sends a weekly payload to GitLab. The payload provides important high-level data that helps our product, support, and sales teams understand how GitLab is used. The data helps to: diff --git a/doc/development/internal_analytics/service_ping/troubleshooting.md b/doc/development/internal_analytics/service_ping/troubleshooting.md index 637aec384c0..92228e25dec 100644 --- a/doc/development/internal_analytics/service_ping/troubleshooting.md +++ b/doc/development/internal_analytics/service_ping/troubleshooting.md @@ -90,89 +90,6 @@ However, it has the following limitations: always runs as a process alongside other GitLab components on any given node. For Service Ping, none of the node data would therefore appear to be associated to any of the services running, because they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Service Ping. -## Troubleshooting - -### Cannot disable Service Ping with the configuration file - -The method to disable Service Ping with the GitLab configuration file does not work in -GitLab versions 9.3.0 to 13.12.3. To disable it, you must use the Admin Area in -the GitLab UI instead. For more information, see -[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/333269). - -GitLab functionality and application settings cannot override or circumvent -restrictions at the network layer. If Service Ping is blocked by your firewall, -you are not impacted by this bug. - -#### Check if you are affected - -You can check if you were affected by this bug by using the Admin Area or by -checking the configuration file of your GitLab instance: - -- Using the Admin Area: - - 1. On the left sidebar, at the bottom, select **Admin Area**. - 1. On the left sidebar, select **Settings > Metrics and profiling**. - 1. Expand **Usage statistics**. - 1. Are you able to check or uncheck the checkbox to disable Service Ping? - - - If _yes_, your GitLab instance is not affected by this bug. - - If you can't check or uncheck the checkbox, you are affected by this bug. - See the steps on [how to fix this](#how-to-fix-the-cannot-disable-service-ping-bug). - -- Checking your GitLab instance configuration file: - - To check whether you're impacted by this bug, check your instance configuration - settings. The configuration file in which Service Ping can be disabled depends - on your installation and deployment method, but is typically one of the following: - - - `/etc/gitlab/gitlab.rb` for Linux package installations and Docker. - - `charts.yaml` for GitLab Helm and cloud-native Kubernetes deployments. - - `gitlab.yml` for self-compiled installations. - - To check the relevant configuration file for strings that indicate whether - Service Ping is disabled, you can use `grep`: - - ```shell - # Linux package - grep "usage_ping_enabled'\] = false" /etc/gitlab/gitlab.rb - - # Kubernetes charts - grep "enableUsagePing: false" values.yaml - - # From source - grep "usage_ping_enabled'\] = false" gitlab/config.yml - ``` - - If you see any output after running the relevant command, your GitLab instance - may be affected by the bug. Otherwise, your instance is not affected. - -#### How to fix the "Cannot disable Service Ping" bug - -To work around this bug, you have two options: - -- [Update](../../../update/index.md) to GitLab 13.12.4 or newer to fix this bug. -- If you can't update to GitLab 13.12.4 or newer, enable Service Ping in the - configuration file, then disable Service Ping in the UI. For example, if you're - using the Linux package: - - 1. Edit `/etc/gitlab/gitlab.rb`: - - ```ruby - gitlab_rails['usage_ping_enabled'] = true - ``` - - 1. Reconfigure GitLab: - - ```shell - sudo gitlab-ctl reconfigure - ``` - - 1. On the left sidebar, at the bottom, select **Admin Area**. - 1. On the left sidebar, select **Settings > Metrics and profiling**. - 1. Expand **Usage statistics**. - 1. Clear the **Enable Service Ping** checkbox. - 1. Select **Save Changes**. - ## Generate Service Ping ### Generate or get the cached Service Ping in rails console diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md index 71ccefd6bbb..9bd7da2244b 100644 --- a/doc/topics/git/lfs/index.md +++ b/doc/topics/git/lfs/index.md @@ -7,17 +7,15 @@ description: "Use Git LFS to manage binary assets, like images and video, withou # Git Large File Storage (LFS) -Managing large files such as audio, video and graphics files has always been one -of the shortcomings of Git. The general recommendation is to not have Git repositories -larger than 1 GB to preserve performance. +Git Large File Storage (LFS) can manage large binary files efficiently in Git repositories. +It addresses challenges, such as repository performance and capacity limits. +For best performance, keep your repositories as small as possible. +Git LFS creates pointers to the actual file, stored elsewhere. -Your Git LFS client communicates with the GitLab server over HTTPS. It uses HTTP Basic authentication -to authorize client requests. After the request is authorized, Git LFS client receives -instructions on where to fetch or where to push the large file. +For GitLab.com repository size limits, see [account and limit settings](../../../administration/settings/account_and_limit_settings.md). -In the repository view, files tracked by Git LFS display an **LFS** badge next to the filename: - -![Git LFS tracking status](img/lfs_badge_v16_0.png) +Git LFS clients communicate with server over HTTPS, with HTTP Basic authentication. +After the request is authorized, Git LFS client gets instructions on where to fetch or where to push the large file. ## Configure your GitLab server for Git LFS @@ -47,13 +45,19 @@ To do this: Install the [Git LFS client](https://github.com/git-lfs/git-lfs) appropriate for your operating system. GitLab requires version 1.0.1 or later of the Git LFS client. +After Git LFS is installed on the server and client, you can see the **LFS** badge +next to the filename: + +![Git LFS tracking status](img/lfs_badge_v16_0.png) + ## Known limitations - Git LFS v1 original API is not supported, because it was deprecated early in LFS development. -- When SSH is set as a remote, Git LFS objects still go through HTTPS. -- Any Git LFS request asks for HTTPS credentials, so you should use a good Git - credentials store. +- Even when Git communicates with the repository over SSH, Git LFS objects still + go through HTTPS. +- Because Git LFS requests require HTTPS credentials, you should use a good Git + [credentials store](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). - Git LFS always assumes HTTPS so if you have GitLab server on HTTP you must [add the URL to Git configuration manually](troubleshooting.md#getsockopt-connection-refused). - [Group wikis](../../../user/project/wiki/group.md) do not support Git LFS. @@ -65,16 +69,16 @@ When you add an LFS object to a repository, GitLab: 1. Creates an LFS object. 1. Associates the LFS object with the repository. 1. Queues a job to recalculate your project's statistics, including storage size and - LFS object storage. Your LFS object storage is the sum of the size of all LFS objects - associated with the repository. + LFS object storage. Your LFS object storage is the sum of the size of all LFS + objects associated with the repository. -When your repository is forked, LFS objects from the upstream project are associated -with the fork. When the fork is created, the LFS object storage for the fork is equal -to the storage used by the upstream project. If new LFS objects are added to the fork, -the total object storage changes for the fork, but not the upstream project. +When your repository is forked, the fork includes LFS objects from the upstream project. +The LFS object storage for the fork, at first, is the same size as the storage used by the upstream +project. +If new LFS objects are added to the fork, the total object storage increases only for the fork. If you create a merge request from the fork back to the upstream project, -any new LFS objects in the fork become associated with the upstream project. +new LFS objects get associated with the upstream project. ## Using Git LFS @@ -89,27 +93,23 @@ git lfs install # initialize the Git LFS project git lfs track "*.iso" # select the file extensions that you want to treat as large files ``` -After you mark a file extension for tracking as a LFS object you can use -Git as usual without redoing the command to track a file with the same extension: +These commands create a `.gitattributes` file with the file types that you want to track. +In this case, Git LFS is now tracking `*.iso` files. +You can now use these commands to push a large `*.iso` file (and the new `.gitattributes` file) to +your repository: ```shell cp ~/tmp/debian.iso ./ # copy a large file into the current directory git add . # add the large file to the project -git commit -am "Added Debian iso" # commit the file meta data +git commit -am "Add Debian iso and .gitattributes" # commit the file meta data git push origin main # sync the git repo and large file to the GitLab server ``` -**Make sure** that `.gitattributes` is tracked by Git. Otherwise Git -LFS doesn't work properly for people cloning the project: - -```shell -git add .gitattributes -git commit -am "Added .gitattributes to capture LFS tracking" -git push origin main -``` +**Make sure** you've committed `.gitattributes` to your repository. Otherwise Git +LFS doesn't work properly for those who clone it: Cloning the repository works the same as before. Git automatically detects the -LFS-tracked files and clones them via HTTP. If you performed the `git clone` +LFS-tracked files and clones them over HTTP. If you performed the `git clone` command with a SSH URL, you have to enter your GitLab credentials for HTTP authentication. @@ -117,8 +117,8 @@ authentication. git clone git@gitlab.example.com:group/my-sample-project.git ``` -If you already cloned the repository and you want to get the latest LFS object -that are on the remote repository, such as for a branch from origin: +If you already cloned the repository and want the latest LFS objects +that are on the remote repository: ```shell git lfs fetch origin main @@ -138,10 +138,6 @@ To remove objects from LFS: 1. Use [`git filter-repo`](../../../user/project/repository/reducing_the_repo_size_using_git.md) to remove the objects from the repository. 1. Delete the relevant LFS lines for the objects you have removed from your `.gitattributes` file and commit those changes. -## File Locking - -See the documentation on [File Locking](../../../user/project/file_lock.md). - ## LFS objects in project archives > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) support for including Git LFS blobs inside [project source downloads](../../../user/project/repository/index.md) in GitLab 13.5 [with a flag](../../../administration/feature_flags.md) named `include_lfs_blobs_in_archive`. Disabled by default. @@ -165,6 +161,7 @@ Technical details about how this works can be found in the [development document ## Related topics +- Use Git LFS to set up [exclusive file locks](../../../user/project/file_lock.md#exclusive-file-locks). - Blog post: [Getting started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/) - [Git LFS developer information](../../../development/lfs.md) - [GitLab Git Large File Storage (LFS) Administration](../../../administration/lfs/index.md) for self-managed instances diff --git a/doc/user/application_security/continuous_vulnerability_scanning/index.md b/doc/user/application_security/continuous_vulnerability_scanning/index.md index eefde110537..79b45104baa 100644 --- a/doc/user/application_security/continuous_vulnerability_scanning/index.md +++ b/doc/user/application_security/continuous_vulnerability_scanning/index.md @@ -15,16 +15,21 @@ DETAILS: > - Continuous Container Scanning [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/435435) in GitLab 16.8 [with a flag](../../../administration/feature_flags.md) named `container_scanning_continuous_vulnerability_scans`. Disabled by default. > - Continuous Container Scanning [enabled on GitLab.com, self-managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/issues/437162) in GitLab 16.10. -Continuous Vulnerability Scanning detects new vulnerabilities outside a pipeline. -Your projects are automatically scanned whenever advisories are added to the [`GitLab Advisory Database`](https://advisories.gitlab.com/), or [`Trivy DB`](https://github.com/aquasecurity/trivy-db). -Projects that depend on the affected components have new vulnerabilities automatically created. +When advisories are added to either the [GitLab Advisory Database](https://advisories.gitlab.com/) or the +[Trivy Database](https://github.com/aquasecurity/trivy-db), Continuous Vulnerability Scanning +triggers a scan on all projects where either Container Scanning, Dependency Scanning, or both, are +enabled. If a new advisory affects an application or operating system dependency, it creates a +vulnerability in the project. -Continuous Vulnerability Scanning detects vulnerabilities in the latest CycloneDX SBOM reports for the default branch. -[Dependency Scanning](../dependency_scanning/index.md) and [Container Scanning](../container_scanning/index.md) are used to generate these reports. +NOTE: +If a new operating system package is added to either the GitLab Advisory Database or Trivy +Database, and an advisory for it already exists, a vulnerability is **not** created. Support for +improvements is proposed in [epic 11219](https://gitlab.com/groups/gitlab-org/-/epics/11219) and +[epic 8026](https://gitlab.com/groups/gitlab-org/-/epics/8026). ## Supported package types -Components with the following [package URL types](https://github.com/package-url/purl-spec/blob/346589846130317464b677bc4eab30bf5040183a/PURL-TYPES.rst) are supported: +Continuous Vulnerability Scanning supports components with the following [PURL types](https://github.com/package-url/purl-spec/blob/346589846130317464b677bc4eab30bf5040183a/PURL-TYPES.rst): - `composer` - `conan` diff --git a/doc/user/gitlab_duo_chat.md b/doc/user/gitlab_duo_chat.md index 16a136c8161..51826de44e9 100644 --- a/doc/user/gitlab_duo_chat.md +++ b/doc/user/gitlab_duo_chat.md @@ -78,6 +78,9 @@ You can ask about a specific GitLab issue. For example: - When you are viewing an issue in GitLab, you can ask `Generate a concise summary of the current issue.` - `How can I improve the description of so that readers understand the value and problems to be solved?` +NOTE: +If the issue contains a large amount of text (more than 40,000 words), GitLab Duo Chat might not be able to consider every word. The AI model has a limit to the amount of input it can process at one time. + ### Ask about a specific epic > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/128487) for SaaS in GitLab 16.3. @@ -89,6 +92,9 @@ You can ask about a specific GitLab epic. For example: - When you are viewing an epic in GitLab, you can ask `Generate a concise summary of the opened epic.` - `What are the unique use cases raised by commenters in ?` +NOTE: +If the epic contains a large amount of text (more than 40,000 words), GitLab Duo Chat might not be able to consider every word. The AI model has a limit to the amount of input it can process at one time. + ### Ask about code > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122235) for SaaS in GitLab 16.1. diff --git a/doc/user/workspace/gitlab_agent_configuration.md b/doc/user/workspace/gitlab_agent_configuration.md index 03f409a6346..442f4cc745b 100644 --- a/doc/user/workspace/gitlab_agent_configuration.md +++ b/doc/user/workspace/gitlab_agent_configuration.md @@ -24,21 +24,16 @@ provided that the agent is properly configured for remote development. ## Remote development settings -To enable Remote Development and register a new workspace, the following GitLab Agent settings are mandatory: - -- [`enabled`] -- [`dns_zone`] - -| Setting | Description | -|-------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------| -| [`enabled`](#enabled) | Indicates whether remote development is enabled for the GitLab agent. | -| [`dns_zone`](#dns_zone) | DNS zone where workspaces are available. | -| [`gitlab_workspaces_proxy`](#gitlab_workspaces_proxy) | Namespace where [`gitlab-workspaces-proxy`](https://gitlab.com/gitlab-org/remote-development/gitlab-workspaces-proxy) is installed. | -| [`network_policy`](#network_policy) | Firewall rules for workspaces. | -| [`default_resources_per_workspace_container`](#default_resources_per_workspace_container) | Default requests and limits for CPU and memory per workspace container. | -| [`max_resources_per_workspace`](#max_resources_per_workspace) | Maximum requests and limits for CPU and memory per workspace. | -| [`workspaces_quota`](#workspaces_quota) | Maximum number of workspaces for the GitLab agent. | -| [`workspaces_per_user_quota`](#workspaces_per_user_quota) | Maximum number of workspaces per user. | +| Setting | Required | Description | +|-------------------------------------------------------------------------------------------|----------|-------------| +| [`enabled`](#enabled) | Yes | Indicates whether remote development is enabled for the GitLab agent. | +| [`dns_zone`](#dns_zone) | Yes | DNS zone where workspaces are available. | +| [`gitlab_workspaces_proxy`](#gitlab_workspaces_proxy) | No | Namespace where [`gitlab-workspaces-proxy`](https://gitlab.com/gitlab-org/remote-development/gitlab-workspaces-proxy) is installed. | +| [`network_policy`](#network_policy) | No | Firewall rules for workspaces. | +| [`default_resources_per_workspace_container`](#default_resources_per_workspace_container) | No | Default requests and limits for CPU and memory per workspace container. | +| [`max_resources_per_workspace`](#max_resources_per_workspace) | No | Maximum requests and limits for CPU and memory per workspace. | +| [`workspaces_quota`](#workspaces_quota) | No | Maximum number of workspaces for the GitLab agent. | +| [`workspaces_per_user_quota`](#workspaces_per_user_quota) | No | Maximum number of workspaces per user. | NOTE: If a setting has an invalid value, it's not possible to update any setting until you fix that value. diff --git a/glfm_specification/output_example_snapshots/html.yml b/glfm_specification/output_example_snapshots/html.yml index f5cfa95ca52..ce201f661ff 100644 --- a/glfm_specification/output_example_snapshots/html.yml +++ b/glfm_specification/output_example_snapshots/html.yml @@ -3,19 +3,19 @@ canonical: "
foo\tbaz\t\tbim\n
\n" static: "
\n
foo\tbaz\t\tbim
\n\n
" + v-pre=\"true\">foo\tbaz\t\tbim\n\n" wysiwyg: "
foo\tbaz\t\tbim
" 02_01_00__preliminaries__tabs__002: canonical: "
foo\tbaz\t\tbim\n
\n" static: "
\n
foo\tbaz\t\tbim
\n\n
" + v-pre=\"true\">foo\tbaz\t\tbim\n\n" wysiwyg: "
foo\tbaz\t\tbim
" 02_01_00__preliminaries__tabs__003: canonical: "
a\ta\nὐ\ta\n
\n" static: "
\n
a\ta\na\ta\nὐ\ta
\n\n
" wysiwyg: "
a\ta\nὐ\ta
" 02_01_00__preliminaries__tabs__004: @@ -49,7 +49,7 @@
  • foo

    -
      bar
    +
      bar
  • @@ -65,7 +65,7 @@ static: |-
    -
      foo
    +
      foo
    @@ -83,7 +83,7 @@
    • -
        foo
      +
        foo
    • @@ -97,7 +97,7 @@
      static: |-
      -
      foo
      +    
      foo
           bar
      @@ -218,7 +218,7 @@ static: |-
      -
      ***
      +
      ***
      wysiwyg: |- @@ -461,7 +461,7 @@ static: |-
      -
      # foo
      +
      # foo
      wysiwyg: |- @@ -658,7 +658,7 @@
      static: |-
      -
      Foo
      +    
      Foo
           ---
           
           Foo
      @@ -803,7 +803,7 @@

      Baz

      static: |-
      -
      Foo
      +
      Foo

      @@ -826,7 +826,7 @@
      static: |-
      -
      +
      wysiwyg: |- @@ -852,7 +852,7 @@
      static: |-
      -
      foo
      +
      foo

      @@ -950,7 +950,7 @@

      static: |-
      -
      a simple
      +    
      a simple
             indented code block
      @@ -1004,7 +1004,7 @@ static: |-
      -
      <a/>
      +    
      <a/>
           *hi*
           
           - one
      @@ -1027,7 +1027,7 @@
      static: |-
      -
      chunk1
      +    
      chunk1
           
           chunk2
           
      @@ -1048,7 +1048,7 @@
         canonical: "
      chunk1\n  \n  chunk2\n
      \n" static: |-
      -
      chunk1
      +    
      chunk1
             
             chunk2
      @@ -1072,7 +1072,7 @@

      bar

      static: |-
      -
      foo
      +
      foo

      bar

      @@ -1092,13 +1092,13 @@

      Heading

      -
      foo
      +
      foo

      Heading

      -
      foo
      +
      foo

      @@ -1115,7 +1115,7 @@
      static: |-
      -
          foo
      +    
          foo
           bar
      @@ -1128,7 +1128,7 @@
      static: |-
      -
      foo
      +
      foo
      wysiwyg: |- @@ -1137,7 +1137,7 @@ canonical: "
      foo  \n
      \n" static: |-
      -
      foo  
      +
      foo  
      wysiwyg: |- @@ -1149,7 +1149,7 @@
      static: |-
      -
      <
      +    
      <
            >
      @@ -1163,7 +1163,7 @@ static: |-
      -
      <
      +    
      <
            >
      @@ -1184,7 +1184,7 @@ static: |-
      -
      aaa
      +    
      aaa
           ~~~
      @@ -1198,7 +1198,7 @@ static: |-
      -
      aaa
      +    
      aaa
           ```
      @@ -1212,7 +1212,7 @@ static: |-
      -
      aaa
      +    
      aaa
           ```
      @@ -1226,7 +1226,7 @@ static: |-
      -
      aaa
      +    
      aaa
           ~~~
      @@ -1238,7 +1238,7 @@
      static: |-
      -
      +
      wysiwyg: |- @@ -1251,7 +1251,7 @@
      static: |-
      -
      
      +    
      
           ```
           aaa
      @@ -1270,7 +1270,7 @@ static: |-
      -
      aaa
      +
      aaa
      @@ -1282,7 +1282,7 @@ canonical: "
      \n  \n
      \n" static: |-
      -
      
      +    
      
             
      @@ -1293,7 +1293,7 @@
      static: |-
      -
      +
      wysiwyg: |- @@ -1305,7 +1305,7 @@
      static: |-
      -
      aaa
      +    
      aaa
           aaa
      @@ -1320,7 +1320,7 @@ static: |-
      -
      aaa
      +    
      aaa
           aaa
           aaa
      @@ -1337,7 +1337,7 @@
      static: |-
      -
      aaa
      +    
      aaa
            aaa
           aaa
      @@ -1354,7 +1354,7 @@
      static: |-
      -
      ```
      +    
      ```
           aaa
           ```
      @@ -1369,7 +1369,7 @@
      static: |-
      -
      aaa
      +
      aaa
      wysiwyg: |- @@ -1380,7 +1380,7 @@
      static: |-
      -
      aaa
      +
      aaa
      wysiwyg: |- @@ -1392,7 +1392,7 @@ static: |-
      -
      aaa
      +    
      aaa
               ```
      @@ -1416,7 +1416,7 @@ static: |-
      -
      aaa
      +    
      aaa
           ~~~ ~~
      @@ -1432,7 +1432,7 @@ static: |-

      foo

      -
      bar
      +
      bar

      baz

      @@ -1450,7 +1450,7 @@

      foo

      -
      bar
      +
      bar

      @@ -1467,7 +1467,7 @@ static: |-
      -
      def foo(x)
      +    
      def foo(x)
             return 3
           end
      @@ -1484,7 +1484,7 @@
      static: |-
      -
      def foo(x)
      +    
      def foo(x)
             return 3
           end
      @@ -1498,7 +1498,7 @@
      static: |-
      -
      +
      wysiwyg: |- @@ -1519,7 +1519,7 @@
      static: |-
      -
      foo
      +
      foo
      wysiwyg: |- @@ -1530,7 +1530,7 @@ static: |-
      -
      ``` aaa
      +
      ``` aaa
      wysiwyg: |- @@ -1796,7 +1796,7 @@

      okay

      static: |-
      -
      
      +    
      
           import Text.HTML.TagSoup
           
           main :: IO ()
      @@ -1987,7 +1987,7 @@
           
      static: " \n
      \n
      <!--
      +    v-pre=\"true\"><!--
           foo -->
      \n\n
      " wysiwyg: |-
      <!-- foo -->
      @@ -1999,7 +1999,7 @@ static: |2-
      -
      <div>
      +
      <div>
      @@ -2110,7 +2110,7 @@
      -
      <td>
      +    
      <td>
             Hi
           </td>
      @@ -2303,7 +2303,7 @@

      [foo]

      static: |-
      -
      [foo]: /url "title"
      +
      [foo]: /url "title"

      [foo]

      @@ -2317,7 +2317,7 @@

      [foo]

      static: |-
      -
      [foo]: /url
      +
      [foo]: /url

      [foo]

      @@ -2486,7 +2486,7 @@

      bbb

      static: |-
      -
      aaa
      +
      aaa

      bbb

      @@ -2833,7 +2833,7 @@
      static: |-
      -
      > # Foo
      +    
      > # Foo
           > bar
           > baz
      @@ -2923,12 +2923,12 @@ static: |-
      -
      foo
      +
      foo
      -
      bar
      +
      bar
      wysiwyg: |- @@ -2944,13 +2944,13 @@ static: |-
      -
      +

      foo

      -
      +
      wysiwyg: |- @@ -3181,7 +3181,7 @@ static: |-
      -
      code
      +
      code
      @@ -3204,7 +3204,7 @@

      A paragraph with two lines.

      -
      indented code
      +
      indented code
      @@ -3234,7 +3234,7 @@

      A paragraph with two lines.

      -
      indented code
      +
      indented code
      @@ -3288,7 +3288,7 @@
    • one
    • -
       two
      +
       two
      wysiwyg: |- @@ -3402,7 +3402,7 @@
    • foo

      -
      bar
      +
      bar

      baz

      @@ -3430,7 +3430,7 @@
    • Foo

      -
      bar
      +    
      bar
           
           
           baz
      @@ -3504,7 +3504,7 @@
    • foo

      -
      bar
      +
      bar
    • @@ -3525,7 +3525,7 @@
    • foo

      -
      bar
      +
      bar
    • @@ -3541,12 +3541,12 @@
      static: |-
      -
      indented code
      +
      indented code

      paragraph

      -
      more code
      +
      more code
      wysiwyg: |- @@ -3568,12 +3568,12 @@
      1. -
        indented code
        +
        indented code

        paragraph

        -
        more code
        +
        more code
      2. @@ -3595,12 +3595,12 @@
        1. -
           indented code
          +
           indented code

          paragraph

          -
          more code
          +
          more code
        2. @@ -3666,13 +3666,13 @@
        3. foo
        4. -
          bar
          +
          bar
        5. -
          baz
          +
          baz
        6. @@ -3800,7 +3800,7 @@

          A paragraph with two lines.

          -
          indented code
          +
          indented code
          @@ -3830,7 +3830,7 @@

          A paragraph with two lines.

          -
          indented code
          +
          indented code
          @@ -3860,7 +3860,7 @@

          A paragraph with two lines.

          -
          indented code
          +
          indented code
          @@ -3882,7 +3882,7 @@
    • static: |-
      -
      1.  A paragraph
      +    
      1.  A paragraph
               with two lines.
           
                   indented code
      @@ -3916,7 +3916,7 @@
           

      A paragraph with two lines.

      -
      indented code
      +
      indented code
      @@ -4342,7 +4342,7 @@
      -
      code
      +
      code
      wysiwyg: |- @@ -4440,7 +4440,7 @@
      -
      3. c
      +
      3. c
      wysiwyg: |- @@ -4570,7 +4570,7 @@
    • a
    • -
      b
      +    
      b
           
           
      @@ -4647,7 +4647,7 @@

      b

    • -
      c
      +
      c
      @@ -4698,7 +4698,7 @@
      1. -
        foo
        +
        foo

        bar

        @@ -4845,7 +4845,7 @@
      static: |-
      -
      \[\]
      +
      \[\]
      wysiwyg: |- @@ -4856,7 +4856,7 @@
      static: |-
      -
      \[\]
      +
      \[\]
      wysiwyg: |- @@ -4896,7 +4896,7 @@ static: |-
      -
      foo
      +
      foo
      wysiwyg: |- @@ -4986,7 +4986,7 @@ static: |-
      -
      foo
      +
      foo
      wysiwyg: |- @@ -5004,7 +5004,7 @@ static: |-
      -
      f&ouml;f&ouml;
      +
      f&ouml;f&ouml;
      wysiwyg: |- @@ -7705,7 +7705,7 @@ static: |-
      -
      title: YAML front matter
      +
      title: YAML front matter
      wysiwyg: |- @@ -7719,7 +7719,7 @@ static: |-
      -
      title: TOML front matter
      +
      title: TOML front matter
      wysiwyg: |- @@ -7735,7 +7735,7 @@ static: |-
      -
      {
      +    
      {
             "title": "JSON front matter"
           }
      @@ -8051,7 +8051,7 @@ TODO: Write canonical HTML for this example static: |-
      -
        console.log('hello world')
      +
        console.log('hello world')
      wysiwyg: |- @@ -8061,7 +8061,7 @@ TODO: Write canonical HTML for this example static: |-
      -
        plaintext
      +
        plaintext
      wysiwyg: |- @@ -8071,7 +8071,7 @@ TODO: Write canonical HTML for this example static: |-
      -
        custom_language = >> this <<
      +
        custom_language = >> this <<
      wysiwyg: |- @@ -8131,7 +8131,7 @@ TODO: Write canonical HTML for this example static: |-
      -
        #stroke: #a86128
      +    
        #stroke: #a86128
             [<frame>Decorator pattern|
               [<abstract>Component||+ operation()]
               [Client] depends --> [Component]
      @@ -8157,7 +8157,7 @@
           TODO: Write canonical HTML for this example
         static: |-
           
      -
        Alice -> Bob: Authentication Request
      +    
        Alice -> Bob: Authentication Request
             Bob --> Alice: Authentication Response
           
             Alice -> Bob: Another authentication Request
      @@ -8175,7 +8175,7 @@
           TODO: Write canonical HTML for this example
         static: |-
           
      -
      A -> B : Text with norwegian characters: æøå
      +
      A -> B : Text with norwegian characters: æøå
      wysiwyg: |- @@ -8249,7 +8249,7 @@ TODO: Write canonical HTML for this example static: |-
      -
      {
      +    
      {
             "title": "Page title"
           }
      @@ -8263,7 +8263,7 @@ TODO: Write canonical HTML for this example static: |-
      -
      title = "Page title"
      +
      title = "Page title"
      wysiwyg: |- @@ -8273,7 +8273,7 @@ TODO: Write canonical HTML for this example static: |-
      -
      title: Page title
      +
      title: Page title
      wysiwyg: |- @@ -8411,7 +8411,7 @@

      This math is inline a^2+b^2=c^2.

      This is on a separate line:

      -
      a^2+b^2=c^2
      +
      a^2+b^2=c^2
      wysiwyg: |- @@ -8696,7 +8696,7 @@

      Blockquotes can be in a footnote.

      -
      as well as code blocks
      +
      as well as code blocks

      or, naturally, simple paragraphs.

      @@ -8706,7 +8706,7 @@
    • -
      this is now a code block (8 spaces indentation)
      +
      this is now a code block (8 spaces indentation)
      diff --git a/glfm_specification/output_example_snapshots/snapshot_spec.html b/glfm_specification/output_example_snapshots/snapshot_spec.html index ea9c2db5447..e8c3551ea20 100644 --- a/glfm_specification/output_example_snapshots/snapshot_spec.html +++ b/glfm_specification/output_example_snapshots/snapshot_spec.html @@ -434,11 +434,11 @@ spaces.)

      -
      →foo→baz→→bim
      +
      →foo→baz→→bim
      -
      <pre><code>foo→baz→→bim
      +
      <pre><code>foo→baz→→bim
       </code></pre>
      @@ -446,11 +446,11 @@ spaces.)

      -
        →foo→baz→→bim
      +
        →foo→baz→→bim
      -
      <pre><code>foo→baz→→bim
      +
      <pre><code>foo→baz→→bim
       </code></pre>
      @@ -458,12 +458,12 @@ spaces.)

      -
          a→a
      +
          a→a
           ὐ→a
      -
      <pre><code>a→a
      +
      <pre><code>a→a
       ὐ→a
       </code></pre>
      @@ -475,13 +475,13 @@ as indentation with four spaces would:

      -
        - foo
      +
        - foo
       
       →bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>bar</p>
      @@ -493,13 +493,13 @@ as indentation with four spaces would:

      -
      - foo
      +
      - foo
       
       →→bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <pre><code>  bar
      @@ -520,11 +520,11 @@ code block starting with two spaces.

      -
      >→→foo
      +
      >→→foo
      -
      <blockquote>
      +
      <blockquote>
       <pre><code>  foo
       </code></pre>
       </blockquote>
      @@ -534,11 +534,11 @@ code block starting with two spaces.

      -
      -→→foo
      +
      -→→foo
      -
      <ul>
      +
      <ul>
       <li>
       <pre><code>  foo
       </code></pre>
      @@ -550,12 +550,12 @@ code block starting with two spaces.

      -
          foo
      +
          foo
       →bar
      -
      <pre><code>foo
      +
      <pre><code>foo
       bar
       </code></pre>
      @@ -564,13 +564,13 @@ code block starting with two spaces.

      -
       - foo
      +
       - foo
          - bar
       → - baz
      -
      <ul>
      +
      <ul>
       <li>foo
       <ul>
       <li>bar
      @@ -587,22 +587,22 @@ code block starting with two spaces.

      -
      #→Foo
      +
      #→Foo
      -
      <h1>Foo</h1>
      +
      <h1>Foo</h1>
      -
      *→*→*→
      +
      *→*→*→
      -
      <hr />
      +
      <hr />
      @@ -626,12 +626,12 @@ two items, not a list with one item containing a code span:

      -
      - `one
      +
      - `one
       - two`
      -
      <ul>
      +
      <ul>
       <li>`one</li>
       <li>two`</li>
       </ul>
      @@ -665,13 +665,13 @@ optionally by any number of spaces or tabs, forms a
      -
      ***
      +
      ***
       ---
       ___
      -
      <hr />
      +
      <hr />
       <hr />
       <hr />
      @@ -681,22 +681,22 @@ optionally by any number of spaces or tabs, forms a
      -
      +++
      +
      +++
      -
      <p>+++</p>
      +
      <p>+++</p>
      -
      ===
      +
      ===
      -
      <p>===</p>
      +
      <p>===</p>
      @@ -704,13 +704,13 @@ optionally by any number of spaces or tabs, forms a
      -
      --
      +
      --
       **
       __
      -
      <p>--
      +
      <p>--
       **
       __</p>
      @@ -720,13 +720,13 @@ optionally by any number of spaces or tabs, forms a
      -
       ***
      +
       ***
         ***
          ***
      -
      <hr />
      +
      <hr />
       <hr />
       <hr />
      @@ -736,11 +736,11 @@ optionally by any number of spaces or tabs, forms a
      -
          ***
      +
          ***
      -
      <pre><code>***
      +
      <pre><code>***
       </code></pre>
      @@ -748,12 +748,12 @@ optionally by any number of spaces or tabs, forms a
      -
      Foo
      +
      Foo
           ***
      -
      <p>Foo
      +
      <p>Foo
       ***</p>
      @@ -762,11 +762,11 @@ optionally by any number of spaces or tabs, forms a
      -
      _____________________________________
      +
      _____________________________________
      -
      <hr />
      +
      <hr />
      @@ -774,33 +774,33 @@ optionally by any number of spaces or tabs, forms a
      -
       - - -
      +
       - - -
      -
      <hr />
      +
      <hr />
      -
       **  * ** * ** * **
      +
       **  * ** * ** * **
      -
      <hr />
      +
      <hr />
      -
      -     -      -      -
      +
      -     -      -      -
      -
      <hr />
      +
      <hr />
      @@ -808,11 +808,11 @@ optionally by any number of spaces or tabs, forms a
      -
      - - - -    
      +
      - - - -    
      -
      <hr />
      +
      <hr />
      @@ -820,7 +820,7 @@ optionally by any number of spaces or tabs, forms a
      -
      _ _ _ _ a
      +
      _ _ _ _ a
       
       a------
       
      @@ -828,7 +828,7 @@ optionally by any number of spaces or tabs, forms a
       
       
      -
      <p>_ _ _ _ a</p>
      +
      <p>_ _ _ _ a</p>
       <p>a------</p>
       <p>---a---</p>
      @@ -839,11 +839,11 @@ So, this is not a thematic break:

      -
       *-*
      +
       *-*
      -
      <p><em>-</em></p>
      +
      <p><em>-</em></p>
      @@ -851,13 +851,13 @@ So, this is not a thematic break:

      -
      - foo
      +
      - foo
       ***
       - bar
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       </ul>
       <hr />
      @@ -871,13 +871,13 @@ So, this is not a thematic break:

      -
      Foo
      +
      Foo
       ***
       bar
      -
      <p>Foo</p>
      +
      <p>Foo</p>
       <hr />
       <p>bar</p>
      @@ -891,13 +891,13 @@ this is a setext heading, not a paragraph followed by a thematic break:

      -
      Foo
      +
      Foo
       ---
       bar
      -
      <h2>Foo</h2>
      +
      <h2>Foo</h2>
       <p>bar</p>
      @@ -907,13 +907,13 @@ interpretations of a line, the thematic break takes precedence:

      -
      * Foo
      +
      * Foo
       * * *
       * Bar
      -
      <ul>
      +
      <ul>
       <li>Foo</li>
       </ul>
       <hr />
      @@ -927,12 +927,12 @@ interpretations of a line, the thematic break takes precedence:

      -
      - Foo
      +
      - Foo
       - * * *
      -
      <ul>
      +
      <ul>
       <li>Foo</li>
       <li>
       <hr />
      @@ -958,7 +958,7 @@ characters in the opening sequence.

      -
      # foo
      +
      # foo
       ## foo
       ### foo
       #### foo
      @@ -967,7 +967,7 @@ characters in the opening sequence.

      -
      <h1>foo</h1>
      +
      <h1>foo</h1>
       <h2>foo</h2>
       <h3>foo</h3>
       <h4>foo</h4>
      @@ -980,11 +980,11 @@ characters in the opening sequence.

      -
      ####### foo
      +
      ####### foo
      -
      <p>####### foo</p>
      +
      <p>####### foo</p>
      @@ -998,13 +998,13 @@ headings:

      -
      #5 bolt
      +
      #5 bolt
       
       #hashtag
      -
      <p>#5 bolt</p>
      +
      <p>#5 bolt</p>
       <p>#hashtag</p>
      @@ -1013,11 +1013,11 @@ headings:

      -
      \## foo
      +
      \## foo
      -
      <p>## foo</p>
      +
      <p>## foo</p>
      @@ -1025,11 +1025,11 @@ headings:

      -
      # foo *bar* \*baz\*
      +
      # foo *bar* \*baz\*
      -
      <h1>foo <em>bar</em> *baz*</h1>
      +
      <h1>foo <em>bar</em> *baz*</h1>
      @@ -1037,11 +1037,11 @@ headings:

      -
      #                  foo                     
      +
      #                  foo                     
      -
      <h1>foo</h1>
      +
      <h1>foo</h1>
      @@ -1049,13 +1049,13 @@ headings:

      -
       ### foo
      +
       ### foo
         ## foo
          # foo
      -
      <h3>foo</h3>
      +
      <h3>foo</h3>
       <h2>foo</h2>
       <h1>foo</h1>
      @@ -1065,11 +1065,11 @@ headings:

      -
          # foo
      +
          # foo
      -
      <pre><code># foo
      +
      <pre><code># foo
       </code></pre>
      @@ -1077,12 +1077,12 @@ headings:

      -
      foo
      +
      foo
           # bar
      -
      <p>foo
      +
      <p>foo
       # bar</p>
      @@ -1091,12 +1091,12 @@ headings:

      -
      ## foo ##
      +
      ## foo ##
         ###   bar    ###
      -
      <h2>foo</h2>
      +
      <h2>foo</h2>
       <h3>bar</h3>
      @@ -1105,12 +1105,12 @@ headings:

      -
      # foo ##################################
      +
      # foo ##################################
       ##### foo ##
      -
      <h1>foo</h1>
      +
      <h1>foo</h1>
       <h5>foo</h5>
      @@ -1119,11 +1119,11 @@ headings:

      -
      ### foo ###     
      +
      ### foo ###     
      -
      <h3>foo</h3>
      +
      <h3>foo</h3>
      @@ -1133,11 +1133,11 @@ heading:

      -
      ### foo ### b
      +
      ### foo ### b
      -
      <h3>foo ### b</h3>
      +
      <h3>foo ### b</h3>
      @@ -1145,11 +1145,11 @@ heading:

      -
      # foo#
      +
      # foo#
      -
      <h1>foo#</h1>
      +
      <h1>foo#</h1>
      @@ -1158,13 +1158,13 @@ of the closing sequence:

      -
      ### foo \###
      +
      ### foo \###
       ## foo #\##
       # foo \#
      -
      <h3>foo ###</h3>
      +
      <h3>foo ###</h3>
       <h2>foo ###</h2>
       <h1>foo #</h1>
      @@ -1175,13 +1175,13 @@ lines, and they can interrupt paragraphs:

      -
      ****
      +
      ****
       ## foo
       ****
      -
      <hr />
      +
      <hr />
       <h2>foo</h2>
       <hr />
      @@ -1190,13 +1190,13 @@ lines, and they can interrupt paragraphs:

      -
      Foo bar
      +
      Foo bar
       # baz
       Bar foo
      -
      <p>Foo bar</p>
      +
      <p>Foo bar</p>
       <h1>baz</h1>
       <p>Bar foo</p>
      @@ -1206,13 +1206,13 @@ lines, and they can interrupt paragraphs:

      -
      ## 
      +
      ## 
       #
       ### ###
      -
      <h2></h2>
      +
      <h2></h2>
       <h1></h1>
       <h3></h3>
      @@ -1248,7 +1248,7 @@ them.

      -
      Foo *bar*
      +
      Foo *bar*
       =========
       
       Foo *bar*
      @@ -1256,7 +1256,7 @@ them.

      -
      <h1>Foo <em>bar</em></h1>
      +
      <h1>Foo <em>bar</em></h1>
       <h2>Foo <em>bar</em></h2>
      @@ -1265,13 +1265,13 @@ them.

      -
      Foo *bar
      +
      Foo *bar
       baz*
       ====
      -
      <h1>Foo <em>bar
      +
      <h1>Foo <em>bar
       baz</em></h1>
      @@ -1283,13 +1283,13 @@ concatenating the lines and removing initial and final
      -
        Foo *bar
      +
        Foo *bar
       baz*→
       ====
      -
      <h1>Foo <em>bar
      +
      <h1>Foo <em>bar
       baz</em></h1>
      @@ -1298,7 +1298,7 @@ concatenating the lines and removing initial and final
      -
      Foo
      +
      Foo
       -------------------------
       
       Foo
      @@ -1306,7 +1306,7 @@ concatenating the lines and removing initial and final
       
       
      -
      <h2>Foo</h2>
      +
      <h2>Foo</h2>
       <h1>Foo</h1>
      @@ -1316,7 +1316,7 @@ not line up with the underlining:

      -
         Foo
      +
         Foo
       ---
       
         Foo
      @@ -1327,7 +1327,7 @@ not line up with the underlining:

      -
      <h2>Foo</h2>
      +
      <h2>Foo</h2>
       <h2>Foo</h2>
       <h1>Foo</h1>
      @@ -1337,7 +1337,7 @@ not line up with the underlining:

      -
          Foo
      +
          Foo
           ---
       
           Foo
      @@ -1345,7 +1345,7 @@ not line up with the underlining:

      -
      <pre><code>Foo
      +
      <pre><code>Foo
       ---
       
       Foo
      @@ -1359,12 +1359,12 @@ may have trailing spaces:

      -
      Foo
      +
      Foo
          ----      
      -
      <h2>Foo</h2>
      +
      <h2>Foo</h2>
      @@ -1372,12 +1372,12 @@ may have trailing spaces:

      -
      Foo
      +
      Foo
           ---
      -
      <p>Foo
      +
      <p>Foo
       ---</p>
      @@ -1386,7 +1386,7 @@ may have trailing spaces:

      -
      Foo
      +
      Foo
       = =
       
       Foo
      @@ -1394,7 +1394,7 @@ may have trailing spaces:

      -
      <p>Foo
      +
      <p>Foo
       = =</p>
       <p>Foo</p>
       <hr />
      @@ -1405,12 +1405,12 @@ may have trailing spaces:

      -
      Foo  
      +
      Foo  
       -----
      -
      <h2>Foo</h2>
      +
      <h2>Foo</h2>
      @@ -1418,12 +1418,12 @@ may have trailing spaces:

      -
      Foo\
      +
      Foo\
       ----
      -
      <h2>Foo\</h2>
      +
      <h2>Foo\</h2>
      @@ -1432,7 +1432,7 @@ indicators of inline structure, the following are setext headings:

      -
      `Foo
      +
      `Foo
       ----
       `
       
      @@ -1442,7 +1442,7 @@ indicators of inline structure, the following are setext headings:

      -
      <h2>`Foo</h2>
      +
      <h2>`Foo</h2>
       <p>`</p>
       <h2>&lt;a title=&quot;a lot</h2>
       <p>of dashes&quot;/&gt;</p>
      @@ -1454,12 +1454,12 @@ line] in a list item or block quote:

      -
      > Foo
      +
      > Foo
       ---
      -
      <blockquote>
      +
      <blockquote>
       <p>Foo</p>
       </blockquote>
       <hr />
      @@ -1469,13 +1469,13 @@ line] in a list item or block quote:

      -
      > foo
      +
      > foo
       bar
       ===
      -
      <blockquote>
      +
      <blockquote>
       <p>foo
       bar
       ===</p>
      @@ -1486,12 +1486,12 @@ line] in a list item or block quote:

      -
      - Foo
      +
      - Foo
       ---
      -
      <ul>
      +
      <ul>
       <li>Foo</li>
       </ul>
       <hr />
      @@ -1504,13 +1504,13 @@ of the heading's content:

      -
      Foo
      +
      Foo
       Bar
       ---
      -
      <h2>Foo
      +
      <h2>Foo
       Bar</h2>
      @@ -1520,7 +1520,7 @@ setext headings:

      -
      ---
      +
      ---
       Foo
       ---
       Bar
      @@ -1529,7 +1529,7 @@ setext headings:

      -
      <hr />
      +
      <hr />
       <h2>Foo</h2>
       <h2>Bar</h2>
       <p>Baz</p>
      @@ -1540,12 +1540,12 @@ setext headings:

      -
      
      +
      
       ====
      -
      <p>====</p>
      +
      <p>====</p>
      @@ -1555,12 +1555,12 @@ in these examples gets interpreted as a thematic break:

      -
      ---
      +
      ---
       ---
      -
      <hr />
      +
      <hr />
       <hr />
      @@ -1568,12 +1568,12 @@ in these examples gets interpreted as a thematic break:

      -
      - foo
      +
      - foo
       -----
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       </ul>
       <hr />
      @@ -1583,12 +1583,12 @@ in these examples gets interpreted as a thematic break:

      -
          foo
      +
          foo
       ---
      -
      <pre><code>foo
      +
      <pre><code>foo
       </code></pre>
       <hr />
      @@ -1597,12 +1597,12 @@ in these examples gets interpreted as a thematic break:

      -
      > foo
      +
      > foo
       -----
      -
      <blockquote>
      +
      <blockquote>
       <p>foo</p>
       </blockquote>
       <hr />
      @@ -1614,12 +1614,12 @@ use backslash escapes:

      -
      \> foo
      +
      \> foo
       ------
      -
      <h2>&gt; foo</h2>
      +
      <h2>&gt; foo</h2>
      @@ -1627,7 +1627,7 @@ use backslash escapes:

      do not allow the text of setext headings to span multiple lines. But there is no consensus about how to interpret

      -
      Foo
      +
      Foo
       bar
       ---
       baz
      @@ -1647,7 +1647,7 @@ put a blank line after the first paragraph:

      -
      Foo
      +
      Foo
       
       bar
       ---
      @@ -1655,7 +1655,7 @@ put a blank line after the first paragraph:

      -
      <p>Foo</p>
      +
      <p>Foo</p>
       <h2>bar</h2>
       <p>baz</p>
      @@ -1666,7 +1666,7 @@ the thematic break,

      -
      Foo
      +
      Foo
       bar
       
       ---
      @@ -1675,7 +1675,7 @@ the thematic break,

      -
      <p>Foo
      +
      <p>Foo
       bar</p>
       <hr />
       <p>baz</p>
      @@ -1687,14 +1687,14 @@ underline], such as

      -
      Foo
      +
      Foo
       bar
       * * *
       baz
      -
      <p>Foo
      +
      <p>Foo
       bar</p>
       <hr />
       <p>baz</p>
      @@ -1705,14 +1705,14 @@ underline], such as

      -
      Foo
      +
      Foo
       bar
       \---
       baz
      -
      <p>Foo
      +
      <p>Foo
       bar
       ---
       baz</p>
      @@ -1735,12 +1735,12 @@ paragraph.)

      -
          a simple
      +
          a simple
             indented code block
      -
      <pre><code>a simple
      +
      <pre><code>a simple
         indented code block
       </code></pre>
      @@ -1752,13 +1752,13 @@ item][list items], the list item interpretation takes precedence:

      -
        - foo
      +
        - foo
       
           bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>bar</p>
      @@ -1770,13 +1770,13 @@ item][list items], the list item interpretation takes precedence:

      -
      1.  foo
      +
      1.  foo
       
           - bar
      -
      <ol>
      +
      <ol>
       <li>
       <p>foo</p>
       <ul>
      @@ -1792,14 +1792,14 @@ as Markdown:

      -
          <a/>
      +
          <a/>
           *hi*
       
           - one
      -
      <pre><code>&lt;a/&gt;
      +
      <pre><code>&lt;a/&gt;
       *hi*
       
       - one
      @@ -1811,7 +1811,7 @@ as Markdown:

      -
          chunk1
      +
          chunk1
       
           chunk2
         
      @@ -1821,7 +1821,7 @@ as Markdown:

      -
      <pre><code>chunk1
      +
      <pre><code>chunk1
       
       chunk2
       
      @@ -1837,13 +1837,13 @@ in interior blank lines:

      -
          chunk1
      +
          chunk1
             
             chunk2
      -
      <pre><code>chunk1
      +
      <pre><code>chunk1
         
         chunk2
       </code></pre>
      @@ -1855,13 +1855,13 @@ allows hanging indents and the like.)

      -
      Foo
      +
      Foo
           bar
       
      -
      <p>Foo
      +
      <p>Foo
       bar</p>
      @@ -1872,12 +1872,12 @@ after indented code:

      -
          foo
      +
          foo
       bar
      -
      <pre><code>foo
      +
      <pre><code>foo
       </code></pre>
       <p>bar</p>
      @@ -1888,7 +1888,7 @@ blocks:

      -
      # Heading
      +
      # Heading
           foo
       Heading
       ------
      @@ -1897,7 +1897,7 @@ blocks:

      -
      <h1>Heading</h1>
      +
      <h1>Heading</h1>
       <pre><code>foo
       </code></pre>
       <h2>Heading</h2>
      @@ -1911,12 +1911,12 @@ blocks:

      -
              foo
      +
              foo
           bar
      -
      <pre><code>    foo
      +
      <pre><code>    foo
       bar
       </code></pre>
      @@ -1927,7 +1927,7 @@ are not included in it:

      -
      
      +
      
           
           foo
           
      @@ -1935,7 +1935,7 @@ are not included in it:

      -
      <pre><code>foo
      +
      <pre><code>foo
       </code></pre>
      @@ -1944,11 +1944,11 @@ are not included in it:

      -
          foo  
      +
          foo  
      -
      <pre><code>foo  
      +
      <pre><code>foo  
       </code></pre>
      @@ -1995,14 +1995,14 @@ particular treatment of the [info string].

      -
      ```
      +
      ```
       <
        >
       ```
      -
      <pre><code>&lt;
      +
      <pre><code>&lt;
        &gt;
       </code></pre>
      @@ -2012,14 +2012,14 @@ particular treatment of the [info string].

      -
      ~~~
      +
      ~~~
       <
        >
       ~~~
      -
      <pre><code>&lt;
      +
      <pre><code>&lt;
        &gt;
       </code></pre>
      @@ -2029,13 +2029,13 @@ particular treatment of the [info string].

      -
      ``
      +
      ``
       foo
       ``
      -
      <p><code>foo</code></p>
      +
      <p><code>foo</code></p>
      @@ -2044,14 +2044,14 @@ fence:

      -
      ```
      +
      ```
       aaa
       ~~~
       ```
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       ~~~
       </code></pre>
      @@ -2060,14 +2060,14 @@ fence:

      -
      ~~~
      +
      ~~~
       aaa
       ```
       ~~~
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       ```
       </code></pre>
      @@ -2077,14 +2077,14 @@ fence:

      -
      ````
      +
      ````
       aaa
       ```
       ``````
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       ```
       </code></pre>
      @@ -2093,14 +2093,14 @@ fence:

      -
      ~~~~
      +
      ~~~~
       aaa
       ~~~
       ~~~~
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       ~~~
       </code></pre>
      @@ -2111,25 +2111,25 @@ fence:

      -
      ```
      +
      ```
      -
      <pre><code></code></pre>
      +
      <pre><code></code></pre>
      -
      `````
      +
      `````
       
       ```
       aaa
      -
      <pre><code>
      +
      <pre><code>
       ```
       aaa
       </code></pre>
      @@ -2139,14 +2139,14 @@ fence:

      -
      > ```
      +
      > ```
       > aaa
       
       bbb
      -
      <blockquote>
      +
      <blockquote>
       <pre><code>aaa
       </code></pre>
       </blockquote>
      @@ -2158,14 +2158,14 @@ fence:

      -
      ```
      +
      ```
       
         
       ```
      -
      <pre><code>
      +
      <pre><code>
         
       </code></pre>
      @@ -2175,12 +2175,12 @@ fence:

      -
      ```
      +
      ```
       ```
      -
      <pre><code></code></pre>
      +
      <pre><code></code></pre>
      @@ -2190,14 +2190,14 @@ if present:

      -
       ```
      +
       ```
        aaa
       aaa
       ```
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       aaa
       </code></pre>
      @@ -2206,7 +2206,7 @@ if present:

      -
        ```
      +
        ```
       aaa
         aaa
       aaa
      @@ -2214,7 +2214,7 @@ if present:

      -
      <pre><code>aaa
      +
      <pre><code>aaa
       aaa
       aaa
       </code></pre>
      @@ -2224,7 +2224,7 @@ if present:

      -
         ```
      +
         ```
          aaa
           aaa
         aaa
      @@ -2232,7 +2232,7 @@ if present:

      -
      <pre><code>aaa
      +
      <pre><code>aaa
        aaa
       aaa
       </code></pre>
      @@ -2243,13 +2243,13 @@ if present:

      -
          ```
      +
          ```
           aaa
           ```
      -
      <pre><code>```
      +
      <pre><code>```
       aaa
       ```
       </code></pre>
      @@ -2261,13 +2261,13 @@ need not match that of the opening fence:

      -
      ```
      +
      ```
       aaa
         ```
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       </code></pre>
      @@ -2275,13 +2275,13 @@ need not match that of the opening fence:

      -
         ```
      +
         ```
       aaa
         ```
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       </code></pre>
      @@ -2290,13 +2290,13 @@ need not match that of the opening fence:

      -
      ```
      +
      ```
       aaa
           ```
      -
      <pre><code>aaa
      +
      <pre><code>aaa
           ```
       </code></pre>
      @@ -2306,12 +2306,12 @@ need not match that of the opening fence:

      -
      ``` ```
      +
      ``` ```
       aaa
      -
      <p><code> </code>
      +
      <p><code> </code>
       aaa</p>
      @@ -2319,13 +2319,13 @@ need not match that of the opening fence:

      -
      ~~~~~~
      +
      ~~~~~~
       aaa
       ~~~ ~~
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       ~~~ ~~
       </code></pre>
      @@ -2336,7 +2336,7 @@ directly by paragraphs, without a blank line between:

      -
      foo
      +
      foo
       ```
       bar
       ```
      @@ -2344,7 +2344,7 @@ directly by paragraphs, without a blank line between:

      -
      <p>foo</p>
      +
      <p>foo</p>
       <pre><code>bar
       </code></pre>
       <p>baz</p>
      @@ -2356,7 +2356,7 @@ without an intervening blank line:

      -
      foo
      +
      foo
       ---
       ~~~
       bar
      @@ -2365,7 +2365,7 @@ without an intervening blank line:

      -
      <h2>foo</h2>
      +
      <h2>foo</h2>
       <pre><code>bar
       </code></pre>
       <h1>baz</h1>
      @@ -2381,7 +2381,7 @@ of language- followed by the langua
      -
      ```ruby
      +
      ```ruby
       def foo(x)
         return 3
       end
      @@ -2389,7 +2389,7 @@ of language- followed by the langua
       
       
      -
      <pre><code class="language-ruby">def foo(x)
      +
      <pre><code class="language-ruby">def foo(x)
         return 3
       end
       </code></pre>
      @@ -2399,7 +2399,7 @@ of language- followed by the langua
      -
      ~~~~    ruby startline=3 $%@#$
      +
      ~~~~    ruby startline=3 $%@#$
       def foo(x)
         return 3
       end
      @@ -2407,7 +2407,7 @@ of language- followed by the langua
       
       
      -
      <pre><code class="language-ruby">def foo(x)
      +
      <pre><code class="language-ruby">def foo(x)
         return 3
       end
       </code></pre>
      @@ -2417,12 +2417,12 @@ of language- followed by the langua
      -
      ````;
      +
      ````;
       ````
      -
      <pre><code class="language-;"></code></pre>
      +
      <pre><code class="language-;"></code></pre>
      @@ -2430,12 +2430,12 @@ of language- followed by the langua
      -
      ``` aa ```
      +
      ``` aa ```
       foo
      -
      <p><code>aa</code>
      +
      <p><code>aa</code>
       foo</p>
      @@ -2444,13 +2444,13 @@ of language- followed by the langua
      -
      ~~~ aa ``` ~~~
      +
      ~~~ aa ``` ~~~
       foo
       ~~~
      -
      <pre><code class="language-aa">foo
      +
      <pre><code class="language-aa">foo
       </code></pre>
      @@ -2459,13 +2459,13 @@ of language- followed by the langua
      -
      ```
      +
      ```
       ``` aaa
       ```
      -
      <pre><code>``` aaa
      +
      <pre><code>``` aaa
       </code></pre>
      @@ -2546,7 +2546,7 @@ will end at any blank line. This can be surprising:

      -
      <table><tr><td>
      +
      <table><tr><td>
       <pre>
       **Hello**,
       
      @@ -2556,7 +2556,7 @@ will end at any blank line. This can be surprising:

      -
      <table><tr><td>
      +
      <table><tr><td>
       <pre>
       **Hello**,
       <p><em>world</em>.
      @@ -2577,7 +2577,7 @@ of type 6:

      -
      <table>
      +
      <table>
         <tr>
           <td>
                  hi
      @@ -2589,7 +2589,7 @@ of type 6:

      -
      <table>
      +
      <table>
         <tr>
           <td>
                  hi
      @@ -2603,13 +2603,13 @@ of type 6:

      -
       <div>
      +
       <div>
         *hello*
                <foo><a>
      -
       <div>
      +
       <div>
         *hello*
                <foo><a>
      @@ -2619,12 +2619,12 @@ of type 6:

      -
      </div>
      +
      </div>
       *foo*
      -
      </div>
      +
      </div>
       *foo*
      @@ -2633,7 +2633,7 @@ of type 6:

      -
      <DIV CLASS="foo">
      +
      <DIV CLASS="foo">
       
       *Markdown*
       
      @@ -2641,7 +2641,7 @@ of type 6:

      -
      <DIV CLASS="foo">
      +
      <DIV CLASS="foo">
       <p><em>Markdown</em></p>
       </DIV>
      @@ -2652,13 +2652,13 @@ as it is split where there would be whitespace:

      -
      <div id="foo"
      +
      <div id="foo"
         class="bar">
       </div>
      -
      <div id="foo"
      +
      <div id="foo"
         class="bar">
       </div>
      @@ -2667,13 +2667,13 @@ as it is split where there would be whitespace:

      -
      <div id="foo" class="bar
      +
      <div id="foo" class="bar
         baz">
       </div>
      -
      <div id="foo" class="bar
      +
      <div id="foo" class="bar
         baz">
       </div>
      @@ -2683,14 +2683,14 @@ as it is split where there would be whitespace:

      -
      <div>
      +
      <div>
       *foo*
       
       *bar*
      -
      <div>
      +
      <div>
       *foo*
       <p><em>bar</em></p>
      @@ -2701,12 +2701,12 @@ in, garbage out):

      -
      <div id="foo"
      +
      <div id="foo"
       *hi*
      -
      <div id="foo"
      +
      <div id="foo"
       *hi*
      @@ -2714,12 +2714,12 @@ in, garbage out):

      -
      <div class
      +
      <div class
       foo
      -
      <div class
      +
      <div class
       foo
      @@ -2729,12 +2729,12 @@ tag, as long as it starts like one:

      -
      <div *???-&&&-<---
      +
      <div *???-&&&-<---
       *foo*
      -
      <div *???-&&&-<---
      +
      <div *???-&&&-<---
       *foo*
      @@ -2744,24 +2744,24 @@ itself:

      -
      <div><a href="bar">*foo*</a></div>
      +
      <div><a href="bar">*foo*</a></div>
      -
      <div><a href="bar">*foo*</a></div>
      +
      <div><a href="bar">*foo*</a></div>
      -
      <table><tr><td>
      +
      <table><tr><td>
       foo
       </td></tr></table>
      -
      <table><tr><td>
      +
      <table><tr><td>
       foo
       </td></tr></table>
      @@ -2775,14 +2775,14 @@ line or the end of the document is reached:

      -
      <div></div>
      +
      <div></div>
       ``` c
       int x = 33;
       ```
      -
      <div></div>
      +
      <div></div>
       ``` c
       int x = 33;
       ```
      @@ -2795,13 +2795,13 @@ itself on the first line (and it must be complete):

      -
      <a href="foo">
      +
      <a href="foo">
       *bar*
       </a>
      -
      <a href="foo">
      +
      <a href="foo">
       *bar*
       </a>
      @@ -2811,13 +2811,13 @@ itself on the first line (and it must be complete):

      -
      <Warning>
      +
      <Warning>
       *bar*
       </Warning>
      -
      <Warning>
      +
      <Warning>
       *bar*
       </Warning>
      @@ -2826,13 +2826,13 @@ itself on the first line (and it must be complete):

      -
      <i class="foo">
      +
      <i class="foo">
       *bar*
       </i>
      -
      <i class="foo">
      +
      <i class="foo">
       *bar*
       </i>
      @@ -2841,12 +2841,12 @@ itself on the first line (and it must be complete):

      -
      </ins>
      +
      </ins>
       *bar*
      -
      </ins>
      +
      </ins>
       *bar*
      @@ -2859,13 +2859,13 @@ HTML block, because the <del>
      -
      <del>
      +
      <del>
       *foo*
       </del>
      -
      <del>
      +
      <del>
       *foo*
       </del>
      @@ -2877,7 +2877,7 @@ line). So the contents get interpreted as CommonMark:

      -
      <del>
      +
      <del>
       
       *foo*
       
      @@ -2885,7 +2885,7 @@ line).  So the contents get interpreted as CommonMark:

      -
      <del>
      +
      <del>
       <p><em>foo</em></p>
       </del>
      @@ -2898,11 +2898,11 @@ rather than an [HTML block].)

      -
      <del>*foo*</del>
      +
      <del>*foo*</del>
      -
      <p><del><em>foo</em></del></p>
      +
      <p><del><em>foo</em></del></p>
      @@ -2916,7 +2916,7 @@ As a result, these blocks can contain blank lines:

      -
      <pre language="haskell"><code>
      +
      <pre language="haskell"><code>
       import Text.HTML.TagSoup
       
       main :: IO ()
      @@ -2926,7 +2926,7 @@ As a result, these blocks can contain blank lines:

      -
      <pre language="haskell"><code>
      +
      <pre language="haskell"><code>
       import Text.HTML.TagSoup
       
       main :: IO ()
      @@ -2940,7 +2940,7 @@ As a result, these blocks can contain blank lines:

      -
      <script type="text/javascript">
      +
      <script type="text/javascript">
       // JavaScript example
       
       document.getElementById("demo").innerHTML = "Hello JavaScript!";
      @@ -2949,7 +2949,7 @@ As a result, these blocks can contain blank lines:

      -
      <script type="text/javascript">
      +
      <script type="text/javascript">
       // JavaScript example
       
       document.getElementById("demo").innerHTML = "Hello JavaScript!";
      @@ -2962,7 +2962,7 @@ As a result, these blocks can contain blank lines:

      -
      <style
      +
      <style
         type="text/css">
       h1 {color:red;}
       
      @@ -2972,7 +2972,7 @@ As a result, these blocks can contain blank lines:

      -
      <style
      +
      <style
         type="text/css">
       h1 {color:red;}
       
      @@ -2988,14 +2988,14 @@ or [list item][list items]):

      -
      <style
      +
      <style
         type="text/css">
       
       foo
      -
      <style
      +
      <style
         type="text/css">
       
       foo
      @@ -3005,14 +3005,14 @@ or [list item][list items]):

      -
      > <div>
      +
      > <div>
       > foo
       
       bar
      -
      <blockquote>
      +
      <blockquote>
       <div>
       foo
       </blockquote>
      @@ -3023,12 +3023,12 @@ or [list item][list items]):

      -
      - <div>
      +
      - <div>
       - foo
      -
      <ul>
      +
      <ul>
       <li>
       <div>
       </li>
      @@ -3041,12 +3041,12 @@ or [list item][list items]):

      -
      <style>p{color:red;}</style>
      +
      <style>p{color:red;}</style>
       *foo*
      -
      <style>p{color:red;}</style>
      +
      <style>p{color:red;}</style>
       <p><em>foo</em></p>
      @@ -3054,12 +3054,12 @@ or [list item][list items]):

      -
      <!-- foo -->*bar*
      +
      <!-- foo -->*bar*
       *baz*
      -
      <!-- foo -->*bar*
      +
      <!-- foo -->*bar*
       <p><em>baz</em></p>
      @@ -3069,13 +3069,13 @@ end tag will be included in the [HTML block]:

      -
      <script>
      +
      <script>
       foo
       </script>1. *bar*
      -
      <script>
      +
      <script>
       foo
       </script>1. *bar*
      @@ -3085,7 +3085,7 @@ end tag will be included in the [HTML block]:

      -
      <!-- Foo
      +
      <!-- Foo
       
       bar
          baz -->
      @@ -3093,7 +3093,7 @@ end tag will be included in the [HTML block]:

      -
      <!-- Foo
      +
      <!-- Foo
       
       bar
          baz -->
      @@ -3105,7 +3105,7 @@ end tag will be included in the [HTML block]:

      -
      <?php
      +
      <?php
       
         echo '>';
       
      @@ -3114,7 +3114,7 @@ end tag will be included in the [HTML block]:

      -
      <?php
      +
      <?php
       
         echo '>';
       
      @@ -3127,11 +3127,11 @@ end tag will be included in the [HTML block]:

      -
      <!DOCTYPE html>
      +
      <!DOCTYPE html>
      -
      <!DOCTYPE html>
      +
      <!DOCTYPE html>
      @@ -3139,7 +3139,7 @@ end tag will be included in the [HTML block]:

      -
      <![CDATA[
      +
      <![CDATA[
       function matchwo(a,b)
       {
         if (a < b && a < 0) then {
      @@ -3155,7 +3155,7 @@ end tag will be included in the [HTML block]:

      -
      <![CDATA[
      +
      <![CDATA[
       function matchwo(a,b)
       {
         if (a < b && a < 0) then {
      @@ -3175,13 +3175,13 @@ end tag will be included in the [HTML block]:

      -
        <!-- foo -->
      +
        <!-- foo -->
       
           <!-- foo -->
      -
        <!-- foo -->
      +
        <!-- foo -->
       <pre><code>&lt;!-- foo --&gt;
       </code></pre>
      @@ -3190,13 +3190,13 @@ end tag will be included in the [HTML block]:

      -
        <div>
      +
        <div>
       
           <div>
      -
        <div>
      +
        <div>
       <pre><code>&lt;div&gt;
       </code></pre>
      @@ -3207,14 +3207,14 @@ preceded by a blank line.

      -
      Foo
      +
      Foo
       <div>
       bar
       </div>
      -
      <p>Foo</p>
      +
      <p>Foo</p>
       <div>
       bar
       </div>
      @@ -3227,14 +3227,14 @@ block]:

      -
      <div>
      +
      <div>
       bar
       </div>
       *foo*
      -
      <div>
      +
      <div>
       bar
       </div>
       *foo*
      @@ -3245,13 +3245,13 @@ block]:

      -
      Foo
      +
      Foo
       <a href="bar">
       baz
      -
      <p>Foo
      +
      <p>Foo
       <a href="bar">
       baz</p>
      @@ -3287,7 +3287,7 @@ simply separate the Markdown from the HTML using blank lines:

      -
      <div>
      +
      <div>
       
       *Emphasized* text.
       
      @@ -3295,7 +3295,7 @@ simply separate the Markdown from the HTML using blank lines:

      -
      <div>
      +
      <div>
       <p><em>Emphasized</em> text.</p>
       </div>
      @@ -3304,13 +3304,13 @@ simply separate the Markdown from the HTML using blank lines:

      -
      <div>
      +
      <div>
       *Emphasized* text.
       </div>
      -
      <div>
      +
      <div>
       *Emphasized* text.
       </div>
      @@ -3328,7 +3328,7 @@ HTML are usually followed by HTML block tags. For example:

      -
      <table>
      +
      <table>
       
       <tr>
       
      @@ -3342,7 +3342,7 @@ HTML are usually followed by HTML block tags.  For example:

      -
      <table>
      +
      <table>
       <tr>
       <td>
       Hi
      @@ -3358,7 +3358,7 @@ an indented code block:

      -
      <table>
      +
      <table>
       
         <tr>
       
      @@ -3372,7 +3372,7 @@ an indented code block:

      -
      <table>
      +
      <table>
         <tr>
       <pre><code>&lt;td&gt;
         Hi
      @@ -3407,20 +3407,20 @@ them.

      -
      [foo]: /url "title"
      +
      [foo]: /url "title"
       
       [foo]
      -
      <p><a href="/url" title="title">foo</a></p>
      +
      <p><a href="/url" title="title">foo</a></p>
      -
         [foo]: 
      +
         [foo]: 
             /url  
                  'the title'  
       
      @@ -3428,27 +3428,27 @@ them.

      -
      <p><a href="/url" title="the title">foo</a></p>
      +
      <p><a href="/url" title="the title">foo</a></p>
      -
      [Foo*bar\]]:my_(url) 'title (with parens)'
      +
      [Foo*bar\]]:my_(url) 'title (with parens)'
       
       [Foo*bar\]]
      -
      <p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
      +
      <p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
      -
      [Foo bar]:
      +
      [Foo bar]:
       <my url>
       'title'
       
      @@ -3456,7 +3456,7 @@ them.

      -
      <p><a href="my%20url" title="title">Foo bar</a></p>
      +
      <p><a href="my%20url" title="title">Foo bar</a></p>
      @@ -3464,7 +3464,7 @@ them.

      -
      [foo]: /url '
      +
      [foo]: /url '
       title
       line1
       line2
      @@ -3474,7 +3474,7 @@ them.

      -
      <p><a href="/url" title="
      +
      <p><a href="/url" title="
       title
       line1
       line2
      @@ -3486,7 +3486,7 @@ them.

      -
      [foo]: /url 'title
      +
      [foo]: /url 'title
       
       with blank line'
       
      @@ -3494,7 +3494,7 @@ them.

      -
      <p>[foo]: /url 'title</p>
      +
      <p>[foo]: /url 'title</p>
       <p>with blank line'</p>
       <p>[foo]</p>
      @@ -3504,14 +3504,14 @@ them.

      -
      [foo]:
      +
      [foo]:
       /url
       
       [foo]
      -
      <p><a href="/url">foo</a></p>
      +
      <p><a href="/url">foo</a></p>
      @@ -3519,13 +3519,13 @@ them.

      -
      [foo]:
      +
      [foo]:
       
       [foo]
      -
      <p>[foo]:</p>
      +
      <p>[foo]:</p>
       <p>[foo]</p>
      @@ -3535,13 +3535,13 @@ angle brackets:

      -
      [foo]: <>
      +
      [foo]: <>
       
       [foo]
      -
      <p><a href="">foo</a></p>
      +
      <p><a href="">foo</a></p>
      @@ -3550,13 +3550,13 @@ whitespace:

      -
      [foo]: <bar>(baz)
      +
      [foo]: <bar>(baz)
       
       [foo]
      -
      <p>[foo]: <bar>(baz)</p>
      +
      <p>[foo]: <bar>(baz)</p>
       <p>[foo]</p>
      @@ -3566,13 +3566,13 @@ and literal backslashes:

      -
      [foo]: /url\bar\*baz "foo\"bar\baz"
      +
      [foo]: /url\bar\*baz "foo\"bar\baz"
       
       [foo]
      -
      <p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
      +
      <p><a href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
      @@ -3580,13 +3580,13 @@ and literal backslashes:

      -
      [foo]
      +
      [foo]
       
       [foo]: url
      -
      <p><a href="url">foo</a></p>
      +
      <p><a href="url">foo</a></p>
      @@ -3595,14 +3595,14 @@ precedence:

      -
      [foo]
      +
      [foo]
       
       [foo]: first
       [foo]: second
      -
      <p><a href="first">foo</a></p>
      +
      <p><a href="first">foo</a></p>
      @@ -3611,26 +3611,26 @@ case-insensitive (see [matches]).

      -
      [FOO]: /url
      +
      [FOO]: /url
       
       [Foo]
      -
      <p><a href="/url">Foo</a></p>
      +
      <p><a href="/url">Foo</a></p>
      -
      [ΑΓΩ]: /φου
      +
      [ΑΓΩ]: /φου
       
       [αγω]
      -
      <p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
      +
      <p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
      @@ -3639,11 +3639,11 @@ It contributes nothing to the document.

      -
      [foo]: /url
      +
      [foo]: /url
      -
      +
      @@ -3651,14 +3651,14 @@ It contributes nothing to the document.

      -
      [
      +
      [
       foo
       ]: /url
       bar
      -
      <p>bar</p>
      +
      <p>bar</p>
      @@ -3667,11 +3667,11 @@ It contributes nothing to the document.

      -
      [foo]: /url "title" ok
      +
      [foo]: /url "title" ok
      -
      <p>[foo]: /url &quot;title&quot; ok</p>
      +
      <p>[foo]: /url &quot;title&quot; ok</p>
      @@ -3679,12 +3679,12 @@ It contributes nothing to the document.

      -
      [foo]: /url
      +
      [foo]: /url
       "title" ok
      -
      <p>&quot;title&quot; ok</p>
      +
      <p>&quot;title&quot; ok</p>
      @@ -3693,13 +3693,13 @@ four spaces:

      -
          [foo]: /url "title"
      +
          [foo]: /url "title"
       
       [foo]
      -
      <pre><code>[foo]: /url &quot;title&quot;
      +
      <pre><code>[foo]: /url &quot;title&quot;
       </code></pre>
       <p>[foo]</p>
      @@ -3710,7 +3710,7 @@ a code block:

      -
      ```
      +
      ```
       [foo]: /url
       ```
       
      @@ -3718,7 +3718,7 @@ a code block:

      -
      <pre><code>[foo]: /url
      +
      <pre><code>[foo]: /url
       </code></pre>
       <p>[foo]</p>
      @@ -3728,14 +3728,14 @@ a code block:

      -
      Foo
      +
      Foo
       [bar]: /baz
       
       [bar]
      -
      <p>Foo
      +
      <p>Foo
       [bar]: /baz</p>
       <p>[bar]</p>
      @@ -3746,13 +3746,13 @@ and thematic breaks, and it need not be followed by a blank line.

      -
      # [Foo]
      +
      # [Foo]
       [foo]: /url
       > bar
      -
      <h1><a href="/url">Foo</a></h1>
      +
      <h1><a href="/url">Foo</a></h1>
       <blockquote>
       <p>bar</p>
       </blockquote>
      @@ -3762,14 +3762,14 @@ and thematic breaks, and it need not be followed by a blank line.

      -
      [foo]: /url
      +
      [foo]: /url
       bar
       ===
       [foo]
      -
      <h1>bar</h1>
      +
      <h1>bar</h1>
       <p><a href="/url">foo</a></p>
      @@ -3777,13 +3777,13 @@ and thematic breaks, and it need not be followed by a blank line.

      -
      [foo]: /url
      +
      [foo]: /url
       ===
       [foo]
      -
      <p>===
      +
      <p>===
       <a href="/url">foo</a></p>
      @@ -3793,7 +3793,7 @@ can occur one after another, without intervening blank lines.

      -
      [foo]: /foo-url "foo"
      +
      [foo]: /foo-url "foo"
       [bar]: /bar-url
         "bar"
       [baz]: /baz-url
      @@ -3804,7 +3804,7 @@ can occur one after another, without intervening blank lines.

      -
      <p><a href="/foo-url" title="foo">foo</a>,
      +
      <p><a href="/foo-url" title="foo">foo</a>,
       <a href="/bar-url" title="bar">bar</a>,
       <a href="/baz-url">baz</a></p>
      @@ -3817,13 +3817,13 @@ are defined:

      -
      [foo]
      +
      [foo]
       
       > [foo]: /url
      -
      <p><a href="/url">foo</a></p>
      +
      <p><a href="/url">foo</a></p>
       <blockquote>
       </blockquote>
      @@ -3837,11 +3837,11 @@ no visible content:

      -
      [foo]: /url
      +
      [foo]: /url
      -
      +
      @@ -3857,13 +3857,13 @@ is formed by concatenating the lines and removing initial and final
      -
      aaa
      +
      aaa
       
       bbb
      -
      <p>aaa</p>
      +
      <p>aaa</p>
       <p>bbb</p>
      @@ -3872,7 +3872,7 @@ is formed by concatenating the lines and removing initial and final
      -
      aaa
      +
      aaa
       bbb
       
       ccc
      @@ -3880,7 +3880,7 @@ is formed by concatenating the lines and removing initial and final
       
       
      -
      <p>aaa
      +
      <p>aaa
       bbb</p>
       <p>ccc
       ddd</p>
      @@ -3891,14 +3891,14 @@ is formed by concatenating the lines and removing initial and final
      -
      aaa
      +
      aaa
       
       
       bbb
      -
      <p>aaa</p>
      +
      <p>aaa</p>
       <p>bbb</p>
      @@ -3907,12 +3907,12 @@ is formed by concatenating the lines and removing initial and final
      -
        aaa
      +
        aaa
        bbb
      -
      <p>aaa
      +
      <p>aaa
       bbb</p>
      @@ -3922,13 +3922,13 @@ code blocks cannot interrupt paragraphs.

      -
      aaa
      +
      aaa
                    bbb
                                              ccc
      -
      <p>aaa
      +
      <p>aaa
       bbb
       ccc</p>
      @@ -3939,12 +3939,12 @@ or an indented code block will be triggered:

      -
         aaa
      +
         aaa
       bbb
      -
      <p>aaa
      +
      <p>aaa
       bbb</p>
      @@ -3952,12 +3952,12 @@ or an indented code block will be triggered:

      -
          aaa
      +
          aaa
       bbb
      -
      <pre><code>aaa
      +
      <pre><code>aaa
       </code></pre>
       <p>bbb</p>
      @@ -3969,12 +3969,12 @@ break]:

      -
      aaa     
      +
      aaa     
       bbb     
      -
      <p>aaa<br />
      +
      <p>aaa<br />
       bbb</p>
      @@ -3988,7 +3988,7 @@ is [tight] or [loose].

      -
        
      +
        
       
       aaa
         
      @@ -3999,7 +3999,7 @@ is [tight] or [loose].

      -
      <p>aaa</p>
      +
      <p>aaa</p>
       <h1>aaa</h1>
      @@ -4023,13 +4023,13 @@ right, or center alignment respectively.

      -
      | foo | bar |
      +
      | foo | bar |
       | --- | --- |
       | baz | bim |
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>foo</th>
      @@ -4051,13 +4051,13 @@ they are. Likewise, use of leading and trailing pipes may be inconsistent:

      -
      | abc | defghi |
      +
      | abc | defghi |
       :-: | -----------:
       bar | baz
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th align="center">abc</th>
      @@ -4079,14 +4079,14 @@ inline spans:

      -
      | f\|oo  |
      +
      | f\|oo  |
       | ------ |
       | b `\|` az |
       | b **\|** im |
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>f|oo</th>
      @@ -4109,14 +4109,14 @@ block-level structure:

      -
      | abc | def |
      +
      | abc | def |
       | --- | --- |
       | bar | baz |
       > bar
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>abc</th>
      @@ -4139,7 +4139,7 @@ block-level structure:

      -
      | abc | def |
      +
      | abc | def |
       | --- | --- |
       | bar | baz |
       bar
      @@ -4148,7 +4148,7 @@ block-level structure:

      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>abc</th>
      @@ -4175,13 +4175,13 @@ a table will not be recognized:

      -
      | abc | def |
      +
      | abc | def |
       | --- |
       | bar |
      -
      <p>| abc | def |
      +
      <p>| abc | def |
       | --- |
       | bar |</p>
      @@ -4193,14 +4193,14 @@ cells are inserted. If there are greater, the excess is ignored:

      -
      | abc | def |
      +
      | abc | def |
       | --- | --- |
       | bar |
       | bar | baz | boo |
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>abc</th>
      @@ -4225,12 +4225,12 @@ cells are inserted.  If there are greater, the excess is ignored:

      -
      | abc | def |
      +
      | abc | def |
       | --- | --- |
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>abc</th>
      @@ -4294,13 +4294,13 @@ quotes] in a row unless there is a [blank line] between them.

      -
      > # Foo
      +
      > # Foo
       > bar
       > baz
      -
      <blockquote>
      +
      <blockquote>
       <h1>Foo</h1>
       <p>bar
       baz</p>
      @@ -4312,13 +4312,13 @@ quotes] in a row unless there is a [blank line] between them.

      -
      ># Foo
      +
      ># Foo
       >bar
       > baz
      -
      <blockquote>
      +
      <blockquote>
       <h1>Foo</h1>
       <p>bar
       baz</p>
      @@ -4330,13 +4330,13 @@ quotes] in a row unless there is a [blank line] between them.

      -
         > # Foo
      +
         > # Foo
          > bar
        > baz
      -
      <blockquote>
      +
      <blockquote>
       <h1>Foo</h1>
       <p>bar
       baz</p>
      @@ -4348,13 +4348,13 @@ quotes] in a row unless there is a [blank line] between them.

      -
          > # Foo
      +
          > # Foo
           > bar
           > baz
      -
      <pre><code>&gt; # Foo
      +
      <pre><code>&gt; # Foo
       &gt; bar
       &gt; baz
       </code></pre>
      @@ -4366,13 +4366,13 @@ quotes] in a row unless there is a [blank line] between them.

      -
      > # Foo
      +
      > # Foo
       > bar
       baz
      -
      <blockquote>
      +
      <blockquote>
       <h1>Foo</h1>
       <p>bar
       baz</p>
      @@ -4385,13 +4385,13 @@ continuation lines:

      -
      > bar
      +
      > bar
       baz
       > foo
      -
      <blockquote>
      +
      <blockquote>
       <p>bar
       baz
       foo</p>
      @@ -4403,7 +4403,7 @@ continuation lines:

      paragraphs had they been prepended with [block quote markers]. For example, the > cannot be omitted in the second line of

      -
      > foo
      +
      > foo
       > ---
      @@ -4411,12 +4411,12 @@ For example, the > cannot be o
      -
      > foo
      +
      > foo
       ---
      -
      <blockquote>
      +
      <blockquote>
       <p>foo</p>
       </blockquote>
       <hr />
      @@ -4425,7 +4425,7 @@ For example, the > cannot be o

      Similarly, if we omit the > in the second line of

      -
      > - foo
      +
      > - foo
       > - bar
      @@ -4433,12 +4433,12 @@ For example, the > cannot be o
      -
      > - foo
      +
      > - foo
       - bar
      -
      <blockquote>
      +
      <blockquote>
       <ul>
       <li>foo</li>
       </ul>
      @@ -4454,12 +4454,12 @@ subsequent lines of an indented or fenced code block:

      -
      >     foo
      +
      >     foo
           bar
      -
      <blockquote>
      +
      <blockquote>
       <pre><code>foo
       </code></pre>
       </blockquote>
      @@ -4471,13 +4471,13 @@ subsequent lines of an indented or fenced code block:

      -
      > ```
      +
      > ```
       foo
       ```
      -
      <blockquote>
      +
      <blockquote>
       <pre><code></code></pre>
       </blockquote>
       <p>foo</p>
      @@ -4490,12 +4490,12 @@ continuation line]:

      -
      > foo
      +
      > foo
           - bar
      -
      <blockquote>
      +
      <blockquote>
       <p>foo
       - bar</p>
       </blockquote>
      @@ -4504,7 +4504,7 @@ continuation line]:

      To see why, note that in

      -
      > foo
      +
      > foo
       >     - bar
      @@ -4515,11 +4515,11 @@ interrupt paragraphs, so it is [paragraph continuation text].

      -
      >
      +
      >
      -
      <blockquote>
      +
      <blockquote>
       </blockquote>
      @@ -4527,13 +4527,13 @@ interrupt paragraphs, so it is [paragraph continuation text].

      -
      >
      +
      >
       >  
       > 
      -
      <blockquote>
      +
      <blockquote>
       </blockquote>
      @@ -4542,13 +4542,13 @@ interrupt paragraphs, so it is [paragraph continuation text].

      -
      >
      +
      >
       > foo
       >  
      -
      <blockquote>
      +
      <blockquote>
       <p>foo</p>
       </blockquote>
      @@ -4558,13 +4558,13 @@ interrupt paragraphs, so it is [paragraph continuation text].

      -
      > foo
      +
      > foo
       
       > bar
      -
      <blockquote>
      +
      <blockquote>
       <p>foo</p>
       </blockquote>
       <blockquote>
      @@ -4582,12 +4582,12 @@ we get a single block quote:

      -
      > foo
      +
      > foo
       > bar
      -
      <blockquote>
      +
      <blockquote>
       <p>foo
       bar</p>
       </blockquote>
      @@ -4598,13 +4598,13 @@ we get a single block quote:

      -
      > foo
      +
      > foo
       >
       > bar
      -
      <blockquote>
      +
      <blockquote>
       <p>foo</p>
       <p>bar</p>
       </blockquote>
      @@ -4615,12 +4615,12 @@ we get a single block quote:

      -
      foo
      +
      foo
       > bar
      -
      <p>foo</p>
      +
      <p>foo</p>
       <blockquote>
       <p>bar</p>
       </blockquote>
      @@ -4632,13 +4632,13 @@ quotes:

      -
      > aaa
      +
      > aaa
       ***
       > bbb
      -
      <blockquote>
      +
      <blockquote>
       <p>aaa</p>
       </blockquote>
       <hr />
      @@ -4653,12 +4653,12 @@ a block quote and a following paragraph:

      -
      > bar
      +
      > bar
       baz
      -
      <blockquote>
      +
      <blockquote>
       <p>bar
       baz</p>
       </blockquote>
      @@ -4668,13 +4668,13 @@ a block quote and a following paragraph:

      -
      > bar
      +
      > bar
       
       baz
      -
      <blockquote>
      +
      <blockquote>
       <p>bar</p>
       </blockquote>
       <p>baz</p>
      @@ -4684,13 +4684,13 @@ a block quote and a following paragraph:

      -
      > bar
      +
      > bar
       >
       baz
      -
      <blockquote>
      +
      <blockquote>
       <p>bar</p>
       </blockquote>
       <p>baz</p>
      @@ -4703,12 +4703,12 @@ nested block quote:

      -
      > > > foo
      +
      > > > foo
       bar
      -
      <blockquote>
      +
      <blockquote>
       <blockquote>
       <blockquote>
       <p>foo
      @@ -4722,13 +4722,13 @@ nested block quote:

      -
      >>> foo
      +
      >>> foo
       > bar
       >>baz
      -
      <blockquote>
      +
      <blockquote>
       <blockquote>
       <blockquote>
       <p>foo
      @@ -4747,13 +4747,13 @@ the >:

      -
      >     code
      +
      >     code
       
       >    not code
      -
      <blockquote>
      +
      <blockquote>
       <pre><code>code
       </code></pre>
       </blockquote>
      @@ -4802,7 +4802,7 @@ that line is not a list item.
    • -
      A paragraph
      +
      A paragraph
       with two lines.
       
           indented code
      @@ -4811,7 +4811,7 @@ that line is not a list item.
       
       
      -
      <p>A paragraph
      +
      <p>A paragraph
       with two lines.</p>
       <pre><code>indented code
       </code></pre>
      @@ -4827,7 +4827,7 @@ and the same contents as Ls:

      -
      1.  A paragraph
      +
      1.  A paragraph
           with two lines.
       
               indented code
      @@ -4836,7 +4836,7 @@ and the same contents as Ls:

      -
      <ol>
      +
      <ol>
       <li>
       <p>A paragraph
       with two lines.</p>
      @@ -4862,13 +4862,13 @@ put under the list item:

      -
      - one
      +
      - one
       
        two
      -
      <ul>
      +
      <ul>
       <li>one</li>
       </ul>
       <p>two</p>
      @@ -4878,13 +4878,13 @@ put under the list item:

      -
      - one
      +
      - one
       
         two
      -
      <ul>
      +
      <ul>
       <li>
       <p>one</p>
       <p>two</p>
      @@ -4896,13 +4896,13 @@ put under the list item:

      -
       -    one
      +
       -    one
       
            two
      -
      <ul>
      +
      <ul>
       <li>one</li>
       </ul>
       <pre><code> two
      @@ -4913,13 +4913,13 @@ put under the list item:

      -
       -    one
      +
       -    one
       
             two
      -
      <ul>
      +
      <ul>
       <li>
       <p>one</p>
       <p>two</p>
      @@ -4938,13 +4938,13 @@ this example:

      -
         > > 1.  one
      +
         > > 1.  one
       >>
       >>     two
      -
      <blockquote>
      +
      <blockquote>
       <blockquote>
       <ol>
       <li>
      @@ -4967,13 +4967,13 @@ far enough past the blockquote marker:

      -
      >>- one
      +
      >>- one
       >>
         >  > two
      -
      <blockquote>
      +
      <blockquote>
       <blockquote>
       <ul>
       <li>one</li>
      @@ -4989,13 +4989,13 @@ any following content, so these are not list items:

      -
      -one
      +
      -one
       
       2.two
      -
      <p>-one</p>
      +
      <p>-one</p>
       <p>2.two</p>
      @@ -5005,14 +5005,14 @@ one blank line.

      -
      - foo
      +
      - foo
       
       
         bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>bar</p>
      @@ -5025,7 +5025,7 @@ one blank line.

      -
      1.  foo
      +
      1.  foo
       
           ```
           bar
      @@ -5037,7 +5037,7 @@ one blank line.

      -
      <ol>
      +
      <ol>
       <li>
       <p>foo</p>
       <pre><code>bar
      @@ -5056,7 +5056,7 @@ empty lines within the code block verbatim.

      -
      - Foo
      +
      - Foo
       
             bar
       
      @@ -5065,7 +5065,7 @@ empty lines within the code block verbatim.

      -
      <ul>
      +
      <ul>
       <li>
       <p>Foo</p>
       <pre><code>bar
      @@ -5082,11 +5082,11 @@ empty lines within the code block verbatim.

      -
      123456789. ok
      +
      123456789. ok
      -
      <ol start="123456789">
      +
      <ol start="123456789">
       <li>ok</li>
       </ol>
      @@ -5095,11 +5095,11 @@ empty lines within the code block verbatim.

      -
      1234567890. not ok
      +
      1234567890. not ok
      -
      <p>1234567890. not ok</p>
      +
      <p>1234567890. not ok</p>
      @@ -5107,11 +5107,11 @@ empty lines within the code block verbatim.

      -
      0. ok
      +
      0. ok
      -
      <ol start="0">
      +
      <ol start="0">
       <li>ok</li>
       </ol>
      @@ -5120,11 +5120,11 @@ empty lines within the code block verbatim.

      -
      003. ok
      +
      003. ok
      -
      <ol start="3">
      +
      <ol start="3">
       <li>ok</li>
       </ol>
      @@ -5134,11 +5134,11 @@ empty lines within the code block verbatim.

      -
      -1. not ok
      +
      -1. not ok
      -
      <p>-1. not ok</p>
      +
      <p>-1. not ok</p>
      @@ -5161,13 +5161,13 @@ In the following case that is 6 spaces:

      -
      - foo
      +
      - foo
       
             bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <pre><code>bar
      @@ -5181,13 +5181,13 @@ In the following case that is 6 spaces:

      -
        10.  foo
      +
        10.  foo
       
                  bar
      -
      <ol start="10">
      +
      <ol start="10">
       <li>
       <p>foo</p>
       <pre><code>bar
      @@ -5203,7 +5203,7 @@ list marker:

      -
          indented code
      +
          indented code
       
       paragraph
       
      @@ -5211,7 +5211,7 @@ list marker:

      -
      <pre><code>indented code
      +
      <pre><code>indented code
       </code></pre>
       <p>paragraph</p>
       <pre><code>more code
      @@ -5222,7 +5222,7 @@ list marker:

      -
      1.     indented code
      +
      1.     indented code
       
          paragraph
       
      @@ -5230,7 +5230,7 @@ list marker:

      -
      <ol>
      +
      <ol>
       <li>
       <pre><code>indented code
       </code></pre>
      @@ -5247,7 +5247,7 @@ inside the code block:

      -
      1.      indented code
      +
      1.      indented code
       
          paragraph
       
      @@ -5255,7 +5255,7 @@ inside the code block:

      -
      <ol>
      +
      <ol>
       <li>
       <pre><code> indented code
       </code></pre>
      @@ -5277,13 +5277,13 @@ indenting the whole thing and prepending a list marker:

      -
         foo
      +
         foo
       
       bar
      -
      <p>foo</p>
      +
      <p>foo</p>
       <p>bar</p>
      @@ -5291,13 +5291,13 @@ indenting the whole thing and prepending a list marker:

      -
      -    foo
      +
      -    foo
       
         bar
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       </ul>
       <p>bar</p>
      @@ -5311,13 +5311,13 @@ the above case:

      -
      -  foo
      +
      -  foo
       
          bar
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>bar</p>
      @@ -5344,7 +5344,7 @@ start number, based on the ordered list marker.
       
      -
      -
      +
      -
         foo
       -
         ```
      @@ -5355,7 +5355,7 @@ start number, based on the ordered list marker.
       
       
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li>
       <pre><code>bar
      @@ -5374,12 +5374,12 @@ following the list marker doesn't change the required indentation:

      -
      -   
      +
      -   
         foo
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       </ul>
      @@ -5391,13 +5391,13 @@ item:

      -
      -
      +
      -
       
         foo
      -
      <ul>
      +
      <ul>
       <li></li>
       </ul>
       <p>foo</p>
      @@ -5408,13 +5408,13 @@ item:

      -
      - foo
      +
      - foo
       -
       - bar
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li></li>
       <li>bar</li>
      @@ -5426,13 +5426,13 @@ item:

      -
      - foo
      +
      - foo
       -   
       - bar
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li></li>
       <li>bar</li>
      @@ -5444,13 +5444,13 @@ item:

      -
      1. foo
      +
      1. foo
       2.
       3. bar
      -
      <ol>
      +
      <ol>
       <li>foo</li>
       <li></li>
       <li>bar</li>
      @@ -5462,11 +5462,11 @@ item:

      -
      *
      +
      *
      -
      <ul>
      +
      <ul>
       <li></li>
       </ul>
      @@ -5476,7 +5476,7 @@ item:

      -
      foo
      +
      foo
       *
       
       foo
      @@ -5484,7 +5484,7 @@ item:

      -
      <p>foo
      +
      <p>foo
       *</p>
       <p>foo
       1.</p>
      @@ -5503,7 +5503,7 @@ empty, then it need not be indented.
      -
       1.  A paragraph
      +
       1.  A paragraph
            with two lines.
       
                indented code
      @@ -5512,7 +5512,7 @@ empty, then it need not be indented.
       
       
      -
      <ol>
      +
      <ol>
       <li>
       <p>A paragraph
       with two lines.</p>
      @@ -5530,7 +5530,7 @@ empty, then it need not be indented.
       
      -
        1.  A paragraph
      +
        1.  A paragraph
             with two lines.
       
                 indented code
      @@ -5539,7 +5539,7 @@ empty, then it need not be indented.
       
       
      -
      <ol>
      +
      <ol>
       <li>
       <p>A paragraph
       with two lines.</p>
      @@ -5557,7 +5557,7 @@ empty, then it need not be indented.
       
      -
         1.  A paragraph
      +
         1.  A paragraph
              with two lines.
       
                  indented code
      @@ -5566,7 +5566,7 @@ empty, then it need not be indented.
       
       
      -
      <ol>
      +
      <ol>
       <li>
       <p>A paragraph
       with two lines.</p>
      @@ -5584,7 +5584,7 @@ empty, then it need not be indented.
       
      -
          1.  A paragraph
      +
          1.  A paragraph
               with two lines.
       
                   indented code
      @@ -5593,7 +5593,7 @@ empty, then it need not be indented.
       
       
      -
      <pre><code>1.  A paragraph
      +
      <pre><code>1.  A paragraph
           with two lines.
       
               indented code
      @@ -5618,7 +5618,7 @@ lines are called
       
      -
        1.  A paragraph
      +
        1.  A paragraph
       with two lines.
       
                 indented code
      @@ -5627,7 +5627,7 @@ lines are called
       
       
      -
      <ol>
      +
      <ol>
       <li>
       <p>A paragraph
       with two lines.</p>
      @@ -5645,12 +5645,12 @@ lines are called
       
      -
        1.  A paragraph
      +
        1.  A paragraph
           with two lines.
      -
      <ol>
      +
      <ol>
       <li>A paragraph
       with two lines.</li>
       </ol>
      @@ -5661,12 +5661,12 @@ lines are called
      -
      > 1. > Blockquote
      +
      > 1. > Blockquote
       continued here.
      -
      <blockquote>
      +
      <blockquote>
       <ol>
       <li>
       <blockquote>
      @@ -5682,12 +5682,12 @@ lines are called
       
      -
      > 1. > Blockquote
      +
      > 1. > Blockquote
       > continued here.
      -
      <blockquote>
      +
      <blockquote>
       <ol>
       <li>
       <blockquote>
      @@ -5713,14 +5713,14 @@ in the list item.

      -
      - foo
      +
      - foo
         - bar
           - baz
             - boo
      -
      <ul>
      +
      <ul>
       <li>foo
       <ul>
       <li>bar
      @@ -5742,14 +5742,14 @@ in the list item.

      -
      - foo
      +
      - foo
        - bar
         - baz
          - boo
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li>bar</li>
       <li>baz</li>
      @@ -5762,12 +5762,12 @@ in the list item.

      -
      10) foo
      +
      10) foo
           - bar
      -
      <ol start="10">
      +
      <ol start="10">
       <li>foo
       <ul>
       <li>bar</li>
      @@ -5781,12 +5781,12 @@ in the list item.

      -
      10) foo
      +
      10) foo
          - bar
      -
      <ol start="10">
      +
      <ol start="10">
       <li>foo</li>
       </ol>
       <ul>
      @@ -5799,11 +5799,11 @@ in the list item.

      -
      - - foo
      +
      - - foo
      -
      <ul>
      +
      <ul>
       <li>
       <ul>
       <li>foo</li>
      @@ -5816,11 +5816,11 @@ in the list item.

      -
      1. - 2. foo
      +
      1. - 2. foo
      -
      <ol>
      +
      <ol>
       <li>
       <ul>
       <li>
      @@ -5838,14 +5838,14 @@ in the list item.

      -
      - # Foo
      +
      - # Foo
       - Bar
         ---
         baz
      -
      <ul>
      +
      <ul>
       <li>
       <h1>Foo</h1>
       </li>
      @@ -5926,7 +5926,7 @@ unindented if needed.)

      indentation from the margin. The four-space rule is clear but unnatural. It is quite unintuitive that

      -
      - foo
      +
      - foo
       
         bar
       
      @@ -5935,7 +5935,7 @@ unnatural. It is quite unintuitive that

      should be parsed as two lists with an intervening paragraph,

      -
      <ul>
      +
      <ul>
       <li>foo</li>
       </ul>
       <p>bar</p>
      @@ -5946,7 +5946,7 @@ unnatural. It is quite unintuitive that

      as the four-space rule demands, rather than a single list,

      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>bar</p>
      @@ -5965,14 +5965,14 @@ initial list marker, allows text that is indented Markdown.pl parses

      -
         - one
      +
         - one
       
         two

      as a single list item, with two a continuation paragraph:

      -
      <ul>
      +
      <ul>
       <li>
       <p>one</p>
       <p>two</p>
      @@ -5982,14 +5982,14 @@ original list marker to be included in the list item. For example,
       

      and similarly

      -
      >   - one
      +
      >   - one
       >
       >  two

      as

      -
      <blockquote>
      +
      <blockquote>
       <ul>
       <li>
       <p>one</p>
      @@ -6007,7 +6007,7 @@ discussed.  Unlike the spec presented above, it would count the following
       as a list item with a subparagraph, even though the paragraph bar
       is not indented as far as the first paragraph foo:

      -
       10. foo
      +
       10. foo
       
          bar  
      @@ -6017,7 +6017,7 @@ which may count in favor of the proposal. However, on this proposal indented code would have to be indented six spaces after the list marker. And this would break a lot of existing Markdown, which has the pattern:

      -
      1.  foo
      +
      1.  foo
       
               indented code
      @@ -6054,12 +6054,12 @@ the final rendered document.

      -
      - [ ] foo
      +
      - [ ] foo
       - [x] bar
      -
      <ul>
      +
      <ul>
       <li><input disabled="" type="checkbox"> foo</li>
       <li><input checked="" disabled="" type="checkbox"> bar</li>
       </ul>
      @@ -6070,14 +6070,14 @@ the final rendered document.

      -
      - [x] foo
      +
      - [x] foo
         - [ ] bar
         - [x] baz
       - [ ] bim
      -
      <ul>
      +
      <ul>
       <li><input checked="" disabled="" type="checkbox"> foo
       <ul>
       <li><input disabled="" type="checkbox"> bar</li>
      @@ -6120,13 +6120,13 @@ wrapped in <p> tags, while p
       
      -
      - foo
      +
      - foo
       - bar
       + baz
      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li>bar</li>
       </ul>
      @@ -6139,13 +6139,13 @@ wrapped in <p> tags, while p
       
      -
      1. foo
      +
      1. foo
       2. bar
       3) baz
      -
      <ol>
      +
      <ol>
       <li>foo</li>
       <li>bar</li>
       </ol>
      @@ -6161,13 +6161,13 @@ list:

      -
      Foo
      +
      Foo
       - bar
       - baz
      -
      <p>Foo</p>
      +
      <p>Foo</p>
       <ul>
       <li>bar</li>
       <li>baz</li>
      @@ -6178,7 +6178,7 @@ list:

      Markdown.pl does not allow this, through fear of triggering a list via a numeral in a hard-wrapped line:

      -
      The number of windows in my house is
      +
      The number of windows in my house is
       14.  The number of doors is 6.
      @@ -6189,7 +6189,7 @@ apply.

      two reasons. First, it is natural and not uncommon for people to start lists without blank lines:

      -
      I need to buy
      +
      I need to buy
       - new shoes
       - a coat
       - a plane ticket
      @@ -6205,7 +6205,7 @@ container block (such as a list item or blockquote).

      (Indeed, the spec for [list items] and [block quotes] presupposes this principle.) This principle implies that if

      -
        * I need to buy
      +
        * I need to buy
           - new shoes
           - a coat
           - a plane ticket
      @@ -6216,7 +6216,7 @@ as all Markdown implementations agree it is (though the paragraph may be rendered without <p> tags, since the list is "tight"), then

      -
      I need to buy
      +
      I need to buy
       - new shoes
       - a coat
       - a plane ticket
      @@ -6235,12 +6235,12 @@ interrupt paragraphs. Thus,

      -
      The number of windows in my house is
      +
      The number of windows in my house is
       14.  The number of doors is 6.
      -
      <p>The number of windows in my house is
      +
      <p>The number of windows in my house is
       14.  The number of doors is 6.</p>
      @@ -6249,12 +6249,12 @@ interrupt paragraphs. Thus,

      -
      The number of windows in my house is
      +
      The number of windows in my house is
       1.  The number of doors is 6.
      -
      <p>The number of windows in my house is</p>
      +
      <p>The number of windows in my house is</p>
       <ol>
       <li>The number of doors is 6.</li>
       </ol>
      @@ -6266,7 +6266,7 @@ interrupt paragraphs. Thus,

      -
      - foo
      +
      - foo
       
       - bar
       
      @@ -6275,7 +6275,7 @@ interrupt paragraphs.  Thus,

      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       </li>
      @@ -6292,7 +6292,7 @@ interrupt paragraphs.  Thus,

      -
      - foo
      +
      - foo
         - bar
           - baz
       
      @@ -6301,7 +6301,7 @@ interrupt paragraphs.  Thus,

      -
      <ul>
      +
      <ul>
       <li>foo
       <ul>
       <li>bar
      @@ -6325,7 +6325,7 @@ comment:

      -
      - foo
      +
      - foo
       - bar
       
       <!-- -->
      @@ -6335,7 +6335,7 @@ comment:

      -
      <ul>
      +
      <ul>
       <li>foo</li>
       <li>bar</li>
       </ul>
      @@ -6350,7 +6350,7 @@ comment:

      -
      -   foo
      +
      -   foo
       
           notcode
       
      @@ -6362,7 +6362,7 @@ comment:

      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <p>notcode</p>
      @@ -6384,7 +6384,7 @@ item:

      -
      - a
      +
      - a
        - b
         - c
          - d
      @@ -6394,7 +6394,7 @@ item:

      -
      <ul>
      +
      <ul>
       <li>a</li>
       <li>b</li>
       <li>c</li>
      @@ -6409,7 +6409,7 @@ item:

      -
      1. a
      +
      1. a
       
         2. b
       
      @@ -6417,7 +6417,7 @@ item:

      -
      <ol>
      +
      <ol>
       <li>
       <p>a</p>
       </li>
      @@ -6437,7 +6437,7 @@ line, because it is indented more than three spaces:

      -
      - a
      +
      - a
        - b
         - c
          - d
      @@ -6445,7 +6445,7 @@ line, because it is indented more than three spaces:

      -
      <ul>
      +
      <ul>
       <li>a</li>
       <li>b</li>
       <li>c</li>
      @@ -6461,7 +6461,7 @@ blank line.

      -
      1. a
      +
      1. a
       
         2. b
       
      @@ -6469,7 +6469,7 @@ blank line.

      -
      <ol>
      +
      <ol>
       <li>
       <p>a</p>
       </li>
      @@ -6487,14 +6487,14 @@ two of the list items:

      -
      - a
      +
      - a
       - b
       
       - c
      -
      <ul>
      +
      <ul>
       <li>
       <p>a</p>
       </li>
      @@ -6512,14 +6512,14 @@ two of the list items:

      -
      * a
      +
      * a
       *
       
       * c
      -
      <ul>
      +
      <ul>
       <li>
       <p>a</p>
       </li>
      @@ -6537,7 +6537,7 @@ with a blank line between them:

      -
      - a
      +
      - a
       - b
       
         c
      @@ -6545,7 +6545,7 @@ with a blank line between them:

      -
      <ul>
      +
      <ul>
       <li>
       <p>a</p>
       </li>
      @@ -6563,7 +6563,7 @@ with a blank line between them:

      -
      - a
      +
      - a
       - b
       
         [ref]: /url
      @@ -6571,7 +6571,7 @@ with a blank line between them:

      -
      <ul>
      +
      <ul>
       <li>
       <p>a</p>
       </li>
      @@ -6589,7 +6589,7 @@ with a blank line between them:

      -
      - a
      +
      - a
       - ```
         b
       
      @@ -6599,7 +6599,7 @@ with a blank line between them:

      -
      <ul>
      +
      <ul>
       <li>a</li>
       <li>
       <pre><code>b
      @@ -6618,7 +6618,7 @@ the outer list is tight:

      -
      - a
      +
      - a
         - b
       
           c
      @@ -6626,7 +6626,7 @@ the outer list is tight:

      -
      <ul>
      +
      <ul>
       <li>a
       <ul>
       <li>
      @@ -6645,14 +6645,14 @@ block quote:

      -
      * a
      +
      * a
         > b
         >
       * c
      -
      <ul>
      +
      <ul>
       <li>a
       <blockquote>
       <p>b</p>
      @@ -6668,7 +6668,7 @@ are not separated by blank lines:

      -
      - a
      +
      - a
         > b
         ```
         c
      @@ -6677,7 +6677,7 @@ are not separated by blank lines:

      -
      <ul>
      +
      <ul>
       <li>a
       <blockquote>
       <p>b</p>
      @@ -6694,11 +6694,11 @@ are not separated by blank lines:

      -
      - a
      +
      - a
      -
      <ul>
      +
      <ul>
       <li>a</li>
       </ul>
      @@ -6707,12 +6707,12 @@ are not separated by blank lines:

      -
      - a
      +
      - a
         - b
      -
      <ul>
      +
      <ul>
       <li>a
       <ul>
       <li>b</li>
      @@ -6727,7 +6727,7 @@ two block elements in the list item:

      -
      1. ```
      +
      1. ```
          foo
          ```
       
      @@ -6735,7 +6735,7 @@ two block elements in the list item:

      -
      <ol>
      +
      <ol>
       <li>
       <pre><code>foo
       </code></pre>
      @@ -6749,14 +6749,14 @@ two block elements in the list item:

      -
      * foo
      +
      * foo
         * bar
       
         baz
      -
      <ul>
      +
      <ul>
       <li>
       <p>foo</p>
       <ul>
      @@ -6771,7 +6771,7 @@ two block elements in the list item:

      -
      - a
      +
      - a
         - b
         - c
       
      @@ -6781,7 +6781,7 @@ two block elements in the list item:

      -
      <ul>
      +
      <ul>
       <li>
       <p>a</p>
       <ul>
      @@ -6808,11 +6808,11 @@ Thus, for example, in

      -
      `hi`lo`
      +
      `hi`lo`
      -
      <p><code>hi</code>lo`</p>
      +
      <p><code>hi</code>lo`</p>
      @@ -6824,11 +6824,11 @@ backtick.

      -
      \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
      +
      \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
      -
      <p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
      +
      <p>!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</p>
      @@ -6837,11 +6837,11 @@ backslashes:

      -
      \→\A\a\ \3\φ\«
      +
      \→\A\a\ \3\φ\«
      -
      <p>\→\A\a\ \3\φ\«</p>
      +
      <p>\→\A\a\ \3\φ\«</p>
      @@ -6850,7 +6850,7 @@ not have their usual Markdown meanings:

      -
      \*not emphasized*
      +
      \*not emphasized*
       \<br/> not a tag
       \[not a link](/foo)
       \`not code`
      @@ -6862,7 +6862,7 @@ not have their usual Markdown meanings:

      -
      <p>*not emphasized*
      +
      <p>*not emphasized*
       &lt;br/&gt; not a tag
       [not a link](/foo)
       `not code`
      @@ -6878,11 +6878,11 @@ not have their usual Markdown meanings:

      -
      \\*emphasis*
      +
      \\*emphasis*
      -
      <p>\<em>emphasis</em></p>
      +
      <p>\<em>emphasis</em></p>
      @@ -6890,12 +6890,12 @@ not have their usual Markdown meanings:

      -
      foo\
      +
      foo\
       bar
      -
      <p>foo<br />
      +
      <p>foo<br />
       bar</p>
      @@ -6905,22 +6905,22 @@ raw HTML:

      -
      `` \[\` ``
      +
      `` \[\` ``
      -
      <p><code>\[\`</code></p>
      +
      <p><code>\[\`</code></p>
      -
          \[\]
      +
          \[\]
      -
      <pre><code>\[\]
      +
      <pre><code>\[\]
       </code></pre>
      @@ -6928,13 +6928,13 @@ raw HTML:

      -
      ~~~
      +
      ~~~
       \[\]
       ~~~
      -
      <pre><code>\[\]
      +
      <pre><code>\[\]
       </code></pre>
      @@ -6942,22 +6942,22 @@ raw HTML:

      -
      <http://example.com?find=\*>
      +
      <http://example.com?find=\*>
      -
      <p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
      +
      <p><a href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
      -
      <a href="/bar\/)">
      +
      <a href="/bar\/)">
      -
      <a href="/bar\/)">
      +
      <a href="/bar\/)">
      @@ -6966,37 +6966,37 @@ link references, and [info strings] in [fenced code blocks]:

      -
      [foo](/bar\* "ti\*tle")
      +
      [foo](/bar\* "ti\*tle")
      -
      <p><a href="/bar*" title="ti*tle">foo</a></p>
      +
      <p><a href="/bar*" title="ti*tle">foo</a></p>
      -
      [foo]
      +
      [foo]
       
       [foo]: /bar\* "ti\*tle"
      -
      <p><a href="/bar*" title="ti*tle">foo</a></p>
      +
      <p><a href="/bar*" title="ti*tle">foo</a></p>
      -
      ``` foo\+bar
      +
      ``` foo\+bar
       foo
       ```
      -
      <pre><code class="language-foo+bar">foo
      +
      <pre><code class="language-foo+bar">foo
       </code></pre>
      @@ -7031,13 +7031,13 @@ references and their corresponding code points.

      -
      &nbsp; &amp; &copy; &AElig; &Dcaron;
      +
      &nbsp; &amp; &copy; &AElig; &Dcaron;
       &frac34; &HilbertSpace; &DifferentialD;
       &ClockwiseContourIntegral; &ngE;
      -
      <p>  &amp; © Æ Ď
      +
      <p>  &amp; © Æ Ď
       ¾ ℋ ⅆ
       ∲ ≧̸</p>
      @@ -7053,11 +7053,11 @@ the code point U+0000 will also be
      -
      &#35; &#1234; &#992; &#0;
      +
      &#35; &#1234; &#992; &#0;
      -
      <p># Ӓ Ϡ �</p>
      +
      <p># Ӓ Ϡ �</p>
      @@ -7069,11 +7069,11 @@ time specified with a hexadecimal numeral instead of decimal).

      -
      &#X22; &#XD06; &#xcab;
      +
      &#X22; &#XD06; &#xcab;
      -
      <p>&quot; ആ ಫ</p>
      +
      <p>&quot; ആ ಫ</p>
      @@ -7081,14 +7081,14 @@ time specified with a hexadecimal numeral instead of decimal).

      -
      &nbsp &x; &#; &#x;
      +
      &nbsp &x; &#; &#x;
       &#987654321;
       &#abcdef0;
       &ThisIsNotDefined; &hi?;
      -
      <p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
      +
      <p>&amp;nbsp &amp;x; &amp;#; &amp;#x;
       &amp;#987654321;
       &amp;#abcdef0;
       &amp;ThisIsNotDefined; &amp;hi?;</p>
      @@ -7101,11 +7101,11 @@ recognized here, because it makes the grammar too ambiguous:

      -
      &copy
      +
      &copy
      -
      <p>&amp;copy</p>
      +
      <p>&amp;copy</p>
      @@ -7114,11 +7114,11 @@ recognized as entity references either:

      -
      &MadeUpEntity;
      +
      &MadeUpEntity;
      -
      <p>&amp;MadeUpEntity;</p>
      +
      <p>&amp;MadeUpEntity;</p>
      @@ -7128,48 +7128,48 @@ URLs, [link titles], and [fenced code block][] [info strings]:

      -
      <a href="&ouml;&ouml;.html">
      +
      <a href="&ouml;&ouml;.html">
      -
      <a href="&ouml;&ouml;.html">
      +
      <a href="&ouml;&ouml;.html">
      -
      [foo](/f&ouml;&ouml; "f&ouml;&ouml;")
      +
      [foo](/f&ouml;&ouml; "f&ouml;&ouml;")
      -
      <p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
      +
      <p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
      -
      [foo]
      +
      [foo]
       
       [foo]: /f&ouml;&ouml; "f&ouml;&ouml;"
      -
      <p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
      +
      <p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
      -
      ``` f&ouml;&ouml;
      +
      ``` f&ouml;&ouml;
       foo
       ```
      -
      <pre><code class="language-föö">foo
      +
      <pre><code class="language-föö">foo
       </code></pre>
      @@ -7179,22 +7179,22 @@ text in code spans and code blocks:

      -
      `f&ouml;&ouml;`
      +
      `f&ouml;&ouml;`
      -
      <p><code>f&amp;ouml;&amp;ouml;</code></p>
      +
      <p><code>f&amp;ouml;&amp;ouml;</code></p>
      -
          f&ouml;f&ouml;
      +
          f&ouml;f&ouml;
      -
      <pre><code>f&amp;ouml;f&amp;ouml;
      +
      <pre><code>f&amp;ouml;f&amp;ouml;
       </code></pre>
      @@ -7205,12 +7205,12 @@ documents.

      -
      &#42;foo&#42;
      +
      &#42;foo&#42;
       *foo*
      -
      <p>*foo*
      +
      <p>*foo*
       <em>foo</em></p>
      @@ -7218,13 +7218,13 @@ documents.

      -
      &#42; foo
      +
      &#42; foo
       
       * foo
      -
      <p>* foo</p>
      +
      <p>* foo</p>
       <ul>
       <li>foo</li>
       </ul>
      @@ -7234,11 +7234,11 @@ documents.

      -
      foo&#10;&#10;bar
      +
      foo&#10;&#10;bar
      -
      <p>foo
      +
      <p>foo
       
       bar</p>
      @@ -7247,22 +7247,22 @@ documents.

      -
      &#9;foo
      +
      &#9;foo
      -
      <p>→foo</p>
      +
      <p>→foo</p>
      -
      [a](url &quot;tit&quot;)
      +
      [a](url &quot;tit&quot;)
      -
      <p>[a](url &quot;tit&quot;)</p>
      +
      <p>[a](url &quot;tit&quot;)</p>
      @@ -7288,11 +7288,11 @@ whitespace from the opening or closing backtick strings.
      -
      `foo`
      +
      `foo`
      -
      <p><code>foo</code></p>
      +
      <p><code>foo</code></p>
      @@ -7302,11 +7302,11 @@ trailing space:

      -
      `` foo ` bar ``
      +
      `` foo ` bar ``
      -
      <p><code>foo ` bar</code></p>
      +
      <p><code>foo ` bar</code></p>
      @@ -7315,11 +7315,11 @@ spaces:

      -
      ` `` `
      +
      ` `` `
      -
      <p><code>``</code></p>
      +
      <p><code>``</code></p>
      @@ -7327,11 +7327,11 @@ spaces:

      -
      `  ``  `
      +
      `  ``  `
      -
      <p><code> `` </code></p>
      +
      <p><code> `` </code></p>
      @@ -7340,11 +7340,11 @@ sides of the string:

      -
      ` a`
      +
      ` a`
      -
      <p><code> a</code></p>
      +
      <p><code> a</code></p>
      @@ -7353,11 +7353,11 @@ stripped in this way:

      -
      ` b `
      +
      ` b `
      -
      <p><code> b </code></p>
      +
      <p><code> b </code></p>
      @@ -7365,12 +7365,12 @@ stripped in this way:

      -
      ` `
      +
      ` `
       `  `
      -
      <p><code> </code>
      +
      <p><code> </code>
       <code>  </code></p>
      @@ -7379,7 +7379,7 @@ stripped in this way:

      -
      ``
      +
      ``
       foo
       bar  
       baz
      @@ -7387,20 +7387,20 @@ stripped in this way:

      -
      <p><code>foo bar   baz</code></p>
      +
      <p><code>foo bar   baz</code></p>
      -
      ``
      +
      ``
       foo 
       ``
      -
      <p><code>foo </code></p>
      +
      <p><code>foo </code></p>
      @@ -7408,12 +7408,12 @@ stripped in this way:

      -
      `foo   bar 
      +
      `foo   bar 
       baz`
      -
      <p><code>foo   bar  baz</code></p>
      +
      <p><code>foo   bar  baz</code></p>
      @@ -7421,7 +7421,7 @@ stripped in this way:

      when rendering <code> elements, so it is recommended that the following CSS be used:

      -
      code{white-space: pre-wrap;}
      +
      code{white-space: pre-wrap;}

      Note that backslash escapes do not work in code spans. All backslashes @@ -7429,11 +7429,11 @@ are treated literally:

      -
      `foo\`bar`
      +
      `foo\`bar`
      -
      <p><code>foo\</code>bar`</p>
      +
      <p><code>foo\</code>bar`</p>
      @@ -7443,22 +7443,22 @@ not contain any strings of exactly n b
      -
      ``foo`bar``
      +
      ``foo`bar``
      -
      <p><code>foo`bar</code></p>
      +
      <p><code>foo`bar</code></p>
      -
      ` foo `` bar `
      +
      ` foo `` bar `
      -
      <p><code>foo `` bar</code></p>
      +
      <p><code>foo `` bar</code></p>
      @@ -7469,11 +7469,11 @@ span:

      -
      *foo`*`
      +
      *foo`*`
      -
      <p>*foo<code>*</code></p>
      +
      <p>*foo<code>*</code></p>
      @@ -7481,11 +7481,11 @@ span:

      -
      [not a `link](/foo`)
      +
      [not a `link](/foo`)
      -
      <p>[not a <code>link](/foo</code>)</p>
      +
      <p>[not a <code>link](/foo</code>)</p>
      @@ -7494,11 +7494,11 @@ Thus, this is code:

      -
      `<a href="`">`
      +
      `<a href="`">`
      -
      <p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
      +
      <p><code>&lt;a href=&quot;</code>&quot;&gt;`</p>
      @@ -7506,11 +7506,11 @@ Thus, this is code:

      -
      <a href="`">`
      +
      <a href="`">`
      -
      <p><a href="`">`</p>
      +
      <p><a href="`">`</p>
      @@ -7518,11 +7518,11 @@ Thus, this is code:

      -
      `<http://foo.bar.`baz>`
      +
      `<http://foo.bar.`baz>`
      -
      <p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
      +
      <p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
      @@ -7530,11 +7530,11 @@ Thus, this is code:

      -
      <http://foo.bar.`baz>`
      +
      <http://foo.bar.`baz>`
      -
      <p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
      +
      <p><a href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
      @@ -7543,22 +7543,22 @@ we just have literal backticks:

      -
      ```foo``
      +
      ```foo``
      -
      <p>```foo``</p>
      +
      <p>```foo``</p>
      -
      `foo
      +
      `foo
      -
      <p>`foo</p>
      +
      <p>`foo</p>
      @@ -7567,11 +7567,11 @@ closing backtick strings to be equal in length:

      -
      `foo``bar``
      +
      `foo``bar``
      -
      <p>`foo<code>bar</code></p>
      +
      <p>`foo<code>bar</code></p>
      @@ -7591,7 +7591,7 @@ especially when it comes to nested emphasis. The original ___ delimiters can be used for strong emphasis, and most implementations have also allowed the following patterns:

      -
      ***strong emph***
      +
      ***strong emph***
       ***strong** in emph*
       ***emph* in strong**
       **in strong *emph***
      @@ -7602,7 +7602,7 @@ implementations have also allowed the following patterns:

      is clear and they are useful (especially in contexts like bibliography entries):

      -
      *emph *with emph* in it*
      +
      *emph *with emph* in it*
       **strong **with strong** in it**
      @@ -7611,7 +7611,7 @@ the * forms, to avoid unwanted empha internal underscores. (It is best practice to put these in code spans, but users often do not.)

      -
      internal emphasis: foo*bar*baz
      +
      internal emphasis: foo*bar*baz
       no emphasis: foo_bar_baz
      @@ -7641,7 +7641,7 @@ the line count as Unicode whitespace.

    • left-flanking but not right-flanking:

      -
      ***abc
      +
      ***abc
         _abc
       **"abc"
        _"abc"
      @@ -7651,7 +7651,7 @@ the line count as Unicode whitespace.

    • right-flanking but not left-flanking:

      -
       abc***
      +
       abc***
        abc_
       "abc"**
       "abc"_
      @@ -7661,7 +7661,7 @@ the line count as Unicode whitespace.

    • Both left and right-flanking:

      -
       abc***def
      +
       abc***def
       "abc"_"def"
      @@ -7669,7 +7669,7 @@ the line count as Unicode whitespace.

    • Neither left nor right-flanking:

      -
      abc *** def
      +
      abc *** def
       a _ b
      @@ -7802,11 +7802,11 @@ parsed as *<a href="bar">foo*</a
      -
      *foo bar*
      +
      *foo bar*
      -
      <p><em>foo bar</em></p>
      +
      <p><em>foo bar</em></p>
      @@ -7815,11 +7815,11 @@ whitespace, and hence not part of a [left-flanking delimiter run]:

      -
      a * foo bar*
      +
      a * foo bar*
      -
      <p>a * foo bar*</p>
      +
      <p>a * foo bar*</p>
      @@ -7829,11 +7829,11 @@ not part of a [left-flanking delimiter run]:

      -
      a*"foo"*
      +
      a*"foo"*
      -
      <p>a*&quot;foo&quot;*</p>
      +
      <p>a*&quot;foo&quot;*</p>
      @@ -7841,11 +7841,11 @@ not part of a [left-flanking delimiter run]:

      -
      * a *
      +
      * a *
      -
      <p>* a *</p>
      +
      <p>* a *</p>
      @@ -7853,22 +7853,22 @@ not part of a [left-flanking delimiter run]:

      -
      foo*bar*
      +
      foo*bar*
      -
      <p>foo<em>bar</em></p>
      +
      <p>foo<em>bar</em></p>
      -
      5*6*78
      +
      5*6*78
      -
      <p>5<em>6</em>78</p>
      +
      <p>5<em>6</em>78</p>
      @@ -7876,11 +7876,11 @@ not part of a [left-flanking delimiter run]:

      -
      _foo bar_
      +
      _foo bar_
      -
      <p><em>foo bar</em></p>
      +
      <p><em>foo bar</em></p>
      @@ -7889,11 +7889,11 @@ whitespace:

      -
      _ foo bar_
      +
      _ foo bar_
      -
      <p>_ foo bar_</p>
      +
      <p>_ foo bar_</p>
      @@ -7902,11 +7902,11 @@ by an alphanumeric and followed by punctuation:

      -
      a_"foo"_
      +
      a_"foo"_
      -
      <p>a_&quot;foo&quot;_</p>
      +
      <p>a_&quot;foo&quot;_</p>
      @@ -7914,33 +7914,33 @@ by an alphanumeric and followed by punctuation:

      -
      foo_bar_
      +
      foo_bar_
      -
      <p>foo_bar_</p>
      +
      <p>foo_bar_</p>
      -
      5_6_78
      +
      5_6_78
      -
      <p>5_6_78</p>
      +
      <p>5_6_78</p>
      -
      пристаням_стремятся_
      +
      пристаням_стремятся_
      -
      <p>пристаням_стремятся_</p>
      +
      <p>пристаням_стремятся_</p>
      @@ -7949,11 +7949,11 @@ is right-flanking and the second left-flanking:

      -
      aa_"bb"_cc
      +
      aa_"bb"_cc
      -
      <p>aa_&quot;bb&quot;_cc</p>
      +
      <p>aa_&quot;bb&quot;_cc</p>
      @@ -7963,11 +7963,11 @@ punctuation:

      -
      foo-_(bar)_
      +
      foo-_(bar)_
      -
      <p>foo-<em>(bar)</em></p>
      +
      <p>foo-<em>(bar)</em></p>
      @@ -7977,11 +7977,11 @@ not match the opening delimiter:

      -
      _foo*
      +
      _foo*
      -
      <p>_foo*</p>
      +
      <p>_foo*</p>
      @@ -7990,11 +7990,11 @@ whitespace:

      -
      *foo bar *
      +
      *foo bar *
      -
      <p>*foo bar *</p>
      +
      <p>*foo bar *</p>
      @@ -8002,12 +8002,12 @@ whitespace:

      -
      *foo bar
      +
      *foo bar
       *
      -
      <p>*foo bar
      +
      <p>*foo bar
       *</p>
      @@ -8018,11 +8018,11 @@ preceded by punctuation and followed by an alphanumeric
      -
      *(*foo)
      +
      *(*foo)
      -
      <p>*(*foo)</p>
      +
      <p>*(*foo)</p>
      @@ -8031,11 +8031,11 @@ with this example:

      -
      *(*foo*)*
      +
      *(*foo*)*
      -
      <p><em>(<em>foo</em>)</em></p>
      +
      <p><em>(<em>foo</em>)</em></p>
      @@ -8043,11 +8043,11 @@ with this example:

      -
      *foo*bar
      +
      *foo*bar
      -
      <p><em>foo</em>bar</p>
      +
      <p><em>foo</em>bar</p>
      @@ -8057,11 +8057,11 @@ whitespace:

      -
      _foo bar _
      +
      _foo bar _
      -
      <p>_foo bar _</p>
      +
      <p>_foo bar _</p>
      @@ -8070,11 +8070,11 @@ preceded by punctuation and followed by an alphanumeric:

      -
      _(_foo)
      +
      _(_foo)
      -
      <p>_(_foo)</p>
      +
      <p>_(_foo)</p>
      @@ -8082,11 +8082,11 @@ preceded by punctuation and followed by an alphanumeric:

      -
      _(_foo_)_
      +
      _(_foo_)_
      -
      <p><em>(<em>foo</em>)</em></p>
      +
      <p><em>(<em>foo</em>)</em></p>
      @@ -8094,33 +8094,33 @@ preceded by punctuation and followed by an alphanumeric:

      -
      _foo_bar
      +
      _foo_bar
      -
      <p>_foo_bar</p>
      +
      <p>_foo_bar</p>
      -
      _пристаням_стремятся
      +
      _пристаням_стремятся
      -
      <p>_пристаням_стремятся</p>
      +
      <p>_пристаням_стремятся</p>
      -
      _foo_bar_baz_
      +
      _foo_bar_baz_
      -
      <p><em>foo_bar_baz</em></p>
      +
      <p><em>foo_bar_baz</em></p>
      @@ -8130,11 +8130,11 @@ punctuation:

      -
      _(bar)_.
      +
      _(bar)_.
      -
      <p><em>(bar)</em>.</p>
      +
      <p><em>(bar)</em>.</p>
      @@ -8142,11 +8142,11 @@ punctuation:

      -
      **foo bar**
      +
      **foo bar**
      -
      <p><strong>foo bar</strong></p>
      +
      <p><strong>foo bar</strong></p>
      @@ -8155,11 +8155,11 @@ followed by whitespace:

      -
      ** foo bar**
      +
      ** foo bar**
      -
      <p>** foo bar**</p>
      +
      <p>** foo bar**</p>
      @@ -8169,11 +8169,11 @@ not part of a [left-flanking delimiter run]:

      -
      a**"foo"**
      +
      a**"foo"**
      -
      <p>a**&quot;foo&quot;**</p>
      +
      <p>a**&quot;foo&quot;**</p>
      @@ -8181,11 +8181,11 @@ not part of a [left-flanking delimiter run]:

      -
      foo**bar**
      +
      foo**bar**
      -
      <p>foo<strong>bar</strong></p>
      +
      <p>foo<strong>bar</strong></p>
      @@ -8193,11 +8193,11 @@ not part of a [left-flanking delimiter run]:

      -
      __foo bar__
      +
      __foo bar__
      -
      <p><strong>foo bar</strong></p>
      +
      <p><strong>foo bar</strong></p>
      @@ -8206,11 +8206,11 @@ followed by whitespace:

      -
      __ foo bar__
      +
      __ foo bar__
      -
      <p>__ foo bar__</p>
      +
      <p>__ foo bar__</p>
      @@ -8218,12 +8218,12 @@ followed by whitespace:

      -
      __
      +
      __
       foo bar__
      -
      <p>__
      +
      <p>__
       foo bar__</p>
      @@ -8233,11 +8233,11 @@ by an alphanumeric and followed by punctuation:

      -
      a__"foo"__
      +
      a__"foo"__
      -
      <p>a__&quot;foo&quot;__</p>
      +
      <p>a__&quot;foo&quot;__</p>
      @@ -8245,44 +8245,44 @@ by an alphanumeric and followed by punctuation:

      -
      foo__bar__
      +
      foo__bar__
      -
      <p>foo__bar__</p>
      +
      <p>foo__bar__</p>
      -
      5__6__78
      +
      5__6__78
      -
      <p>5__6__78</p>
      +
      <p>5__6__78</p>
      -
      пристаням__стремятся__
      +
      пристаням__стремятся__
      -
      <p>пристаням__стремятся__</p>
      +
      <p>пристаням__стремятся__</p>
      -
      __foo, __bar__, baz__
      +
      __foo, __bar__, baz__
      -
      <p><strong>foo, <strong>bar</strong>, baz</strong></p>
      +
      <p><strong>foo, <strong>bar</strong>, baz</strong></p>
      @@ -8292,11 +8292,11 @@ punctuation:

      -
      foo-__(bar)__
      +
      foo-__(bar)__
      -
      <p>foo-<strong>(bar)</strong></p>
      +
      <p>foo-<strong>(bar)</strong></p>
      @@ -8306,11 +8306,11 @@ by whitespace:

      -
      **foo bar **
      +
      **foo bar **
      -
      <p>**foo bar **</p>
      +
      <p>**foo bar **</p>
      @@ -8321,11 +8321,11 @@ preceded by punctuation and followed by an alphanumeric:

      -
      **(**foo)
      +
      **(**foo)
      -
      <p>**(**foo)</p>
      +
      <p>**(**foo)</p>
      @@ -8334,23 +8334,23 @@ with these examples:

      -
      *(**foo**)*
      +
      *(**foo**)*
      -
      <p><em>(<strong>foo</strong>)</em></p>
      +
      <p><em>(<strong>foo</strong>)</em></p>
      -
      **Gomphocarpus (*Gomphocarpus physocarpus*, syn.
      +
      **Gomphocarpus (*Gomphocarpus physocarpus*, syn.
       *Asclepias physocarpa*)**
      -
      <p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
      +
      <p><strong>Gomphocarpus (<em>Gomphocarpus physocarpus</em>, syn.
       <em>Asclepias physocarpa</em>)</strong></p>
      @@ -8358,11 +8358,11 @@ with these examples:

      -
      **foo "*bar*" foo**
      +
      **foo "*bar*" foo**
      -
      <p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
      +
      <p><strong>foo &quot;<em>bar</em>&quot; foo</strong></p>
      @@ -8370,11 +8370,11 @@ with these examples:

      -
      **foo**bar
      +
      **foo**bar
      -
      <p><strong>foo</strong>bar</p>
      +
      <p><strong>foo</strong>bar</p>
      @@ -8384,11 +8384,11 @@ preceded by whitespace:

      -
      __foo bar __
      +
      __foo bar __
      -
      <p>__foo bar __</p>
      +
      <p>__foo bar __</p>
      @@ -8397,11 +8397,11 @@ preceded by punctuation and followed by an alphanumeric:

      -
      __(__foo)
      +
      __(__foo)
      -
      <p>__(__foo)</p>
      +
      <p>__(__foo)</p>
      @@ -8410,11 +8410,11 @@ with this example:

      -
      _(__foo__)_
      +
      _(__foo__)_
      -
      <p><em>(<strong>foo</strong>)</em></p>
      +
      <p><em>(<strong>foo</strong>)</em></p>
      @@ -8422,33 +8422,33 @@ with this example:

      -
      __foo__bar
      +
      __foo__bar
      -
      <p>__foo__bar</p>
      +
      <p>__foo__bar</p>
      -
      __пристаням__стремятся
      +
      __пристаням__стремятся
      -
      <p>__пристаням__стремятся</p>
      +
      <p>__пристаням__стремятся</p>
      -
      __foo__bar__baz__
      +
      __foo__bar__baz__
      -
      <p><strong>foo__bar__baz</strong></p>
      +
      <p><strong>foo__bar__baz</strong></p>
      @@ -8458,11 +8458,11 @@ punctuation:

      -
      __(bar)__.
      +
      __(bar)__.
      -
      <p><strong>(bar)</strong>.</p>
      +
      <p><strong>(bar)</strong>.</p>
      @@ -8472,23 +8472,23 @@ emphasized span.

      -
      *foo [bar](/url)*
      +
      *foo [bar](/url)*
      -
      <p><em>foo <a href="/url">bar</a></em></p>
      +
      <p><em>foo <a href="/url">bar</a></em></p>
      -
      *foo
      +
      *foo
       bar*
      -
      <p><em>foo
      +
      <p><em>foo
       bar</em></p>
      @@ -8498,72 +8498,72 @@ inside emphasis:

      -
      _foo __bar__ baz_
      +
      _foo __bar__ baz_
      -
      <p><em>foo <strong>bar</strong> baz</em></p>
      +
      <p><em>foo <strong>bar</strong> baz</em></p>
      -
      _foo _bar_ baz_
      +
      _foo _bar_ baz_
      -
      <p><em>foo <em>bar</em> baz</em></p>
      +
      <p><em>foo <em>bar</em> baz</em></p>
      -
      __foo_ bar_
      +
      __foo_ bar_
      -
      <p><em><em>foo</em> bar</em></p>
      +
      <p><em><em>foo</em> bar</em></p>
      -
      *foo *bar**
      +
      *foo *bar**
      -
      <p><em>foo <em>bar</em></em></p>
      +
      <p><em>foo <em>bar</em></em></p>
      -
      *foo **bar** baz*
      +
      *foo **bar** baz*
      -
      <p><em>foo <strong>bar</strong> baz</em></p>
      +
      <p><em>foo <strong>bar</strong> baz</em></p>
      -
      *foo**bar**baz*
      +
      *foo**bar**baz*
      -
      <p><em>foo<strong>bar</strong>baz</em></p>
      +
      <p><em>foo<strong>bar</strong>baz</em></p>

      Note that in the preceding case, the interpretation

      -
      <p><em>foo</em><em>bar<em></em>baz</em></p>
      +
      <p><em>foo</em><em>bar<em></em>baz</em></p>

      is precluded by the condition that a delimiter that @@ -8577,11 +8577,11 @@ emphasis sections in this example:

      -
      *foo**bar*
      +
      *foo**bar*
      -
      <p><em>foo**bar</em></p>
      +
      <p><em>foo**bar</em></p>
      @@ -8592,33 +8592,33 @@ omitted:

      -
      ***foo** bar*
      +
      ***foo** bar*
      -
      <p><em><strong>foo</strong> bar</em></p>
      +
      <p><em><strong>foo</strong> bar</em></p>
      -
      *foo **bar***
      +
      *foo **bar***
      -
      <p><em>foo <strong>bar</strong></em></p>
      +
      <p><em>foo <strong>bar</strong></em></p>
      -
      *foo**bar***
      +
      *foo**bar***
      -
      <p><em>foo<strong>bar</strong></em></p>
      +
      <p><em>foo<strong>bar</strong></em></p>
      @@ -8628,22 +8628,22 @@ they can match to create emphasis:

      -
      foo***bar***baz
      +
      foo***bar***baz
      -
      <p>foo<em><strong>bar</strong></em>baz</p>
      +
      <p>foo<em><strong>bar</strong></em>baz</p>
      -
      foo******bar*********baz
      +
      foo******bar*********baz
      -
      <p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
      +
      <p>foo<strong><strong><strong>bar</strong></strong></strong>***baz</p>
      @@ -8651,22 +8651,22 @@ they can match to create emphasis:

      -
      *foo **bar *baz* bim** bop*
      +
      *foo **bar *baz* bim** bop*
      -
      <p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
      +
      <p><em>foo <strong>bar <em>baz</em> bim</strong> bop</em></p>
      -
      *foo [*bar*](/url)*
      +
      *foo [*bar*](/url)*
      -
      <p><em>foo <a href="/url"><em>bar</em></a></em></p>
      +
      <p><em>foo <a href="/url"><em>bar</em></a></em></p>
      @@ -8674,22 +8674,22 @@ they can match to create emphasis:

      -
      ** is not an empty emphasis
      +
      ** is not an empty emphasis
      -
      <p>** is not an empty emphasis</p>
      +
      <p>** is not an empty emphasis</p>
      -
      **** is not an empty strong emphasis
      +
      **** is not an empty strong emphasis
      -
      <p>**** is not an empty strong emphasis</p>
      +
      <p>**** is not an empty strong emphasis</p>
      @@ -8699,23 +8699,23 @@ strongly emphasized span.

      -
      **foo [bar](/url)**
      +
      **foo [bar](/url)**
      -
      <p><strong>foo <a href="/url">bar</a></strong></p>
      +
      <p><strong>foo <a href="/url">bar</a></strong></p>
      -
      **foo
      +
      **foo
       bar**
      -
      <p><strong>foo
      +
      <p><strong>foo
       bar</strong></p>
      @@ -8725,88 +8725,88 @@ inside strong emphasis:

      -
      __foo _bar_ baz__
      +
      __foo _bar_ baz__
      -
      <p><strong>foo <em>bar</em> baz</strong></p>
      +
      <p><strong>foo <em>bar</em> baz</strong></p>
      -
      __foo __bar__ baz__
      +
      __foo __bar__ baz__
      -
      <p><strong>foo <strong>bar</strong> baz</strong></p>
      +
      <p><strong>foo <strong>bar</strong> baz</strong></p>
      -
      ____foo__ bar__
      +
      ____foo__ bar__
      -
      <p><strong><strong>foo</strong> bar</strong></p>
      +
      <p><strong><strong>foo</strong> bar</strong></p>
      -
      **foo **bar****
      +
      **foo **bar****
      -
      <p><strong>foo <strong>bar</strong></strong></p>
      +
      <p><strong>foo <strong>bar</strong></strong></p>
      -
      **foo *bar* baz**
      +
      **foo *bar* baz**
      -
      <p><strong>foo <em>bar</em> baz</strong></p>
      +
      <p><strong>foo <em>bar</em> baz</strong></p>
      -
      **foo*bar*baz**
      +
      **foo*bar*baz**
      -
      <p><strong>foo<em>bar</em>baz</strong></p>
      +
      <p><strong>foo<em>bar</em>baz</strong></p>
      -
      ***foo* bar**
      +
      ***foo* bar**
      -
      <p><strong><em>foo</em> bar</strong></p>
      +
      <p><strong><em>foo</em> bar</strong></p>
      -
      **foo *bar***
      +
      **foo *bar***
      -
      <p><strong>foo <em>bar</em></strong></p>
      +
      <p><strong>foo <em>bar</em></strong></p>
      @@ -8814,12 +8814,12 @@ inside strong emphasis:

      -
      **foo *bar **baz**
      +
      **foo *bar **baz**
       bim* bop**
      -
      <p><strong>foo <em>bar <strong>baz</strong>
      +
      <p><strong>foo <em>bar <strong>baz</strong>
       bim</em> bop</strong></p>
      @@ -8827,11 +8827,11 @@ inside strong emphasis:

      -
      **foo [*bar*](/url)**
      +
      **foo [*bar*](/url)**
      -
      <p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
      +
      <p><strong>foo <a href="/url"><em>bar</em></a></strong></p>
      @@ -8839,22 +8839,22 @@ inside strong emphasis:

      -
      __ is not an empty emphasis
      +
      __ is not an empty emphasis
      -
      <p>__ is not an empty emphasis</p>
      +
      <p>__ is not an empty emphasis</p>
      -
      ____ is not an empty strong emphasis
      +
      ____ is not an empty strong emphasis
      -
      <p>____ is not an empty strong emphasis</p>
      +
      <p>____ is not an empty strong emphasis</p>
      @@ -8862,66 +8862,66 @@ inside strong emphasis:

      -
      foo ***
      +
      foo ***
      -
      <p>foo ***</p>
      +
      <p>foo ***</p>
      -
      foo *\**
      +
      foo *\**
      -
      <p>foo <em>*</em></p>
      +
      <p>foo <em>*</em></p>
      -
      foo *_*
      +
      foo *_*
      -
      <p>foo <em>_</em></p>
      +
      <p>foo <em>_</em></p>
      -
      foo *****
      +
      foo *****
      -
      <p>foo *****</p>
      +
      <p>foo *****</p>
      -
      foo **\***
      +
      foo **\***
      -
      <p>foo <strong>*</strong></p>
      +
      <p>foo <strong>*</strong></p>
      -
      foo **_**
      +
      foo **_**
      -
      <p>foo <strong>_</strong></p>
      +
      <p>foo <strong>_</strong></p>
      @@ -8931,66 +8931,66 @@ emphasis, rather than inside it:

      -
      **foo*
      +
      **foo*
      -
      <p>*<em>foo</em></p>
      +
      <p>*<em>foo</em></p>
      -
      *foo**
      +
      *foo**
      -
      <p><em>foo</em>*</p>
      +
      <p><em>foo</em>*</p>
      -
      ***foo**
      +
      ***foo**
      -
      <p>*<strong>foo</strong></p>
      +
      <p>*<strong>foo</strong></p>
      -
      ****foo*
      +
      ****foo*
      -
      <p>***<em>foo</em></p>
      +
      <p>***<em>foo</em></p>
      -
      **foo***
      +
      **foo***
      -
      <p><strong>foo</strong>*</p>
      +
      <p><strong>foo</strong>*</p>
      -
      *foo****
      +
      *foo****
      -
      <p><em>foo</em>***</p>
      +
      <p><em>foo</em>***</p>
      @@ -8998,77 +8998,77 @@ emphasis, rather than inside it:

      -
      foo ___
      +
      foo ___
      -
      <p>foo ___</p>
      +
      <p>foo ___</p>
      -
      foo _\__
      +
      foo _\__
      -
      <p>foo <em>_</em></p>
      +
      <p>foo <em>_</em></p>
      -
      foo _*_
      +
      foo _*_
      -
      <p>foo <em>*</em></p>
      +
      <p>foo <em>*</em></p>
      -
      foo _____
      +
      foo _____
      -
      <p>foo _____</p>
      +
      <p>foo _____</p>
      -
      foo __\___
      +
      foo __\___
      -
      <p>foo <strong>_</strong></p>
      +
      <p>foo <strong>_</strong></p>
      -
      foo __*__
      +
      foo __*__
      -
      <p>foo <strong>*</strong></p>
      +
      <p>foo <strong>*</strong></p>
      -
      __foo_
      +
      __foo_
      -
      <p>_<em>foo</em></p>
      +
      <p>_<em>foo</em></p>
      @@ -9078,55 +9078,55 @@ emphasis, rather than inside it:

      -
      _foo__
      +
      _foo__
      -
      <p><em>foo</em>_</p>
      +
      <p><em>foo</em>_</p>
      -
      ___foo__
      +
      ___foo__
      -
      <p>_<strong>foo</strong></p>
      +
      <p>_<strong>foo</strong></p>
      -
      ____foo_
      +
      ____foo_
      -
      <p>___<em>foo</em></p>
      +
      <p>___<em>foo</em></p>
      -
      __foo___
      +
      __foo___
      -
      <p><strong>foo</strong>_</p>
      +
      <p><strong>foo</strong>_</p>
      -
      _foo____
      +
      _foo____
      -
      <p><em>foo</em>___</p>
      +
      <p><em>foo</em>___</p>
      @@ -9135,44 +9135,44 @@ emphasis, you must use different delimiters:

      -
      **foo**
      +
      **foo**
      -
      <p><strong>foo</strong></p>
      +
      <p><strong>foo</strong></p>
      -
      *_foo_*
      +
      *_foo_*
      -
      <p><em><em>foo</em></em></p>
      +
      <p><em><em>foo</em></em></p>
      -
      __foo__
      +
      __foo__
      -
      <p><strong>foo</strong></p>
      +
      <p><strong>foo</strong></p>
      -
      _*foo*_
      +
      _*foo*_
      -
      <p><em><em>foo</em></em></p>
      +
      <p><em><em>foo</em></em></p>
      @@ -9181,22 +9181,22 @@ switching delimiters:

      -
      ****foo****
      +
      ****foo****
      -
      <p><strong><strong>foo</strong></strong></p>
      +
      <p><strong><strong>foo</strong></strong></p>
      -
      ____foo____
      +
      ____foo____
      -
      <p><strong><strong>foo</strong></strong></p>
      +
      <p><strong><strong>foo</strong></strong></p>
      @@ -9205,11 +9205,11 @@ delimiters:

      -
      ******foo******
      +
      ******foo******
      -
      <p><strong><strong><strong>foo</strong></strong></strong></p>
      +
      <p><strong><strong><strong>foo</strong></strong></strong></p>
      @@ -9217,22 +9217,22 @@ delimiters:

      -
      ***foo***
      +
      ***foo***
      -
      <p><em><strong>foo</strong></em></p>
      +
      <p><em><strong>foo</strong></em></p>
      -
      _____foo_____
      +
      _____foo_____
      -
      <p><em><strong><strong>foo</strong></strong></em></p>
      +
      <p><em><strong><strong>foo</strong></strong></em></p>
      @@ -9240,22 +9240,22 @@ delimiters:

      -
      *foo _bar* baz_
      +
      *foo _bar* baz_
      -
      <p><em>foo _bar</em> baz_</p>
      +
      <p><em>foo _bar</em> baz_</p>
      -
      *foo __bar *baz bim__ bam*
      +
      *foo __bar *baz bim__ bam*
      -
      <p><em>foo <strong>bar *baz bim</strong> bam</em></p>
      +
      <p><em>foo <strong>bar *baz bim</strong> bam</em></p>
      @@ -9263,22 +9263,22 @@ delimiters:

      -
      **foo **bar baz**
      +
      **foo **bar baz**
      -
      <p>**foo <strong>bar baz</strong></p>
      +
      <p>**foo <strong>bar baz</strong></p>
      -
      *foo *bar baz*
      +
      *foo *bar baz*
      -
      <p>*foo <em>bar baz</em></p>
      +
      <p>*foo <em>bar baz</em></p>
      @@ -9286,99 +9286,99 @@ delimiters:

      -
      *[bar*](/url)
      +
      *[bar*](/url)
      -
      <p>*<a href="/url">bar*</a></p>
      +
      <p>*<a href="/url">bar*</a></p>
      -
      _foo [bar_](/url)
      +
      _foo [bar_](/url)
      -
      <p>_foo <a href="/url">bar_</a></p>
      +
      <p>_foo <a href="/url">bar_</a></p>
      -
      *<img src="foo" title="*"/>
      +
      *<img src="foo" title="*"/>
      -
      <p>*<img src="foo" title="*"/></p>
      +
      <p>*<img src="foo" title="*"/></p>
      -
      **<a href="**">
      +
      **<a href="**">
      -
      <p>**<a href="**"></p>
      +
      <p>**<a href="**"></p>
      -
      __<a href="__">
      +
      __<a href="__">
      -
      <p>__<a href="__"></p>
      +
      <p>__<a href="__"></p>
      -
      *a `*`*
      +
      *a `*`*
      -
      <p><em>a <code>*</code></em></p>
      +
      <p><em>a <code>*</code></em></p>
      -
      _a `_`_
      +
      _a `_`_
      -
      <p><em>a <code>_</code></em></p>
      +
      <p><em>a <code>_</code></em></p>
      -
      **a<http://foo.bar/?q=**>
      +
      **a<http://foo.bar/?q=**>
      -
      <p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
      +
      <p>**a<a href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
      -
      __a<http://foo.bar/?q=__>
      +
      __a<http://foo.bar/?q=__>
      -
      <p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
      +
      <p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
      @@ -9391,11 +9391,11 @@ available.

      -
      ~~Hi~~ Hello, world!
      +
      ~~Hi~~ Hello, world!
      -
      <p><del>Hi</del> Hello, world!</p>
      +
      <p><del>Hi</del> Hello, world!</p>
      @@ -9404,13 +9404,13 @@ parsing to cease:

      -
      This ~~has a
      +
      This ~~has a
       
       new paragraph~~.
      -
      <p>This ~~has a</p>
      +
      <p>This ~~has a</p>
       <p>new paragraph~~.</p>
      @@ -9502,11 +9502,11 @@ above.

      -
      [link](/uri "title")
      +
      [link](/uri "title")
      -
      <p><a href="/uri" title="title">link</a></p>
      +
      <p><a href="/uri" title="title">link</a></p>
      @@ -9514,11 +9514,11 @@ above.

      -
      [link](/uri)
      +
      [link](/uri)
      -
      <p><a href="/uri">link</a></p>
      +
      <p><a href="/uri">link</a></p>
      @@ -9526,22 +9526,22 @@ above.

      -
      [link]()
      +
      [link]()
      -
      <p><a href="">link</a></p>
      +
      <p><a href="">link</a></p>
      -
      [link](<>)
      +
      [link](<>)
      -
      <p><a href="">link</a></p>
      +
      <p><a href="">link</a></p>
      @@ -9550,22 +9550,22 @@ enclosed in pointy brackets:

      -
      [link](/my uri)
      +
      [link](/my uri)
      -
      <p>[link](/my uri)</p>
      +
      <p>[link](/my uri)</p>
      -
      [link](</my uri>)
      +
      [link](</my uri>)
      -
      <p><a href="/my%20uri">link</a></p>
      +
      <p><a href="/my%20uri">link</a></p>
      @@ -9574,12 +9574,12 @@ even if enclosed in pointy brackets:

      -
      [link](foo
      +
      [link](foo
       bar)
      -
      <p>[link](foo
      +
      <p>[link](foo
       bar)</p>
      @@ -9587,12 +9587,12 @@ even if enclosed in pointy brackets:

      -
      [link](<foo
      +
      [link](<foo
       bar>)
      -
      <p>[link](<foo
      +
      <p>[link](<foo
       bar>)</p>
      @@ -9602,11 +9602,11 @@ in pointy brackets:

      -
      [a](<b)c>)
      +
      [a](<b)c>)
      -
      <p><a href="b)c">a</a></p>
      +
      <p><a href="b)c">a</a></p>
      @@ -9614,11 +9614,11 @@ in pointy brackets:

      -
      [link](<foo\>)
      +
      [link](<foo\>)
      -
      <p>[link](&lt;foo&gt;)</p>
      +
      <p>[link](&lt;foo&gt;)</p>
      @@ -9627,13 +9627,13 @@ is not matched properly:

      -
      [a](<b)c
      +
      [a](<b)c
       [a](<b)c>
       [a](<b>c)
      -
      <p>[a](&lt;b)c
      +
      <p>[a](&lt;b)c
       [a](&lt;b)c&gt;
       [a](<b>c)</p>
      @@ -9643,11 +9643,11 @@ is not matched properly:

      -
      [link](\(foo\))
      +
      [link](\(foo\))
      -
      <p><a href="(foo)">link</a></p>
      +
      <p><a href="(foo)">link</a></p>
      @@ -9656,11 +9656,11 @@ balanced:

      -
      [link](foo(and(bar)))
      +
      [link](foo(and(bar)))
      -
      <p><a href="foo(and(bar))">link</a></p>
      +
      <p><a href="foo(and(bar))">link</a></p>
      @@ -9669,22 +9669,22 @@ balanced:

      -
      [link](foo\(and\(bar\))
      +
      [link](foo\(and\(bar\))
      -
      <p><a href="foo(and(bar)">link</a></p>
      +
      <p><a href="foo(and(bar)">link</a></p>
      -
      [link](<foo(and(bar)>)
      +
      [link](<foo(and(bar)>)
      -
      <p><a href="foo(and(bar)">link</a></p>
      +
      <p><a href="foo(and(bar)">link</a></p>
      @@ -9693,11 +9693,11 @@ in Markdown:

      -
      [link](foo\)\:)
      +
      [link](foo\)\:)
      -
      <p><a href="foo):">link</a></p>
      +
      <p><a href="foo):">link</a></p>
      @@ -9705,7 +9705,7 @@ in Markdown:

      -
      [link](#fragment)
      +
      [link](#fragment)
       
       [link](http://example.com#fragment)
       
      @@ -9713,7 +9713,7 @@ in Markdown:

      -
      <p><a href="#fragment">link</a></p>
      +
      <p><a href="#fragment">link</a></p>
       <p><a href="http://example.com#fragment">link</a></p>
       <p><a href="http://example.com?foo=3#frag">link</a></p>
      @@ -9724,11 +9724,11 @@ just a backslash:

      -
      [link](foo\bar)
      +
      [link](foo\bar)
      -
      <p><a href="foo%5Cbar">link</a></p>
      +
      <p><a href="foo%5Cbar">link</a></p>
      @@ -9743,11 +9743,11 @@ about how to escape or normalize URLs in the output.

      -
      [link](foo%20b&auml;)
      +
      [link](foo%20b&auml;)
      -
      <p><a href="foo%20b%C3%A4">link</a></p>
      +
      <p><a href="foo%20b%C3%A4">link</a></p>
      @@ -9757,11 +9757,11 @@ get unexpected results:

      -
      [link]("title")
      +
      [link]("title")
      -
      <p><a href="%22title%22">link</a></p>
      +
      <p><a href="%22title%22">link</a></p>
      @@ -9769,13 +9769,13 @@ get unexpected results:

      -
      [link](/url "title")
      +
      [link](/url "title")
       [link](/url 'title')
       [link](/url (title))
      -
      <p><a href="/url" title="title">link</a>
      +
      <p><a href="/url" title="title">link</a>
       <a href="/url" title="title">link</a>
       <a href="/url" title="title">link</a></p>
      @@ -9786,11 +9786,11 @@ may be used in titles:

      -
      [link](/url "title \"&quot;")
      +
      [link](/url "title \"&quot;")
      -
      <p><a href="/url" title="title &quot;&quot;">link</a></p>
      +
      <p><a href="/url" title="title &quot;&quot;">link</a></p>
      @@ -9799,11 +9799,11 @@ Other [Unicode whitespace] like non-breaking space doesn't work.

      -
      [link](/url "title")
      +
      [link](/url "title")
      -
      <p><a href="/url%C2%A0%22title%22">link</a></p>
      +
      <p><a href="/url%C2%A0%22title%22">link</a></p>
      @@ -9811,11 +9811,11 @@ Other [Unicode whitespace] like non-breaking space doesn't work.

      -
      [link](/url "title "and" title")
      +
      [link](/url "title "and" title")
      -
      <p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
      +
      <p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
      @@ -9823,11 +9823,11 @@ Other [Unicode whitespace] like non-breaking space doesn't work.

      -
      [link](/url 'title "and" title')
      +
      [link](/url 'title "and" title')
      -
      <p><a href="/url" title="title &quot;and&quot; title">link</a></p>
      +
      <p><a href="/url" title="title &quot;and&quot; title">link</a></p>
      @@ -9849,12 +9849,12 @@ the same way in inline links and link reference definitions.)

      -
      [link](   /uri
      +
      [link](   /uri
         "title"  )
      -
      <p><a href="/uri" title="title">link</a></p>
      +
      <p><a href="/uri" title="title">link</a></p>
      @@ -9863,11 +9863,11 @@ following parenthesis:

      -
      [link] (/uri)
      +
      [link] (/uri)
      -
      <p>[link] (/uri)</p>
      +
      <p>[link] (/uri)</p>
      @@ -9876,44 +9876,44 @@ unless they are escaped:

      -
      [link [foo [bar]]](/uri)
      +
      [link [foo [bar]]](/uri)
      -
      <p><a href="/uri">link [foo [bar]]</a></p>
      +
      <p><a href="/uri">link [foo [bar]]</a></p>
      -
      [link] bar](/uri)
      +
      [link] bar](/uri)
      -
      <p>[link] bar](/uri)</p>
      +
      <p>[link] bar](/uri)</p>
      -
      [link [bar](/uri)
      +
      [link [bar](/uri)
      -
      <p>[link <a href="/uri">bar</a></p>
      +
      <p>[link <a href="/uri">bar</a></p>
      -
      [link \[bar](/uri)
      +
      [link \[bar](/uri)
      -
      <p><a href="/uri">link [bar</a></p>
      +
      <p><a href="/uri">link [bar</a></p>
      @@ -9921,22 +9921,22 @@ unless they are escaped:

      -
      [link *foo **bar** `#`*](/uri)
      +
      [link *foo **bar** `#`*](/uri)
      -
      <p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
      +
      <p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
      -
      [![moon](moon.jpg)](/uri)
      +
      [![moon](moon.jpg)](/uri)
      -
      <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
      +
      <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
      @@ -9944,33 +9944,33 @@ unless they are escaped:

      -
      [foo [bar](/uri)](/uri)
      +
      [foo [bar](/uri)](/uri)
      -
      <p>[foo <a href="/uri">bar</a>](/uri)</p>
      +
      <p>[foo <a href="/uri">bar</a>](/uri)</p>
      -
      [foo *[bar [baz](/uri)](/uri)*](/uri)
      +
      [foo *[bar [baz](/uri)](/uri)*](/uri)
      -
      <p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
      +
      <p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
      -
      ![[[foo](uri1)](uri2)](uri3)
      +
      ![[[foo](uri1)](uri2)](uri3)
      -
      <p><img src="uri3" alt="[foo](uri2)" /></p>
      +
      <p><img src="uri3" alt="[foo](uri2)" /></p>
      @@ -9979,22 +9979,22 @@ emphasis grouping:

      -
      *[foo*](/uri)
      +
      *[foo*](/uri)
      -
      <p>*<a href="/uri">foo*</a></p>
      +
      <p>*<a href="/uri">foo*</a></p>
      -
      [foo *bar](baz*)
      +
      [foo *bar](baz*)
      -
      <p><a href="baz*">foo *bar</a></p>
      +
      <p><a href="baz*">foo *bar</a></p>
      @@ -10003,11 +10003,11 @@ precedence:

      -
      *foo [bar* baz]
      +
      *foo [bar* baz]
      -
      <p><em>foo [bar</em> baz]</p>
      +
      <p><em>foo [bar</em> baz]</p>
      @@ -10016,33 +10016,33 @@ and autolinks over link grouping:

      -
      [foo <bar attr="](baz)">
      +
      [foo <bar attr="](baz)">
      -
      <p>[foo <bar attr="](baz)"></p>
      +
      <p>[foo <bar attr="](baz)"></p>
      -
      [foo`](/uri)`
      +
      [foo`](/uri)`
      -
      <p>[foo<code>](/uri)</code></p>
      +
      <p>[foo<code>](/uri)</code></p>
      -
      [foo<http://example.com/?search=](uri)>
      +
      [foo<http://example.com/?search=](uri)>
      -
      <p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
      +
      <p>[foo<a href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
      @@ -10074,13 +10074,13 @@ matching [link reference definition].

      -
      [foo][bar]
      +
      [foo][bar]
       
       [bar]: /url "title"
      -
      <p><a href="/url" title="title">foo</a></p>
      +
      <p><a href="/url" title="title">foo</a></p>
      @@ -10091,26 +10091,26 @@ unless they are escaped:

      -
      [link [foo [bar]]][ref]
      +
      [link [foo [bar]]][ref]
       
       [ref]: /uri
      -
      <p><a href="/uri">link [foo [bar]]</a></p>
      +
      <p><a href="/uri">link [foo [bar]]</a></p>
      -
      [link \[bar][ref]
      +
      [link \[bar][ref]
       
       [ref]: /uri
      -
      <p><a href="/uri">link [bar</a></p>
      +
      <p><a href="/uri">link [bar</a></p>
      @@ -10118,26 +10118,26 @@ unless they are escaped:

      -
      [link *foo **bar** `#`*][ref]
      +
      [link *foo **bar** `#`*][ref]
       
       [ref]: /uri
      -
      <p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
      +
      <p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
      -
      [![moon](moon.jpg)][ref]
      +
      [![moon](moon.jpg)][ref]
       
       [ref]: /uri
      -
      <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
      +
      <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
      @@ -10145,26 +10145,26 @@ unless they are escaped:

      -
      [foo [bar](/uri)][ref]
      +
      [foo [bar](/uri)][ref]
       
       [ref]: /uri
      -
      <p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
      +
      <p>[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
      -
      [foo *bar [baz][ref]*][ref]
      +
      [foo *bar [baz][ref]*][ref]
       
       [ref]: /uri
      -
      <p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
      +
      <p>[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
      @@ -10175,26 +10175,26 @@ emphasis grouping:

      -
      *[foo*][ref]
      +
      *[foo*][ref]
       
       [ref]: /uri
      -
      <p>*<a href="/uri">foo*</a></p>
      +
      <p>*<a href="/uri">foo*</a></p>
      -
      [foo *bar][ref]
      +
      [foo *bar][ref]
       
       [ref]: /uri
      -
      <p><a href="/uri">foo *bar</a></p>
      +
      <p><a href="/uri">foo *bar</a></p>
      @@ -10203,39 +10203,39 @@ and autolinks over link grouping:

      -
      [foo <bar attr="][ref]">
      +
      [foo <bar attr="][ref]">
       
       [ref]: /uri
      -
      <p>[foo <bar attr="][ref]"></p>
      +
      <p>[foo <bar attr="][ref]"></p>
      -
      [foo`][ref]`
      +
      [foo`][ref]`
       
       [ref]: /uri
      -
      <p>[foo<code>][ref]</code></p>
      +
      <p>[foo<code>][ref]</code></p>
      -
      [foo<http://example.com/?search=][ref]>
      +
      [foo<http://example.com/?search=][ref]>
       
       [ref]: /uri
      -
      <p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
      +
      <p>[foo<a href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
      @@ -10243,13 +10243,13 @@ and autolinks over link grouping:

      -
      [foo][BaR]
      +
      [foo][BaR]
       
       [bar]: /url "title"
      -
      <p><a href="/url" title="title">foo</a></p>
      +
      <p><a href="/url" title="title">foo</a></p>
      @@ -10257,13 +10257,13 @@ and autolinks over link grouping:

      -
      [Толпой][Толпой] is a Russian word.
      +
      [Толпой][Толпой] is a Russian word.
       
       [ТОЛПОЙ]: /url
      -
      <p><a href="/url">Толпой</a> is a Russian word.</p>
      +
      <p><a href="/url">Толпой</a> is a Russian word.</p>
      @@ -10272,14 +10272,14 @@ purposes of determining matching:

      -
      [Foo
      +
      [Foo
         bar]: /url
       
       [Baz][Foo bar]
      -
      <p><a href="/url">Baz</a></p>
      +
      <p><a href="/url">Baz</a></p>
      @@ -10288,27 +10288,27 @@ purposes of determining matching:

      -
      [foo] [bar]
      +
      [foo] [bar]
       
       [bar]: /url "title"
      -
      <p>[foo] <a href="/url" title="title">bar</a></p>
      +
      <p>[foo] <a href="/url" title="title">bar</a></p>
      -
      [foo]
      +
      [foo]
       [bar]
       
       [bar]: /url "title"
      -
      <p>[foo]
      +
      <p>[foo]
       <a href="/url" title="title">bar</a></p>
      @@ -10324,7 +10324,7 @@ link text and the link label, then in the following we will have a single reference link, not two shortcut reference links, as intended:

      -
      [foo]
      +
      [foo]
       [bar]
       
       [foo]: /url1
      @@ -10343,7 +10343,7 @@ the first is used:

      -
      [foo]: /url1
      +
      [foo]: /url1
       
       [foo]: /url2
       
      @@ -10351,7 +10351,7 @@ the first is used:

      -
      <p><a href="/url1">bar</a></p>
      +
      <p><a href="/url1">bar</a></p>
      @@ -10361,13 +10361,13 @@ labels define equivalent inline content:

      -
      [bar][foo\!]
      +
      [bar][foo\!]
       
       [foo!]: /url
      -
      <p>[bar][foo!]</p>
      +
      <p>[bar][foo!]</p>
      @@ -10376,13 +10376,13 @@ backslash-escaped:

      -
      [foo][ref[]
      +
      [foo][ref[]
       
       [ref[]: /uri
      -
      <p>[foo][ref[]</p>
      +
      <p>[foo][ref[]</p>
       <p>[ref[]: /uri</p>
      @@ -10390,13 +10390,13 @@ backslash-escaped:

      -
      [foo][ref[bar]]
      +
      [foo][ref[bar]]
       
       [ref[bar]]: /uri
      -
      <p>[foo][ref[bar]]</p>
      +
      <p>[foo][ref[bar]]</p>
       <p>[ref[bar]]: /uri</p>
      @@ -10404,13 +10404,13 @@ backslash-escaped:

      -
      [[[foo]]]
      +
      [[[foo]]]
       
       [[[foo]]]: /url
      -
      <p>[[[foo]]]</p>
      +
      <p>[[[foo]]]</p>
       <p>[[[foo]]]: /url</p>
      @@ -10418,13 +10418,13 @@ backslash-escaped:

      -
      [foo][ref\[]
      +
      [foo][ref\[]
       
       [ref\[]: /uri
      -
      <p><a href="/uri">foo</a></p>
      +
      <p><a href="/uri">foo</a></p>
      @@ -10432,13 +10432,13 @@ backslash-escaped:

      -
      [bar\\]: /uri
      +
      [bar\\]: /uri
       
       [bar\\]
      -
      <p><a href="/uri">bar\</a></p>
      +
      <p><a href="/uri">bar\</a></p>
      @@ -10446,13 +10446,13 @@ backslash-escaped:

      -
      []
      +
      []
       
       []: /uri
      -
      <p>[]</p>
      +
      <p>[]</p>
       <p>[]: /uri</p>
      @@ -10460,7 +10460,7 @@ backslash-escaped:

      -
      [
      +
      [
        ]
       
       [
      @@ -10468,7 +10468,7 @@ backslash-escaped:

      -
      <p>[
      +
      <p>[
       ]</p>
       <p>[
       ]: /uri</p>
      @@ -10486,26 +10486,26 @@ provided by the matching reference link definition. Thus,
      -
      [foo][]
      +
      [foo][]
       
       [foo]: /url "title"
      -
      <p><a href="/url" title="title">foo</a></p>
      +
      <p><a href="/url" title="title">foo</a></p>
      -
      [*foo* bar][]
      +
      [*foo* bar][]
       
       [*foo* bar]: /url "title"
      -
      <p><a href="/url" title="title"><em>foo</em> bar</a></p>
      +
      <p><a href="/url" title="title"><em>foo</em> bar</a></p>
      @@ -10513,13 +10513,13 @@ provided by the matching reference link definition. Thus,
      -
      [Foo][]
      +
      [Foo][]
       
       [foo]: /url "title"
      -
      <p><a href="/url" title="title">Foo</a></p>
      +
      <p><a href="/url" title="title">Foo</a></p>
      @@ -10528,14 +10528,14 @@ allowed between the two sets of brackets:

      -
      [foo] 
      +
      [foo] 
       []
       
       [foo]: /url "title"
      -
      <p><a href="/url" title="title">foo</a>
      +
      <p><a href="/url" title="title">foo</a>
       []</p>
      @@ -10551,52 +10551,52 @@ Thus, [foo] is equivalent to
      -
      [foo]
      +
      [foo]
       
       [foo]: /url "title"
      -
      <p><a href="/url" title="title">foo</a></p>
      +
      <p><a href="/url" title="title">foo</a></p>
      -
      [*foo* bar]
      +
      [*foo* bar]
       
       [*foo* bar]: /url "title"
      -
      <p><a href="/url" title="title"><em>foo</em> bar</a></p>
      +
      <p><a href="/url" title="title"><em>foo</em> bar</a></p>
      -
      [[*foo* bar]]
      +
      [[*foo* bar]]
       
       [*foo* bar]: /url "title"
      -
      <p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
      +
      <p>[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
      -
      [[bar [foo]
      +
      [[bar [foo]
       
       [foo]: /url
      -
      <p>[[bar <a href="/url">foo</a></p>
      +
      <p>[[bar <a href="/url">foo</a></p>
      @@ -10604,13 +10604,13 @@ Thus, [foo] is equivalent to
      -
      [Foo]
      +
      [Foo]
       
       [foo]: /url "title"
      -
      <p><a href="/url" title="title">Foo</a></p>
      +
      <p><a href="/url" title="title">Foo</a></p>
      @@ -10618,13 +10618,13 @@ Thus, [foo] is equivalent to
      -
      [foo] bar
      +
      [foo] bar
       
       [foo]: /url
      -
      <p><a href="/url">foo</a> bar</p>
      +
      <p><a href="/url">foo</a> bar</p>
      @@ -10633,13 +10633,13 @@ opening bracket to avoid links:

      -
      \[foo]
      +
      \[foo]
       
       [foo]: /url "title"
      -
      <p>[foo]</p>
      +
      <p>[foo]</p>
      @@ -10648,13 +10648,13 @@ following closing bracket:

      -
      [foo*]: /url
      +
      [foo*]: /url
       
       *[foo*]
      -
      <p>*<a href="/url">foo*</a></p>
      +
      <p>*<a href="/url">foo*</a></p>
      @@ -10663,27 +10663,27 @@ references:

      -
      [foo][bar]
      +
      [foo][bar]
       
       [foo]: /url1
       [bar]: /url2
      -
      <p><a href="/url2">foo</a></p>
      +
      <p><a href="/url2">foo</a></p>
      -
      [foo][]
      +
      [foo][]
       
       [foo]: /url1
      -
      <p><a href="/url1">foo</a></p>
      +
      <p><a href="/url1">foo</a></p>
      @@ -10691,26 +10691,26 @@ references:

      -
      [foo]()
      +
      [foo]()
       
       [foo]: /url1
      -
      <p><a href="">foo</a></p>
      +
      <p><a href="">foo</a></p>
      -
      [foo](not a link)
      +
      [foo](not a link)
       
       [foo]: /url1
      -
      <p><a href="/url1">foo</a>(not a link)</p>
      +
      <p><a href="/url1">foo</a>(not a link)</p>
      @@ -10719,13 +10719,13 @@ references:

      -
      [foo][bar][baz]
      +
      [foo][bar][baz]
       
       [baz]: /url
      -
      <p>[foo]<a href="/url">bar</a></p>
      +
      <p>[foo]<a href="/url">bar</a></p>
      @@ -10734,14 +10734,14 @@ references:

      -
      [foo][bar][baz]
      +
      [foo][bar][baz]
       
       [baz]: /url1
       [bar]: /url2
      -
      <p><a href="/url2">foo</a><a href="/url1">baz</a></p>
      +
      <p><a href="/url2">foo</a><a href="/url1">baz</a></p>
      @@ -10750,14 +10750,14 @@ is followed by a link label (even though Example 579
      -
      [foo][bar][baz]
      +
      [foo][bar][baz]
       
       [baz]: /url1
       [foo]: /url2
      -
      <p>[foo]<a href="/url1">bar</a></p>
      +
      <p>[foo]<a href="/url1">bar</a></p>
      @@ -10775,46 +10775,46 @@ this is standardly used as the image's
      -
      ![foo](/url "title")
      +
      ![foo](/url "title")
      -
      <p><img src="/url" alt="foo" title="title" /></p>
      +
      <p><img src="/url" alt="foo" title="title" /></p>
      -
      ![foo *bar*]
      +
      ![foo *bar*]
       
       [foo *bar*]: train.jpg "train & tracks"
      -
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      +
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      -
      ![foo ![bar](/url)](/url2)
      +
      ![foo ![bar](/url)](/url2)
      -
      <p><img src="/url2" alt="foo bar" /></p>
      +
      <p><img src="/url2" alt="foo bar" /></p>
      -
      ![foo [bar](/url)](/url2)
      +
      ![foo [bar](/url)](/url2)
      -
      <p><img src="/url2" alt="foo bar" /></p>
      +
      <p><img src="/url2" alt="foo bar" /></p>
      @@ -10826,70 +10826,70 @@ content is rendered, without formatting.

      -
      ![foo *bar*][]
      +
      ![foo *bar*][]
       
       [foo *bar*]: train.jpg "train & tracks"
      -
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      +
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      -
      ![foo *bar*][foobar]
      +
      ![foo *bar*][foobar]
       
       [FOOBAR]: train.jpg "train & tracks"
      -
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      +
      <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
      -
      ![foo](train.jpg)
      +
      ![foo](train.jpg)
      -
      <p><img src="train.jpg" alt="foo" /></p>
      +
      <p><img src="train.jpg" alt="foo" /></p>
      -
      My ![foo bar](/path/to/train.jpg  "title"   )
      +
      My ![foo bar](/path/to/train.jpg  "title"   )
      -
      <p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
      +
      <p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
      -
      ![foo](<url>)
      +
      ![foo](<url>)
      -
      <p><img src="url" alt="foo" /></p>
      +
      <p><img src="url" alt="foo" /></p>
      -
      ![](/url)
      +
      ![](/url)
      -
      <p><img src="/url" alt="" /></p>
      +
      <p><img src="/url" alt="" /></p>
      @@ -10897,26 +10897,26 @@ content is rendered, without formatting.

      -
      ![foo][bar]
      +
      ![foo][bar]
       
       [bar]: /url
      -
      <p><img src="/url" alt="foo" /></p>
      +
      <p><img src="/url" alt="foo" /></p>
      -
      ![foo][bar]
      +
      ![foo][bar]
       
       [BAR]: /url
      -
      <p><img src="/url" alt="foo" /></p>
      +
      <p><img src="/url" alt="foo" /></p>
      @@ -10924,26 +10924,26 @@ content is rendered, without formatting.

      -
      ![foo][]
      +
      ![foo][]
       
       [foo]: /url "title"
      -
      <p><img src="/url" alt="foo" title="title" /></p>
      +
      <p><img src="/url" alt="foo" title="title" /></p>
      -
      ![*foo* bar][]
      +
      ![*foo* bar][]
       
       [*foo* bar]: /url "title"
      -
      <p><img src="/url" alt="foo bar" title="title" /></p>
      +
      <p><img src="/url" alt="foo bar" title="title" /></p>
      @@ -10951,13 +10951,13 @@ content is rendered, without formatting.

      -
      ![Foo][]
      +
      ![Foo][]
       
       [foo]: /url "title"
      -
      <p><img src="/url" alt="Foo" title="title" /></p>
      +
      <p><img src="/url" alt="Foo" title="title" /></p>
      @@ -10966,14 +10966,14 @@ between the two sets of brackets:

      -
      ![foo] 
      +
      ![foo] 
       []
       
       [foo]: /url "title"
      -
      <p><img src="/url" alt="foo" title="title" />
      +
      <p><img src="/url" alt="foo" title="title" />
       []</p>
      @@ -10982,26 +10982,26 @@ between the two sets of brackets:

      -
      ![foo]
      +
      ![foo]
       
       [foo]: /url "title"
      -
      <p><img src="/url" alt="foo" title="title" /></p>
      +
      <p><img src="/url" alt="foo" title="title" /></p>
      -
      ![*foo* bar]
      +
      ![*foo* bar]
       
       [*foo* bar]: /url "title"
      -
      <p><img src="/url" alt="foo bar" title="title" /></p>
      +
      <p><img src="/url" alt="foo bar" title="title" /></p>
      @@ -11009,13 +11009,13 @@ between the two sets of brackets:

      -
      ![[foo]]
      +
      ![[foo]]
       
       [[foo]]: /url "title"
      -
      <p>![[foo]]</p>
      +
      <p>![[foo]]</p>
       <p>[[foo]]: /url &quot;title&quot;</p>
      @@ -11024,13 +11024,13 @@ between the two sets of brackets:

      -
      ![Foo]
      +
      ![Foo]
       
       [foo]: /url "title"
      -
      <p><img src="/url" alt="Foo" title="title" /></p>
      +
      <p><img src="/url" alt="Foo" title="title" /></p>
      @@ -11039,13 +11039,13 @@ backslash-escape the opening [:<
      -
      !\[foo]
      +
      !\[foo]
       
       [foo]: /url "title"
      -
      <p>![foo]</p>
      +
      <p>![foo]</p>
      @@ -11054,13 +11054,13 @@ backslash-escape the opening [:<
      -
      \![foo]
      +
      \![foo]
       
       [foo]: /url "title"
      -
      <p>!<a href="/url" title="title">foo</a></p>
      +
      <p>!<a href="/url" title="title">foo</a></p>
      @@ -11086,33 +11086,33 @@ by any combination of ASCII letters, digits, or the symbols plus
      -
      <http://foo.bar.baz>
      +
      <http://foo.bar.baz>
      -
      <p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
      +
      <p><a href="http://foo.bar.baz">http://foo.bar.baz</a></p>
      -
      <http://foo.bar.baz/test?q=hello&id=22&boolean>
      +
      <http://foo.bar.baz/test?q=hello&id=22&boolean>
      -
      <p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
      +
      <p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
      -
      <irc://foo.bar:2233/baz>
      +
      <irc://foo.bar:2233/baz>
      -
      <p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
      +
      <p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
      @@ -11120,11 +11120,11 @@ by any combination of ASCII letters, digits, or the symbols plus
      -
      <MAILTO:FOO@BAR.BAZ>
      +
      <MAILTO:FOO@BAR.BAZ>
      -
      <p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
      +
      <p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
      @@ -11135,44 +11135,44 @@ with their syntax:

      -
      <a+b+c:d>
      +
      <a+b+c:d>
      -
      <p><a href="a+b+c:d">a+b+c:d</a></p>
      +
      <p><a href="a+b+c:d">a+b+c:d</a></p>
      -
      <made-up-scheme://foo,bar>
      +
      <made-up-scheme://foo,bar>
      -
      <p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
      +
      <p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
      -
      <http://../>
      +
      <http://../>
      -
      <p><a href="http://../">http://../</a></p>
      +
      <p><a href="http://../">http://../</a></p>
      -
      <localhost:5001/foo>
      +
      <localhost:5001/foo>
      -
      <p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
      +
      <p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
      @@ -11180,11 +11180,11 @@ with their syntax:

      -
      <http://foo.bar/baz bim>
      +
      <http://foo.bar/baz bim>
      -
      <p>&lt;http://foo.bar/baz bim&gt;</p>
      +
      <p>&lt;http://foo.bar/baz bim&gt;</p>
      @@ -11192,11 +11192,11 @@ with their syntax:

      -
      <http://example.com/\[\>
      +
      <http://example.com/\[\>
      -
      <p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
      +
      <p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
      @@ -11209,7 +11209,7 @@ for these purposes, is anything that matches the non-normative regex from the HTML5 spec:

      -
      /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
      +
      /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
       (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
      @@ -11217,22 +11217,22 @@ spec:

      -
      <foo@bar.example.com>
      +
      <foo@bar.example.com>
      -
      <p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
      +
      <p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
      -
      <foo+special@Bar.baz-bar0.com>
      +
      <foo+special@Bar.baz-bar0.com>
      -
      <p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
      +
      <p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
      @@ -11240,11 +11240,11 @@ spec:

      -
      <foo\+@bar.example.com>
      +
      <foo\+@bar.example.com>
      -
      <p>&lt;foo+@bar.example.com&gt;</p>
      +
      <p>&lt;foo+@bar.example.com&gt;</p>
      @@ -11252,66 +11252,66 @@ spec:

      -
      <>
      +
      <>
      -
      <p>&lt;&gt;</p>
      +
      <p>&lt;&gt;</p>
      -
      < http://foo.bar >
      +
      < http://foo.bar >
      -
      <p>&lt; http://foo.bar &gt;</p>
      +
      <p>&lt; http://foo.bar &gt;</p>
      -
      <m:abc>
      +
      <m:abc>
      -
      <p>&lt;m:abc&gt;</p>
      +
      <p>&lt;m:abc&gt;</p>
      -
      <foo.bar.baz>
      +
      <foo.bar.baz>
      -
      <p>&lt;foo.bar.baz&gt;</p>
      +
      <p>&lt;foo.bar.baz&gt;</p>
      -
      http://example.com
      +
      http://example.com
      -
      <p>http://example.com</p>
      +
      <p>http://example.com</p>
      -
      foo@bar.example.com
      +
      foo@bar.example.com
      -
      <p>foo@bar.example.com</p>
      +
      <p>foo@bar.example.com</p>
      @@ -11336,11 +11336,11 @@ and no underscores may be present in the last two segments of the domain.

      -
      www.commonmark.org
      +
      www.commonmark.org
      -
      <p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
      +
      <p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
      @@ -11348,11 +11348,11 @@ and no underscores may be present in the last two segments of the domain.

      -
      Visit www.commonmark.org/help for more information.
      +
      Visit www.commonmark.org/help for more information.
      -
      <p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
      +
      <p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
      @@ -11363,13 +11363,13 @@ interior of the link:

      -
      Visit www.commonmark.org.
      +
      Visit www.commonmark.org.
       
       Visit www.commonmark.org/a.b.
      -
      <p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
      +
      <p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
       <p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
      @@ -11381,7 +11381,7 @@ autolink, in order to facilitate including an autolink inside a parenthesis:

      -
      www.google.com/search?q=Markup+(business)
      +
      www.google.com/search?q=Markup+(business)
       
       www.google.com/search?q=Markup+(business)))
       
      @@ -11391,7 +11391,7 @@ autolink, in order to facilitate including an autolink inside a parenthesis:

      -
      <p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
      +
      <p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
       <p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
       <p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
       <p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
      @@ -11404,11 +11404,11 @@ applied:

      -
      www.google.com/search?q=(business))+ok
      +
      www.google.com/search?q=(business))+ok
      -
      <p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
      +
      <p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
      @@ -11419,13 +11419,13 @@ the autolink:

      -
      www.google.com/search?q=commonmark&hl=en
      +
      www.google.com/search?q=commonmark&hl=en
       
       www.google.com/search?q=commonmark&hl;
      -
      <p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
      +
      <p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
       <p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
      @@ -11434,11 +11434,11 @@ the autolink:

      -
      www.commonmark.org/he<lp
      +
      www.commonmark.org/he<lp
      -
      <p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
      +
      <p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
      @@ -11449,7 +11449,7 @@ more non-space non-< characte
      -
      http://commonmark.org
      +
      http://commonmark.org
       
       (Visit https://encrypted.google.com/search?q=Markup+(business))
       
      @@ -11457,7 +11457,7 @@ more non-space non-< characte
       
       
      -
      <p><a href="http://commonmark.org">http://commonmark.org</a></p>
      +
      <p><a href="http://commonmark.org">http://commonmark.org</a></p>
       <p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
       <p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
      @@ -11478,11 +11478,11 @@ The last character must not be one of -
      -
      foo@bar.baz
      +
      foo@bar.baz
      -
      <p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
      +
      <p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
      @@ -11490,11 +11490,11 @@ The last character must not be one of -
      -
      hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
      +
      hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
      -
      <p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
      +
      <p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
      @@ -11504,7 +11504,7 @@ the address:

      -
      a.b-c_d@a.b
      +
      a.b-c_d@a.b
       
       a.b-c_d@a.b.
       
      @@ -11514,7 +11514,7 @@ the address:

      -
      <p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
      +
      <p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
       <p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
       <p>a.b-c_d@a.b-</p>
       <p>a.b-c_d@a.b_</p>
      @@ -11582,11 +11582,11 @@ or a [CDATA section].

      -
      <a><bab><c2c>
      +
      <a><bab><c2c>
      -
      <p><a><bab><c2c></p>
      +
      <p><a><bab><c2c></p>
      @@ -11594,11 +11594,11 @@ or a [CDATA section].

      -
      <a/><b2/>
      +
      <a/><b2/>
      -
      <p><a/><b2/></p>
      +
      <p><a/><b2/></p>
      @@ -11606,12 +11606,12 @@ or a [CDATA section].

      -
      <a  /><b2
      +
      <a  /><b2
       data="foo" >
      -
      <p><a  /><b2
      +
      <p><a  /><b2
       data="foo" ></p>
      @@ -11620,12 +11620,12 @@ or a [CDATA section].

      -
      <a foo="bar" bam = 'baz <em>"</em>'
      +
      <a foo="bar" bam = 'baz <em>"</em>'
       _boolean zoop:33=zoop:33 />
      -
      <p><a foo="bar" bam = 'baz <em>"</em>'
      +
      <p><a foo="bar" bam = 'baz <em>"</em>'
       _boolean zoop:33=zoop:33 /></p>
      @@ -11634,11 +11634,11 @@ or a [CDATA section].

      -
      Foo <responsive-image src="foo.jpg" />
      +
      Foo <responsive-image src="foo.jpg" />
      -
      <p>Foo <responsive-image src="foo.jpg" /></p>
      +
      <p>Foo <responsive-image src="foo.jpg" /></p>
      @@ -11646,11 +11646,11 @@ or a [CDATA section].

      -
      <33> <__>
      +
      <33> <__>
      -
      <p>&lt;33&gt; &lt;__&gt;</p>
      +
      <p>&lt;33&gt; &lt;__&gt;</p>
      @@ -11658,11 +11658,11 @@ or a [CDATA section].

      -
      <a h*#ref="hi">
      +
      <a h*#ref="hi">
      -
      <p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
      +
      <p>&lt;a h*#ref=&quot;hi&quot;&gt;</p>
      @@ -11670,11 +11670,11 @@ or a [CDATA section].

      -
      <a href="hi'> <a href=hi'>
      +
      <a href="hi'> <a href=hi'>
      -
      <p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
      +
      <p>&lt;a href=&quot;hi'&gt; &lt;a href=hi'&gt;</p>
      @@ -11682,14 +11682,14 @@ or a [CDATA section].

      -
      < a><
      +
      < a><
       foo><bar/ >
       <foo bar=baz
       bim!bop />
      -
      <p>&lt; a&gt;&lt;
      +
      <p>&lt; a&gt;&lt;
       foo&gt;&lt;bar/ &gt;
       &lt;foo bar=baz
       bim!bop /&gt;</p>
      @@ -11700,11 +11700,11 @@ or a [CDATA section].

      -
      <a href='bar'title=title>
      +
      <a href='bar'title=title>
      -
      <p>&lt;a href='bar'title=title&gt;</p>
      +
      <p>&lt;a href='bar'title=title&gt;</p>
      @@ -11712,11 +11712,11 @@ or a [CDATA section].

      -
      </a></foo >
      +
      </a></foo >
      -
      <p></a></foo ></p>
      +
      <p></a></foo ></p>
      @@ -11724,11 +11724,11 @@ or a [CDATA section].

      -
      </a href="foo">
      +
      </a href="foo">
      -
      <p>&lt;/a href=&quot;foo&quot;&gt;</p>
      +
      <p>&lt;/a href=&quot;foo&quot;&gt;</p>
      @@ -11736,12 +11736,12 @@ or a [CDATA section].

      -
      foo <!-- this is a
      +
      foo <!-- this is a
       comment - with hyphen -->
      -
      <p>foo <!-- this is a
      +
      <p>foo <!-- this is a
       comment - with hyphen --></p>
      @@ -11749,11 +11749,11 @@ or a [CDATA section].

      -
      foo <!-- not a comment -- two hyphens -->
      +
      foo <!-- not a comment -- two hyphens -->
      -
      <p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
      +
      <p>foo &lt;!-- not a comment -- two hyphens --&gt;</p>
      @@ -11761,13 +11761,13 @@ or a [CDATA section].

      -
      foo <!--> foo -->
      +
      foo <!--> foo -->
       
       foo <!-- foo--->
      -
      <p>foo &lt;!--&gt; foo --&gt;</p>
      +
      <p>foo &lt;!--&gt; foo --&gt;</p>
       <p>foo &lt;!-- foo---&gt;</p>
      @@ -11776,11 +11776,11 @@ or a [CDATA section].

      -
      foo <?php echo $a; ?>
      +
      foo <?php echo $a; ?>
      -
      <p>foo <?php echo $a; ?></p>
      +
      <p>foo <?php echo $a; ?></p>
      @@ -11788,11 +11788,11 @@ or a [CDATA section].

      -
      foo <!ELEMENT br EMPTY>
      +
      foo <!ELEMENT br EMPTY>
      -
      <p>foo <!ELEMENT br EMPTY></p>
      +
      <p>foo <!ELEMENT br EMPTY></p>
      @@ -11800,11 +11800,11 @@ or a [CDATA section].

      -
      foo <![CDATA[>&<]]>
      +
      foo <![CDATA[>&<]]>
      -
      <p>foo <![CDATA[>&<]]></p>
      +
      <p>foo <![CDATA[>&<]]></p>
      @@ -11813,11 +11813,11 @@ attributes:

      -
      foo <a href="&ouml;">
      +
      foo <a href="&ouml;">
      -
      <p>foo <a href="&ouml;"></p>
      +
      <p>foo <a href="&ouml;"></p>
      @@ -11825,22 +11825,22 @@ attributes:

      -
      foo <a href="\*">
      +
      foo <a href="\*">
      -
      <p>foo <a href="\*"></p>
      +
      <p>foo <a href="\*"></p>
      -
      <a href="\"">
      +
      <a href="\"">
      -
      <p>&lt;a href=&quot;&quot;&quot;&gt;</p>
      +
      <p>&lt;a href=&quot;&quot;&quot;&gt;</p>
      @@ -11868,7 +11868,7 @@ usually undesireable in the context of other rendered Markdown content.

      -
      <strong> <title> <style> <em>
      +
      <strong> <title> <style> <em>
       
       <blockquote>
         <xmp> is disallowed.  <XMP> is also disallowed.
      @@ -11876,7 +11876,7 @@ usually undesireable in the context of other rendered Markdown content.

      -
      <p><strong> &lt;title> &lt;style> <em></p>
      +
      <p><strong> &lt;title> &lt;style> <em></p>
       <blockquote>
         &lt;xmp> is disallowed.  &lt;XMP> is also disallowed.
       </blockquote>
      @@ -11893,12 +11893,12 @@ in HTML as a <br /> tag):<
      -
      foo  
      +
      foo  
       baz
      -
      <p>foo<br />
      +
      <p>foo<br />
       baz</p>
      @@ -11908,12 +11908,12 @@ in HTML as a <br /> tag):<
      -
      foo\
      +
      foo\
       baz
      -
      <p>foo<br />
      +
      <p>foo<br />
       baz</p>
      @@ -11922,12 +11922,12 @@ in HTML as a <br /> tag):<
      -
      foo       
      +
      foo       
       baz
      -
      <p>foo<br />
      +
      <p>foo<br />
       baz</p>
      @@ -11936,12 +11936,12 @@ in HTML as a <br /> tag):<
      -
      foo  
      +
      foo  
            bar
      -
      <p>foo<br />
      +
      <p>foo<br />
       bar</p>
      @@ -11949,12 +11949,12 @@ in HTML as a <br /> tag):<
      -
      foo\
      +
      foo\
            bar
      -
      <p>foo<br />
      +
      <p>foo<br />
       bar</p>
      @@ -11964,12 +11964,12 @@ that allow inline content:

      -
      *foo  
      +
      *foo  
       bar*
      -
      <p><em>foo<br />
      +
      <p><em>foo<br />
       bar</em></p>
      @@ -11977,12 +11977,12 @@ that allow inline content:

      -
      *foo\
      +
      *foo\
       bar*
      -
      <p><em>foo<br />
      +
      <p><em>foo<br />
       bar</em></p>
      @@ -11991,24 +11991,24 @@ that allow inline content:

      -
      `code  
      +
      `code  
       span`
      -
      <p><code>code   span</code></p>
      +
      <p><code>code   span</code></p>
      -
      `code\
      +
      `code\
       span`
      -
      <p><code>code\ span</code></p>
      +
      <p><code>code\ span</code></p>
      @@ -12016,12 +12016,12 @@ that allow inline content:

      -
      <a href="foo  
      +
      <a href="foo  
       bar">
      -
      <p><a href="foo  
      +
      <p><a href="foo  
       bar"></p>
      @@ -12029,12 +12029,12 @@ that allow inline content:

      -
      <a href="foo\
      +
      <a href="foo\
       bar">
      -
      <p><a href="foo\
      +
      <p><a href="foo\
       bar"></p>
      @@ -12045,44 +12045,44 @@ other block element:

      -
      foo\
      +
      foo\
      -
      <p>foo\</p>
      +
      <p>foo\</p>
      -
      foo  
      +
      foo  
      -
      <p>foo</p>
      +
      <p>foo</p>
      -
      ### foo\
      +
      ### foo\
      -
      <h3>foo\</h3>
      +
      <h3>foo\</h3>
      -
      ### foo  
      +
      ### foo  
      -
      <h3>foo</h3>
      +
      <h3>foo</h3>
      @@ -12096,12 +12096,12 @@ browsers. In the examples here, a [line ending] will be used.)

      -
      foo
      +
      foo
       baz
      -
      <p>foo
      +
      <p>foo
       baz</p>
      @@ -12111,12 +12111,12 @@ removed:

      -
      foo 
      +
      foo 
        baz
      -
      <p>foo
      +
      <p>foo
       baz</p>
      @@ -12132,22 +12132,22 @@ be parsed as plain textual content.

      -
      hello $.;'there
      +
      hello $.;'there
      -
      <p>hello $.;'there</p>
      +
      <p>hello $.;'there</p>
      -
      Foo χρῆν
      +
      Foo χρῆν
      -
      <p>Foo χρῆν</p>
      +
      <p>Foo χρῆν</p>
      @@ -12155,11 +12155,11 @@ be parsed as plain textual content.

      -
      Multiple     spaces
      +
      Multiple     spaces
      -
      <p>Multiple     spaces</p>
      +
      <p>Multiple     spaces</p>
      @@ -12184,11 +12184,11 @@ GitLab Flavored Markdown specification.

      -
      - [ ] incomplete
      +
      - [ ] incomplete
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" disabled/>
      @@ -12202,11 +12202,11 @@ GitLab Flavored Markdown specification.

      -
      - [x] completed
      +
      - [x] completed
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" checked disabled/>
      @@ -12220,11 +12220,11 @@ GitLab Flavored Markdown specification.

      -
      - [~] inapplicable
      +
      - [~] inapplicable
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" data-inapplicable disabled>
      @@ -12241,13 +12241,13 @@ loose text; it has strikethrough applied with CSS.

      -
      - [~] inapplicable
      +
      - [~] inapplicable
       
         text in loose list
      -
      <ul>
      +
      <ul>
       <li>
       <p>
       <task-button/>
      @@ -12274,13 +12274,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      ---
      +
      ---
       title: YAML front matter
       ---
      -
      <pre>
      +
      <pre>
       <code>
       title: YAML front matter
       </code>
      @@ -12292,13 +12292,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      +++
      +
      +++
       title: TOML front matter
       +++
      -
      <pre>
      +
      <pre>
       <code>
       title: TOML front matter
       </code>
      @@ -12310,7 +12310,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      ;;;
      +
      ;;;
       {
         "title": "JSON front matter"
       }
      @@ -12318,7 +12318,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
       
      -
      <pre>
      +
      <pre>
       <code>
       {
         "title": "JSON front matter"
      @@ -12332,7 +12332,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      text
      +
      text
       
       ---
       title: YAML front matter
      @@ -12340,7 +12340,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
       
      -
      <p>text</p>
      +
      <p>text</p>
       <hr>
       <h2>title: YAML front matter</h2>
      @@ -12350,13 +12350,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
      -
       ---
      +
       ---
       title: YAML front matter
       ---
      -
      <hr>
      +
      <hr>
       <h2>title: YAML front matter</h2>
      @@ -12376,7 +12376,7 @@ Add either the [[_TOC_]] tag or
      -
      [TOC]
      +
      [TOC]
       
       # Heading 1
       
      @@ -12384,7 +12384,7 @@ Add either the [[_TOC_]] tag or
       
       
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
           <ul>
      @@ -12400,7 +12400,7 @@ Add either the [[_TOC_]] tag or
       
      -
      [[_TOC_]]
      +
      [[_TOC_]]
       
       # Heading 1
       
      @@ -12408,7 +12408,7 @@ Add either the [[_TOC_]] tag or
       
       
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
           <ul>
      @@ -12426,7 +12426,7 @@ line.

      -
      [[_TOC_]]
      +
      [[_TOC_]]
       text
       
       text
      @@ -12434,7 +12434,7 @@ line.

      -
      <p>[[<em>TOC</em>]]text</p>
      +
      <p>[[<em>TOC</em>]]text</p>
       <p>text[TOC]</p>
      @@ -12443,13 +12443,13 @@ line.

      -
         [[_TOC_]]
      +
         [[_TOC_]]
       
       # Heading 1
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
         </ul>
      @@ -12470,11 +12470,11 @@ Audio ignore the alternative text part of an image declaration.

      -
      ![audio](audio.oga "audio title")
      +
      ![audio](audio.oga "audio title")
      -
      <p><audio src="audio.oga" title="audio title"></audio></p>
      +
      <p><audio src="audio.oga" title="audio title"></audio></p>
      @@ -12482,13 +12482,13 @@ Audio ignore the alternative text part of an image declaration.

      -
      [audio]: audio.oga "audio title"
      +
      [audio]: audio.oga "audio title"
       
       ![audio][audio]
      -
      <p><audio src="audio.oga" title="audio title"></audio></p>
      +
      <p><audio src="audio.oga" title="audio title"></audio></p>
      @@ -12502,11 +12502,11 @@ Videos ignore the alternative text part of an image declaration.

      -
      ![video](video.m4v "video title")
      +
      ![video](video.m4v "video title")
      -
      <p><video src="video.m4v" title="video title"></video></p>
      +
      <p><video src="video.m4v" title="video title"></video></p>
      @@ -12514,13 +12514,13 @@ Videos ignore the alternative text part of an image declaration.

      -
      [video]: video.mov "video title"
      +
      [video]: video.mov "video title"
       
       ![video][video]
      -
      <p><video src="video.mov" title="video title"></video></p>
      +
      <p><video src="video.mov" title="video title"></video></p>
      @@ -12533,11 +12533,11 @@ endpoints via glfm_example_metadata.yml
      -
      [groups-test-file](/uploads/groups-test-file)
      +
      [groups-test-file](/uploads/groups-test-file)
      -
      <p><a href="groups-test-file">groups-test-file</a></p>
      +
      <p><a href="groups-test-file">groups-test-file</a></p>
      @@ -12545,11 +12545,11 @@ endpoints via glfm_example_metadata.yml
      -
      [projects-test-file](projects-test-file)
      +
      [projects-test-file](projects-test-file)
      -
      <p><a href="projects-test-file">projects-test-file</a></p>
      +
      <p><a href="projects-test-file">projects-test-file</a></p>
      @@ -12557,11 +12557,11 @@ endpoints via glfm_example_metadata.yml
      -
      This project snippet ID reference IS filtered: $88888
      +
      This project snippet ID reference IS filtered: $88888
      -
      <p>This project snippet ID reference IS filtered: $88888</p>
      +
      <p>This project snippet ID reference IS filtered: $88888</p>
      @@ -12572,11 +12572,11 @@ extension behavior, and specifically does not render snippet references via
      -
      This personal snippet ID reference is not filtered: $99999
      +
      This personal snippet ID reference is not filtered: $99999
      -
      <p>This personal snippet ID reference is not filtered: $99999</p>
      +
      <p>This personal snippet ID reference is not filtered: $99999</p>
      @@ -12584,11 +12584,11 @@ extension behavior, and specifically does not render snippet references via
      -
      [project-wikis-test-file](project-wikis-test-file)
      +
      [project-wikis-test-file](project-wikis-test-file)
      -
      <p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
      +
      <p><a href="project-wikis-test-file">project-wikis-test-file</a></p>
      @@ -12597,11 +12597,11 @@ also requires an EE license enabling the Example 696
      -
      [group-wikis-test-file](group-wikis-test-file)
      +
      [group-wikis-test-file](group-wikis-test-file)
      -
      <p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
      +
      <p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
      @@ -12612,11 +12612,11 @@ also requires an EE license enabling the Example 697
      -
      ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
      +
      ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12625,11 +12625,11 @@ also requires an EE license enabling the Example 698
      -
      ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
      +
      ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12638,11 +12638,11 @@ also requires an EE license enabling the Example 699
      -
      ![test-file](test-file.png)
      +
      ![test-file](test-file.png)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12651,11 +12651,11 @@ also requires an EE license enabling the Example 700
      -
      [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
      +
      [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12664,11 +12664,11 @@ also requires an EE license enabling the Example 701
      -
      [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
      +
      [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12677,11 +12677,11 @@ also requires an EE license enabling the Example 702
      -
      [test-file](test-file.zip)
      +
      [test-file](test-file.zip)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12690,11 +12690,11 @@ also requires an EE license enabling the Example 703
      -
      [test-file](test-file.zip)
      +
      [test-file](test-file.zip)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12703,11 +12703,11 @@ also requires an EE license enabling the Example 704
      -
      ![Sample Audio](https://gitlab.com/gitlab.mp3)
      +
      ![Sample Audio](https://gitlab.com/gitlab.mp3)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12716,7 +12716,7 @@ also requires an EE license enabling the Example 705
      -
      * ![Sample Audio](https://gitlab.com/1.mp3)
      +
      * ![Sample Audio](https://gitlab.com/1.mp3)
       * ![Sample Video](https://gitlab.com/2.mp4)
       
       1. ![Sample Video](https://gitlab.com/1.mp4)
      @@ -12728,7 +12728,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12737,13 +12737,13 @@ also requires an EE license enabling the Example 706
      -
      > This is a blockquote
      +
      > This is a blockquote
       >
       > This is another one
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12752,11 +12752,11 @@ also requires an EE license enabling the Example 707
      -
      **bold**
      +
      **bold**
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12765,13 +12765,13 @@ also requires an EE license enabling the Example 708
      -
      * list item 1
      +
      * list item 1
       * list item 2
         * embedded list item 3
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12780,13 +12780,13 @@ also requires an EE license enabling the Example 709
      -
      - list item 1
      +
      - list item 1
       - list item 2
         * embedded list item 3
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12795,13 +12795,13 @@ also requires an EE license enabling the Example 710
      -
      + list item 1
      +
      + list item 1
       + list item 2
         - embedded list item 3
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12810,13 +12810,13 @@ also requires an EE license enabling the Example 711
      -
      ```javascript
      +
      ```javascript
         console.log('hello world')
       ```
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12825,13 +12825,13 @@ also requires an EE license enabling the Example 712
      -
      ```
      +
      ```
         plaintext
       ```
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12840,13 +12840,13 @@ also requires an EE license enabling the Example 713
      -
      ```foobar
      +
      ```foobar
         custom_language = >> this <<
       ```
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12855,7 +12855,7 @@ also requires an EE license enabling the Example 714
      -
      - `#F00`
      +
      - `#F00`
       - `#F00A`
       - `#FF0000`
       - `#FF0000AA`
      @@ -12867,7 +12867,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12876,7 +12876,7 @@ also requires an EE license enabling the Example 715
      -
      <dl>
      +
      <dl>
       <dt>Frog</dt>
       <dd>Wet green thing</dd>
       <dt>Rabbit</dt>
      @@ -12895,7 +12895,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12904,7 +12904,7 @@ also requires an EE license enabling the Example 716
      -
      <details>
      +
      <details>
       <summary>This is the visible summary of the collapsible section</summary>
       
       1. collapsed markdown
      @@ -12914,7 +12914,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12923,7 +12923,7 @@ also requires an EE license enabling the Example 717
      -
      ```nomnoml
      +
      ```nomnoml
         #stroke: #a86128
         [<frame>Decorator pattern|
           [<abstract>Component||+ operation()]
      @@ -12937,7 +12937,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12946,7 +12946,7 @@ also requires an EE license enabling the Example 718
      -
      ```plantuml
      +
      ```plantuml
         Alice -> Bob: Authentication Request
         Bob --> Alice: Authentication Response
       
      @@ -12956,7 +12956,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12965,13 +12965,13 @@ also requires an EE license enabling the Example 719
      -
      ```plantuml
      +
      ```plantuml
       A -> B : Text with norwegian characters: æøå
       ```
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12980,7 +12980,7 @@ also requires an EE license enabling the Example 720
      -
      <div>plain text</div>
      +
      <div>plain text</div>
       <div>
       
       just a plain ol' div, not much to _expect_!
      @@ -12989,7 +12989,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -12998,11 +12998,11 @@ also requires an EE license enabling the Example 721
      -
      :sparkles: :heart: :100:
      +
      :sparkles: :heart: :100:
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13011,11 +13011,11 @@ also requires an EE license enabling the Example 722
      -
      _emphasized text_
      +
      _emphasized text_
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13024,7 +13024,7 @@ also requires an EE license enabling the Example 723
      -
      <figure>
      +
      <figure>
       
       ![Elephant at sunset](elephant-sunset.jpg)
       
      @@ -13043,7 +13043,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13052,7 +13052,7 @@ also requires an EE license enabling the Example 724
      -
      A footnote reference tag looks like this: [^1]
      +
      A footnote reference tag looks like this: [^1]
       
       This reference tag is a mix of letters and numbers. [^footnote]
       
      @@ -13062,7 +13062,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13071,7 +13071,7 @@ also requires an EE license enabling the Example 725
      -
      ;;;
      +
      ;;;
       {
         "title": "Page title"
       }
      @@ -13079,7 +13079,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13088,13 +13088,13 @@ also requires an EE license enabling the Example 726
      -
      +++
      +
      +++
       title = "Page title"
       +++
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13103,13 +13103,13 @@ also requires an EE license enabling the Example 727
      -
      ---
      +
      ---
       title: Page title
       ---
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13118,12 +13118,12 @@ also requires an EE license enabling the Example 728
      -
      This is a line after a\
      +
      This is a line after a\
       hard break
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13132,7 +13132,7 @@ also requires an EE license enabling the Example 729
      -
      # Heading 1
      +
      # Heading 1
       
       ## Heading 2
       
      @@ -13146,7 +13146,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13155,11 +13155,11 @@ also requires an EE license enabling the Example 730
      -
      ---
      +
      ---
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13168,7 +13168,7 @@ also requires an EE license enabling the Example 731
      -
      * Content editor is ~~great~~<ins>amazing</ins>.
      +
      * Content editor is ~~great~~<ins>amazing</ins>.
       * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.
       * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">אה, אני אוהב להיות ליד חוף הים</span>. In the computer's memory, this is stored as <bdo dir="ltr">אה, אני אוהב להיות ליד חוף הים</bdo>.
       * <cite>The Scream</cite> by Edvard Munch. Painted in 1893.
      @@ -13186,7 +13186,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13195,11 +13195,11 @@ also requires an EE license enabling the Example 732
    • -
      ![alt text](https://gitlab.com/logo.png)
      +
      ![alt text](https://gitlab.com/logo.png)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
    • @@ -13208,11 +13208,11 @@ also requires an EE license enabling the Example 733
    • -
      `code`
      +
      `code`
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13221,12 +13221,12 @@ also requires an EE license enabling the Example 734
      -
      * {-deleted-}
      +
      * {-deleted-}
       * {+added+}
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13235,11 +13235,11 @@ also requires an EE license enabling the Example 735
      -
      ~bug
      +
      ~bug
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13248,11 +13248,11 @@ also requires an EE license enabling the Example 736
      -
      [GitLab](https://gitlab.com)
      +
      [GitLab](https://gitlab.com)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13261,7 +13261,7 @@ also requires an EE license enabling the Example 737
      -
      This math is inline $`a^2+b^2=c^2`$.
      +
      This math is inline $`a^2+b^2=c^2`$.
       
       This is on a separate line:
       
      @@ -13271,7 +13271,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13280,13 +13280,13 @@ also requires an EE license enabling the Example 738
      -
      1. list item 1
      +
      1. list item 1
       2. list item 2
       3. list item 3
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13295,13 +13295,13 @@ also requires an EE license enabling the Example 739
      -
      134. list item 1
      +
      134. list item 1
       135. list item 2
       136. list item 3
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13310,7 +13310,7 @@ also requires an EE license enabling the Example 740
      -
      1. [x] hello
      +
      1. [x] hello
       2. [x] world
       3. [ ] example
          1. [ ] of nested
      @@ -13319,7 +13319,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13328,13 +13328,13 @@ also requires an EE license enabling the Example 741
      -
      4893. [x] hello
      +
      4893. [x] hello
       4894. [x] world
       4895. [ ] example
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13343,11 +13343,11 @@ also requires an EE license enabling the Example 742
      -
      Hi @gfm_user - thank you for reporting this ~"UX bug" (#1) we hope to fix it in %1.1 as part of !1
      +
      Hi @gfm_user - thank you for reporting this ~"UX bug" (#1) we hope to fix it in %1.1 as part of !1
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13356,11 +13356,11 @@ also requires an EE license enabling the Example 743
      -
      ~~del~~
      +
      ~~del~~
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13369,7 +13369,7 @@ also requires an EE license enabling the Example 744
      -
      | header | header |
      +
      | header | header |
       |--------|--------|
       | `code` | cell with **bold** |
       | ~~strike~~ | cell with _italic_ |
      @@ -13378,7 +13378,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13387,7 +13387,7 @@ also requires an EE license enabling the Example 745
      -
      [[_TOC_]]
      +
      [[_TOC_]]
       
       # Lorem
       
      @@ -13403,7 +13403,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13412,7 +13412,7 @@ also requires an EE license enabling the Example 746
      -
      * [x] hello
      +
      * [x] hello
       * [x] world
       * [ ] example
         * [ ] of nested
      @@ -13421,7 +13421,7 @@ also requires an EE license enabling the 
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13430,11 +13430,11 @@ also requires an EE license enabling the Example 747
      -
      ![Sample Video](https://gitlab.com/gitlab.mp4)
      +
      ![Sample Video](https://gitlab.com/gitlab.mp4)
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13443,11 +13443,11 @@ also requires an EE license enabling the Example 748
      -
      Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
      +
      Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
      -
      TODO: Write canonical HTML for this example
      +
      TODO: Write canonical HTML for this example
      @@ -13464,11 +13464,11 @@ where it makes sense.

      -
      ![](https://gitlab.com/logo.png){width="100" height="100"}
      +
      ![](https://gitlab.com/logo.png){width="100" height="100"}
      -
      <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p>
      +
      <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p>
      @@ -13476,22 +13476,22 @@ where it makes sense.

      -
      ![](https://gitlab.com/logo.png){width="100%"}
      +
      ![](https://gitlab.com/logo.png){width="100%"}
      -
      <p><img src="https://gitlab.com/logo.png" width="100%"></p>
      +
      <p><img src="https://gitlab.com/logo.png" width="100%"></p>
      -
      ![](https://gitlab.com/logo.png){height="100px"}
      +
      ![](https://gitlab.com/logo.png){height="100px"}
      -
      <p><img src="https://gitlab.com/logo.png" height="100px"></p>
      +
      <p><img src="https://gitlab.com/logo.png" height="100px"></p>
      @@ -13499,11 +13499,11 @@ where it makes sense.

      -
      ![](https://gitlab.com/logo.png){ width="100" height="100" }
      +
      ![](https://gitlab.com/logo.png){ width="100" height="100" }
      -
      <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p>
      +
      <p><img src="https://gitlab.com/logo.png" width="100" height="100"></p>
      @@ -13511,11 +13511,11 @@ where it makes sense.

      -
      ![](https://gitlab.com/logo.png) {width="100" height="100"}
      +
      ![](https://gitlab.com/logo.png) {width="100" height="100"}
      -
      <p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p>
      +
      <p><img src="https://gitlab.com/logo.png"> {width="100" height="100"}</p>
      @@ -13526,13 +13526,13 @@ where it makes sense.

      -
      footnote reference tag [^fortytwo]
      +
      footnote reference tag [^fortytwo]
       
       [^fortytwo]: footnote text
      -
      <p>
      +
      <p>
       footnote reference tag
       <sup>
       <a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref>
      @@ -13564,7 +13564,7 @@ task lists, etc.

      -
      This is some text![^1]. Other text.[^footnote].
      +
      This is some text![^1]. Other text.[^footnote].
       
       Here's a thing[^other-note].
       
      @@ -13593,7 +13593,7 @@ task lists, etc.

      -
      <p>This is some text!<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. Other text.<sup class="footnote-ref"><a href="#fn-footnote" id="fnref-footnote" data-footnote-ref>2</a></sup>.</p>
      +
      <p>This is some text!<sup class="footnote-ref"><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup>. Other text.<sup class="footnote-ref"><a href="#fn-footnote" id="fnref-footnote" data-footnote-ref>2</a></sup>.</p>
       <p>Here's a thing<sup class="footnote-ref"><a href="#fn-other-note" id="fnref-other-note" data-footnote-ref>3</a></sup>.</p>
       <p>And another thing<sup class="footnote-ref"><a href="#fn-codeblock-note" id="fnref-codeblock-note" data-footnote-ref>4</a></sup>.</p>
       <p>This doesn't have a referent[^nope].</p>
      @@ -13629,7 +13629,7 @@ task lists, etc.

      -
      This is some text. It has a footnote[^a-footnote].
      +
      This is some text. It has a footnote[^a-footnote].
       
       This footnote is referenced[^a-footnote] multiple times, in lots of different places.[^a-footnote]
       
      @@ -13637,7 +13637,7 @@ task lists, etc.

      -
      <p>This is some text. It has a footnote<sup class="footnote-ref"><a href="#fn-a-footnote" id="fnref-a-footnote" data-footnote-ref>1</a></sup>.</p>
      +
      <p>This is some text. It has a footnote<sup class="footnote-ref"><a href="#fn-a-footnote" id="fnref-a-footnote" data-footnote-ref>1</a></sup>.</p>
       <p>This footnote is referenced<sup class="footnote-ref"><a href="#fn-a-footnote" id="fnref-a-footnote-2" data-footnote-ref>1</a></sup> multiple times, in lots of different places.<sup class="footnote-ref"><a href="#fn-a-footnote" id="fnref-a-footnote-3" data-footnote-ref>1</a></sup></p>
       <section class="footnotes" data-footnotes>
       <ol>
      @@ -13654,13 +13654,13 @@ task lists, etc.

      -
      Hello[^"><script>alert(1)</script>]
      +
      Hello[^"><script>alert(1)</script>]
       
       [^"><script>alert(1)</script>]: pwned
      -
      <p>Hello<sup class="footnote-ref"><a href="#fn-%22%3E%3Cscript%3Ealert(1)%3C/script%3E" id="fnref-%22%3E%3Cscript%3Ealert(1)%3C/script%3E" data-footnote-ref>1</a></sup></p>
      +
      <p>Hello<sup class="footnote-ref"><a href="#fn-%22%3E%3Cscript%3Ealert(1)%3C/script%3E" id="fnref-%22%3E%3Cscript%3Ealert(1)%3C/script%3E" data-footnote-ref>1</a></sup></p>
       <section class="footnotes" data-footnotes>
       <ol>
       <li id="fn-%22%3E%3Cscript%3Ealert(1)%3C/script%3E">
      @@ -13677,13 +13677,13 @@ task lists, etc.

      -
      ~~www.google.com~~
      +
      ~~www.google.com~~
       
       ~~http://google.com~~
      -
      <p><del><a href="http://www.google.com">www.google.com</a></del></p>
      +
      <p><del><a href="http://www.google.com">www.google.com</a></del></p>
       <p><del><a href="http://google.com">http://google.com</a></del></p>
      @@ -13692,13 +13692,13 @@ task lists, etc.

      -
      | a | b |
      +
      | a | b |
       | --- | --- |
       | https://github.com www.github.com | http://pokemon.com |
      -
      <table>
      +
      <table>
       <thead>
       <tr>
       <th>a</th>
      @@ -13720,12 +13720,12 @@ task lists, etc.

      -
      - [ ] foo
      +
      - [ ] foo
       - [x] bar
      -
      <ul>
      +
      <ul>
       <li><input type="checkbox" disabled="" /> foo</li>
       <li><input type="checkbox" checked="" disabled="" /> bar</li>
       </ul>
      @@ -13741,7 +13741,7 @@ so will be treated as a regular item.

      -
      - [x] foo
      +
      - [x] foo
         - [ ] bar
         - [x] baz
       - [ ] bim
      @@ -13754,7 +13754,7 @@ so will be treated as a regular item.

      -
      <ul>
      +
      <ul>
       <li><input type="checkbox" checked="" disabled="" /> foo
       <ul>
       <li><input type="checkbox" disabled="" /> bar</li>
      @@ -13781,7 +13781,7 @@ the same structure.
       
      -
      - [x] foo
      +
      - [x] foo
           - [ ] bar
           - [x] baz
       - [ ] bim
      @@ -13794,7 +13794,7 @@ the same structure.
       
       
      -
      <ul>
      +
      <ul>
       <li><input type="checkbox" checked="" disabled="" /> foo
       <ul>
       <li><input type="checkbox" disabled="" /> bar</li>
      diff --git a/glfm_specification/output_spec/spec.html b/glfm_specification/output_spec/spec.html
      index e4929c1fa5c..07af9a162d5 100644
      --- a/glfm_specification/output_spec/spec.html
      +++ b/glfm_specification/output_spec/spec.html
      @@ -289,11 +289,11 @@ GitLab Flavored Markdown specification.

      -
      - [ ] incomplete
      +
      - [ ] incomplete
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" disabled/>
      @@ -307,11 +307,11 @@ GitLab Flavored Markdown specification.

      -
      - [x] completed
      +
      - [x] completed
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" checked disabled/>
      @@ -325,11 +325,11 @@ GitLab Flavored Markdown specification.

      -
      - [~] inapplicable
      +
      - [~] inapplicable
      -
      <ul>
      +
      <ul>
       <li>
       <task-button/>
       <input type="checkbox" data-inapplicable disabled>
      @@ -346,13 +346,13 @@ loose text; it has strikethrough applied with CSS.

      -
      - [~] inapplicable
      +
      - [~] inapplicable
       
         text in loose list
      -
      <ul>
      +
      <ul>
       <li>
       <p>
       <task-button/>
      @@ -379,13 +379,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      ---
      +
      ---
       title: YAML front matter
       ---
      -
      <pre>
      +
      <pre>
       <code>
       title: YAML front matter
       </code>
      @@ -397,13 +397,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      +++
      +
      +++
       title: TOML front matter
       +++
      -
      <pre>
      +
      <pre>
       <code>
       title: TOML front matter
       </code>
      @@ -415,7 +415,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      ;;;
      +
      ;;;
       {
         "title": "JSON front matter"
       }
      @@ -423,7 +423,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
       
      -
      <pre>
      +
      <pre>
       <code>
       {
         "title": "JSON front matter"
      @@ -437,7 +437,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
      -
      text
      +
      text
       
       ---
       title: YAML front matter
      @@ -445,7 +445,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
       
       
      -
      <p>text</p>
      +
      <p>text</p>
       <hr>
       <h2>title: YAML front matter</h2>
      @@ -455,13 +455,13 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
      -
       ---
      +
       ---
       title: YAML front matter
       ---
      -
      <hr>
      +
      <hr>
       <h2>title: YAML front matter</h2>
      @@ -481,7 +481,7 @@ Add either the [[_TOC_]] tag or the
      -
      [TOC]
      +
      [TOC]
       
       # Heading 1
       
      @@ -489,7 +489,7 @@ Add either the [[_TOC_]] tag or the
       
       
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
           <ul>
      @@ -505,7 +505,7 @@ Add either the [[_TOC_]] tag or the
       
      -
      [[_TOC_]]
      +
      [[_TOC_]]
       
       # Heading 1
       
      @@ -513,7 +513,7 @@ Add either the [[_TOC_]] tag or the
       
       
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
           <ul>
      @@ -531,7 +531,7 @@ line.

      -
      [[_TOC_]]
      +
      [[_TOC_]]
       text
       
       text
      @@ -539,7 +539,7 @@ line.

      -
      <p>[[<em>TOC</em>]]text</p>
      +
      <p>[[<em>TOC</em>]]text</p>
       <p>text[TOC]</p>
      @@ -548,13 +548,13 @@ line.

      -
         [[_TOC_]]
      +
         [[_TOC_]]
       
       # Heading 1
      -
      <nav>
      +
      <nav>
         <ul>
           <li><a href="#heading-1">Heading 1</a></li>
         </ul>
      diff --git a/lib/banzai/filter/markdown_post_escape_filter.rb b/lib/banzai/filter/markdown_post_escape_filter.rb
      index 90b9555df1d..b62e99b63ae 100644
      --- a/lib/banzai/filter/markdown_post_escape_filter.rb
      +++ b/lib/banzai/filter/markdown_post_escape_filter.rb
      @@ -71,7 +71,7 @@ module Banzai
               end
       
               doc.xpath(XPATH_LANG_TAG).each do |node|
      -          node.attributes['lang'].value  = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
      +          node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
               end
             end
       
      diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
      index 6888e0d19e5..f9e84f5557b 100644
      --- a/lib/banzai/filter/syntax_highlight_filter.rb
      +++ b/lib/banzai/filter/syntax_highlight_filter.rb
      @@ -66,7 +66,6 @@ module Banzai
       
               pre_node.add_class(CSS_CLASSES)
               pre_node.add_class("language-#{language}") if language
      -        pre_node.set_attribute('lang', language)
               pre_node.set_attribute('v-pre', 'true')
               copy_code_btn = "" unless language == 'suggestion'
       
      diff --git a/lib/click_house/write_buffer.rb b/lib/click_house/write_buffer.rb
      new file mode 100644
      index 00000000000..691363d5509
      --- /dev/null
      +++ b/lib/click_house/write_buffer.rb
      @@ -0,0 +1,15 @@
      +# frozen_string_literal: true
      +
      +module ClickHouse
      +  module WriteBuffer
      +    BUFFER_KEY = 'clickhouse_write_buffer'
      +
      +    class << self
      +      def write_event(event_hash)
      +        Gitlab::Redis::SharedState.with do |redis|
      +          redis.lpush(BUFFER_KEY, event_hash.to_json)
      +        end
      +      end
      +    end
      +  end
      +end
      diff --git a/lib/gitlab/ci/pipeline/chain/component_usage.rb b/lib/gitlab/ci/pipeline/chain/component_usage.rb
      index 79b8ea2d9db..fa341a75c1b 100644
      --- a/lib/gitlab/ci/pipeline/chain/component_usage.rb
      +++ b/lib/gitlab/ci/pipeline/chain/component_usage.rb
      @@ -31,6 +31,8 @@ module Gitlab
                       value: component.resource_type_before_type_cast
                     }
                   )
      +
      +            ::Ci::Components::Usages::CreateService.new(component, used_by_project: project).execute
                 end
       
                 def included_catalog_components
      diff --git a/lib/gitlab/merge_requests/mergeability/check_result.rb b/lib/gitlab/merge_requests/mergeability/check_result.rb
      index 075a897478b..25adb05246d 100644
      --- a/lib/gitlab/merge_requests/mergeability/check_result.rb
      +++ b/lib/gitlab/merge_requests/mergeability/check_result.rb
      @@ -6,6 +6,7 @@ module Gitlab
               SUCCESS_STATUS = :success
               FAILED_STATUS = :failed
               INACTIVE_STATUS = :inactive
      +        WARNING_STATUS = :warning
       
               attr_reader :status, :payload
       
      @@ -25,6 +26,10 @@ module Gitlab
                 new(status: INACTIVE_STATUS, payload: default_payload.merge(**payload))
               end
       
      +        def self.warning(payload: {})
      +          new(status: WARNING_STATUS, payload: default_payload.merge(**payload))
      +        end
      +
               def self.from_hash(data)
                 new(
                   status: data.fetch(:status).to_sym,
      diff --git a/locale/gitlab.pot b/locale/gitlab.pot
      index dd549cbefb6..165ad044dd5 100644
      --- a/locale/gitlab.pot
      +++ b/locale/gitlab.pot
      @@ -3553,6 +3553,9 @@ msgstr ""
       msgid "AdminSettings|Allow migrating GitLab groups and projects by direct transfer"
       msgstr ""
       
      +msgid "AdminSettings|Allow runner registration token"
      +msgstr ""
      +
       msgid "AdminSettings|Auto DevOps domain"
       msgstr ""
       
      @@ -3931,6 +3934,9 @@ msgstr ""
       msgid "AdminSettings|Users and groups must accept the invitation before they're added to a group or project."
       msgstr ""
       
      +msgid "AdminSettings|When disabled, runner registration tokens are disabled from runner pages, and maintainers and owners cannot use registration tokens to register runners. They can use runner authentication tokens instead as the more secure runner registration method."
      +msgstr ""
      +
       msgid "AdminSettings|When to delete inactive projects"
       msgstr ""
       
      @@ -43527,6 +43533,9 @@ msgstr ""
       msgid "Runners|Created by %{user} %{timeAgo}"
       msgstr ""
       
      +msgid "Runners|Creating runners with runner registration tokens is disabled. %{linkStart}Learn more%{linkEnd}."
      +msgstr ""
      +
       msgid "Runners|Creator"
       msgstr ""
       
      @@ -43652,9 +43661,6 @@ msgstr ""
       msgid "Runners|Idle"
       msgstr ""
       
      -msgid "Runners|If both settings are disabled, new runners cannot be registered."
      -msgstr ""
      -
       msgid "Runners|If you haven't already configured your Google Cloud project, this step enables the required services and creates a service account with the required permissions. "
       msgstr ""
       
      @@ -43745,7 +43751,7 @@ msgstr ""
       msgid "Runners|Median"
       msgstr ""
       
      -msgid "Runners|Members of the %{type} can register runners"
      +msgid "Runners|Members of the %{type} can create runners"
       msgstr ""
       
       msgid "Runners|Minor version upgrades are available."
      @@ -52944,6 +52950,9 @@ msgstr ""
       msgid "Timeout for the fastest Gitaly operations (in seconds)."
       msgstr ""
       
      +msgid "Timeout: Element not found"
      +msgstr ""
      +
       msgid "Timezone"
       msgstr ""
       
      diff --git a/scripts/utils.sh b/scripts/utils.sh
      index 7175d2577fe..5ac6277f8fa 100644
      --- a/scripts/utils.sh
      +++ b/scripts/utils.sh
      @@ -203,7 +203,7 @@ function install_gitlab_gem() {
       }
       
       function install_tff_gem() {
      -  run_timed_command "gem install test_file_finder --no-document --version 0.3.0"
      +  run_timed_command "gem install test_file_finder --no-document --version 0.3.1"
       }
       
       function install_activesupport_gem() {
      diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
      index e732281a406..89f5c0b34f4 100644
      --- a/spec/controllers/groups/runners_controller_spec.rb
      +++ b/spec/controllers/groups/runners_controller_spec.rb
      @@ -11,8 +11,11 @@ RSpec.describe Groups::RunnersController, feature_category: :fleet_visibility do
       
         let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
         let!(:instance_runner) { create(:ci_runner, :instance) }
      +  let(:runner_registration_enabled) { true }
       
         before do
      +    namespace_settings.update!(runner_registration_enabled: runner_registration_enabled)
      +
           sign_in(user)
         end
       
      @@ -76,6 +79,17 @@ RSpec.describe Groups::RunnersController, feature_category: :fleet_visibility do
               expect(assigns(:group_runner_registration_token)).not_to be_nil
               expect(assigns(:group_new_runner_path)).to eq(new_group_runner_path(group))
             end
      +
      +      context 'when runner registration is disabled' do
      +        let(:runner_registration_enabled) { false }
      +
      +        it 'does not expose runner creation and registration variables' do
      +          execute_get_request
      +
      +          expect(assigns(:group_runner_registration_token)).to be_nil
      +          expect(assigns(:group_new_runner_path)).to be_nil
      +        end
      +      end
           end
       
           context 'when user is not maintainer' do
      diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
      index b27b4e6fe19..e4beb00f538 100644
      --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
      +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
      @@ -5,8 +5,11 @@ require('spec_helper')
       RSpec.describe Projects::Settings::CiCdController, feature_category: :continuous_integration do
         let_it_be(:user) { create(:user) }
         let_it_be(:project_auto_devops) { create(:project_auto_devops) }
      +  let_it_be(:project) { project_auto_devops.project }
       
      -  let(:project) { project_auto_devops.project }
      +  before_all do
      +    project.namespace.namespace_settings = create(:namespace_settings, allow_runner_registration_token: true)
      +  end
       
         context 'as a maintainer' do
           before do
      diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
      index 22cbf6760dc..707694ef53b 100644
      --- a/spec/factories/projects.rb
      +++ b/spec/factories/projects.rb
      @@ -608,4 +608,14 @@ FactoryBot.define do
           path { 'gitlab-profile' }
           files { { 'README.md' => 'Hello World' } }
         end
      +
      +  trait :allow_runner_registration_token do
      +    after :create do |project|
      +      if project.namespace.namespace_settings.nil?
      +        project.namespace.namespace_settings = create(:namespace_settings, namespace: project.namespace)
      +      end
      +
      +      project.namespace.allow_runner_registration_token = true
      +    end
      +  end
       end
      diff --git a/spec/features/projects/files/user_find_file_spec.rb b/spec/features/projects/files/user_find_file_spec.rb
      index bf6680cd57a..5a38298f220 100644
      --- a/spec/features/projects/files/user_find_file_spec.rb
      +++ b/spec/features/projects/files/user_find_file_spec.rb
      @@ -8,6 +8,8 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
         let(:user)    { create :user }
         let(:project) { create :project, :repository }
       
      +  global_search_modal_selector = '#super-sidebar-search-modal'
      +
         before do
           sign_in(user)
           project.add_maintainer(user)
      @@ -16,63 +18,63 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
         end
       
         def find_file(text)
      -    fill_in 'file_find', with: text
      +    fill_in 'search', with: "~#{text}"
         end
       
         def ref_selector_dropdown
           find('.ref-selector .gl-button-text')
         end
       
      -  it 'navigates to find file by shortcut', :js do
      +  it 'activates the global search modal by shortcut', :js do
           find('body').native.send_key('t')
       
      -    expect(page).to have_active_sub_navigation('Repository')
      -    expect(page).to have_selector('.file-finder-holder', count: 1)
      +    expect(page).to have_selector(global_search_modal_selector, count: 1)
         end
       
      -  it 'navigates to find file', :js do
      -    click_link 'Find file'
      +  it 'activates the global search modal when find file button is clicked', :js do
      +    click_button 'Find file'
       
      -    expect(page).to have_active_sub_navigation('Repository')
      -    expect(page).to have_selector('.file-finder-holder', count: 1)
      +    expect(page).to have_selector(global_search_modal_selector, count: 1)
         end
       
         it 'searches CHANGELOG file', :js do
      -    click_link 'Find file'
      +    click_button 'Find file'
       
           find_file 'change'
       
      -    expect(page).to have_content('CHANGELOG')
      -    expect(page).not_to have_content('.gitignore')
      -    expect(page).not_to have_content('VERSION')
      +    page.within(global_search_modal_selector) do
      +      expect(page).to have_content('CHANGELOG')
      +      expect(page).not_to have_content('.gitignore')
      +      expect(page).not_to have_content('VERSION')
      +    end
         end
       
         it 'does not find file when search not exist file', :js do
      -    click_link 'Find file'
      +    click_button 'Find file'
       
           find_file 'asdfghjklqwertyuizxcvbnm'
       
      -    expect(page).not_to have_content('CHANGELOG')
      -    expect(page).not_to have_content('.gitignore')
      -    expect(page).not_to have_content('VERSION')
      +    page.within(global_search_modal_selector) do
      +      expect(page).not_to have_content('CHANGELOG')
      +      expect(page).not_to have_content('.gitignore')
      +      expect(page).not_to have_content('VERSION')
      +    end
         end
       
         it 'searches file by partially matches', :js do
      -    click_link 'Find file'
      +    click_button 'Find file'
       
           find_file 'git'
       
      -    expect(page).to have_content('.gitignore')
      -    expect(page).to have_content('.gitmodules')
      -    expect(page).not_to have_content('CHANGELOG')
      -    expect(page).not_to have_content('VERSION')
      +    page.within(global_search_modal_selector) do
      +      expect(page).to have_content('.gitignore')
      +      expect(page).to have_content('.gitmodules')
      +      expect(page).not_to have_content('CHANGELOG')
      +      expect(page).not_to have_content('VERSION')
      +    end
         end
       
         context 'when refs are switched', :js do
      -    before do
      -      click_link 'Find file'
      -    end
      -
           specify 'the ref switcher lists all the branches and tags' do
             ref = 'add-ipython-files'
             expect(ref_selector_dropdown).not_to have_text(ref)
      @@ -94,7 +96,7 @@ RSpec.describe 'User find project file', feature_category: :source_code_manageme
             wait_for_requests
       
             page.within('.ref-selector') do
      -        fill_in _('Switch branch/tag'), with: ref
      +        fill_in _('Search by Git revision'), with: ref
               wait_for_requests
       
               select_listbox_item(ref)
      diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
      index 3e1ae36a915..015c80b5489 100644
      --- a/spec/features/runners_spec.rb
      +++ b/spec/features/runners_spec.rb
      @@ -10,7 +10,11 @@ RSpec.describe 'Runners', feature_category: :fleet_visibility do
         end
       
         context 'with user as project maintainer' do
      -    let_it_be(:project) { create(:project).tap { |project| project.add_maintainer(user) } }
      +    let_it_be(:project) do
      +      create(:project, :allow_runner_registration_token).tap do |project|
      +        project.add_maintainer(user)
      +      end
      +    end
       
           context 'when user views runners page', :js do
             before do
      diff --git a/spec/frontend/behaviors/shortcuts/shortcuts_spec.js b/spec/frontend/behaviors/shortcuts/shortcuts_spec.js
      index 5f71eb24758..7d0250dd58c 100644
      --- a/spec/frontend/behaviors/shortcuts/shortcuts_spec.js
      +++ b/spec/frontend/behaviors/shortcuts/shortcuts_spec.js
      @@ -2,10 +2,17 @@ import $ from 'jquery';
       import { flatten } from 'lodash';
       import htmlSnippetsShow from 'test_fixtures/snippets/show.html';
       import { Mousetrap } from '~/lib/mousetrap';
      +import { waitForElement } from '~/lib/utils/dom_utils';
       import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
       import Shortcuts, { LOCAL_MOUSETRAP_DATA_KEY } from '~/behaviors/shortcuts/shortcuts';
       import MarkdownPreview from '~/behaviors/preview_markdown';
       
      +const mockSearchInput = document.createElement('input');
      +
      +jest.mock('~/lib/utils/dom_utils', () => ({
      +  waitForElement: jest.fn(() => Promise.resolve(mockSearchInput)),
      +}));
      +
       describe('Shortcuts', () => {
         let shortcuts;
       
      @@ -131,6 +138,37 @@ describe('Shortcuts', () => {
           });
         });
       
      +  describe('focusSearchFile', () => {
      +    let event;
      +
      +    beforeEach(() => {
      +      jest.spyOn(mockSearchInput, 'dispatchEvent');
      +      event = new KeyboardEvent('keydown', { cancelable: true });
      +      Shortcuts.focusSearchFile(event);
      +    });
      +
      +    it('clicks the super sidebar search button', () => {
      +      expect(HTMLElement.prototype.click).toHaveBeenCalled();
      +      expect(HTMLElement.prototype.click.mock.contexts[0].id).toBe('super-sidebar-search');
      +    });
      +
      +    it('cancels the default behavior of the event', () => {
      +      expect(event.defaultPrevented).toBe(true);
      +    });
      +
      +    it('waits for the input to become available in the DOM', () => {
      +      expect(waitForElement).toHaveBeenCalledWith('#super-sidebar-search-modal #search');
      +    });
      +
      +    it('sets the value of the search input', () => {
      +      expect(mockSearchInput.value).toBe('~');
      +    });
      +
      +    it('dispatches an `input` event on the search input', () => {
      +      expect(mockSearchInput.dispatchEvent).toHaveBeenCalledWith(new Event('input'));
      +    });
      +  });
      +
         describe('adding shortcuts', () => {
           it('add calls Mousetrap.bind correctly', () => {
             const mockCommand = { defaultKeys: ['m'] };
      diff --git a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js
      index 5fcdf5f06a2..913079b5d99 100644
      --- a/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js
      +++ b/spec/frontend/ci/runner/admin_runners/admin_runners_app_spec.js
      @@ -121,7 +121,6 @@ describe('AdminRunnersApp', () => {
           wrapper = mountFn(AdminRunnersApp, {
             apolloProvider: createMockApollo(handlers, {}, cacheConfig),
             propsData: {
      -        registrationToken: mockRegistrationToken,
               newRunnerPath,
               ...props,
             },
      @@ -155,11 +154,19 @@ describe('AdminRunnersApp', () => {
           showToast.mockReset();
         });
       
      -  it('shows the runner setup instructions', () => {
      -    createComponent();
      +  it('shows the runner registration token instructions', () => {
      +    createComponent({
      +      props: {
      +        allowRegistrationToken: true,
      +        registrationToken: mockRegistrationToken,
      +      },
      +    });
       
      -    expect(findRegistrationDropdown().props('registrationToken')).toBe(mockRegistrationToken);
      -    expect(findRegistrationDropdown().props('type')).toBe(INSTANCE_TYPE);
      +    expect(findRegistrationDropdown().props()).toEqual({
      +      allowRegistrationToken: true,
      +      registrationToken: mockRegistrationToken,
      +      type: INSTANCE_TYPE,
      +    });
         });
       
         describe('shows total runner counts', () => {
      @@ -491,7 +498,7 @@ describe('AdminRunnersApp', () => {
         });
       
         describe('when no runners are found', () => {
      -    beforeEach(async () => {
      +    beforeEach(() => {
             mockRunnersHandler.mockResolvedValue({
               data: {
                 runners: {
      @@ -500,15 +507,29 @@ describe('AdminRunnersApp', () => {
                 },
               },
             });
      -
      -      await createComponent();
           });
       
      -    it('shows no errors', () => {
      +    it('shows no errors', async () => {
      +      await createComponent();
      +
             expect(createAlert).not.toHaveBeenCalled();
           });
       
      -    it('shows an empty state', () => {
      +    it('shows an empty state', async () => {
      +      await createComponent();
      +
      +      expect(findRunnerListEmptyState().props()).toEqual({
      +        newRunnerPath,
      +        isSearchFiltered: false,
      +        registrationToken: null,
      +      });
      +    });
      +
      +    it('shows an empty state with a legacy registration token', async () => {
      +      await createComponent({
      +        props: { registrationToken: mockRegistrationToken },
      +      });
      +
             expect(findRunnerListEmptyState().props()).toEqual({
               newRunnerPath,
               isSearchFiltered: false,
      @@ -518,6 +539,8 @@ describe('AdminRunnersApp', () => {
       
           describe('when a filter is selected by the user', () => {
             beforeEach(async () => {
      +        await createComponent();
      +
               findRunnerFilteredSearchBar().vm.$emit('input', {
                 runnerType: null,
                 membership: DEFAULT_MEMBERSHIP,
      diff --git a/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js b/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
      index 0bd049ff230..6bd87eaf8ca 100644
      --- a/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
      +++ b/spec/frontend/ci/runner/components/registration/registration_dropdown_spec.js
      @@ -9,7 +9,6 @@ import { createWrapper } from '@vue/test-utils';
       import Vue, { nextTick } from 'vue';
       import VueApollo from 'vue-apollo';
       
      -import { s__ } from '~/locale';
       import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
       import createMockApollo from 'helpers/mock_apollo_helper';
       import waitForPromises from 'helpers/wait_for_promises';
      @@ -48,9 +47,7 @@ describe('RegistrationDropdown', () => {
         const findTokenDropdownItem = () => wrapper.findComponent(GlDropdownForm);
         const findRegistrationToken = () => wrapper.findComponent(RegistrationToken);
         const findRegistrationTokenInput = () =>
      -    wrapper.findByLabelText(
      -      `${RegistrationToken.i18n.registrationToken} ${RegistrationDropdown.i18n.supportForRegistrationTokensDeprecated}`,
      -    );
      +    wrapper.findByLabelText(`Registration token Support for registration tokens is deprecated`);
         const findTokenResetDropdownItem = () =>
           wrapper.findComponent(RegistrationTokenResetDropdownItem);
         const findModal = () => wrapper.findComponent(GlModal);
      @@ -69,7 +66,6 @@ describe('RegistrationDropdown', () => {
         const createComponent = ({ props = {}, ...options } = {}, mountFn = shallowMountExtended) => {
           wrapper = mountFn(RegistrationDropdown, {
             propsData: {
      -        registrationToken: mockRegistrationToken,
               type: INSTANCE_TYPE,
               ...props,
             },
      @@ -80,7 +76,7 @@ describe('RegistrationDropdown', () => {
           });
         };
       
      -  const createComponentWithModal = () => {
      +  const createComponentWithModal = (options = {}) => {
           const requestHandlers = [
             [getRunnerPlatformsQuery, jest.fn().mockResolvedValue(mockRunnerPlatforms)],
             [getRunnerSetupInstructionsQuery, jest.fn().mockResolvedValue(mockInstructions)],
      @@ -92,170 +88,75 @@ describe('RegistrationDropdown', () => {
               apolloProvider: createMockApollo(requestHandlers),
               // Use `attachTo` to find the modal
               attachTo: document.body,
      +        ...options,
             },
             mountExtended,
           );
         };
       
      -  it.each`
      -    type             | text
      -    ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
      -    ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
      -    ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
      -  `('Dropdown text for type $type is "$text"', ({ type, text }) => {
      -    createComponent({ props: { type } }, mountExtended);
      -
      -    expect(wrapper.text()).toContain(text);
      -  });
      -
      -  it('Passes attributes to dropdown', () => {
      -    createComponent({ attrs: { right: true } });
      -
      -    expect(findDropdown().attributes()).toMatchObject({ right: 'true' });
      -  });
      -
      -  it('Passes default props and attributes to dropdown', () => {
      -    createComponent();
      -
      -    expect(findDropdown().props()).toMatchObject({
      -      category: 'tertiary',
      -      variant: 'default',
      -    });
      -
      -    expect(findDropdown().attributes()).toMatchObject({
      -      toggleclass: 'gl-px-3!',
      -    });
      -  });
      -
      -  describe('Instructions dropdown item', () => {
      -    it('Displays "Show runner" dropdown item', () => {
      -      createComponent();
      -
      -      expect(findRegistrationInstructionsDropdownItem().text()).toBe(
      -        'Show runner installation and registration instructions',
      +  describe('when registration token is disabled', () => {
      +    beforeEach(() => {
      +      createComponent(
      +        { props: { allowRegistrationToken: false, registrationToken: null } },
      +        mountExtended,
             );
           });
       
      -    describe('When the dropdown item is clicked', () => {
      -      beforeEach(async () => {
      -        createComponentWithModal({}, mountExtended);
      +    it('"token is disabled" text is shown', () => {
      +      expect(wrapper.text()).toContain(
      +        'Creating runners with runner registration tokens is disabled',
      +      );
      +    });
       
      -        await openModal();
      -      });
      -
      -      it('opens the modal with contents', () => {
      -        const modalText = findModalContent();
      -
      -        expect(modalText).toContain('Install a runner');
      -
      -        // Environment selector
      -        expect(modalText).toContain('Environment');
      -        expect(modalText).toContain('Linux macOS Windows Docker Kubernetes');
      -
      -        // Architecture selector
      -        expect(modalText).toContain('Architecture');
      -        expect(modalText).toContain('amd64 amd64 386 arm arm64');
      -
      -        expect(modalText).toContain('Download and install binary');
      -      });
      +    it('registration token is not shown', () => {
      +      expect(findRegistrationToken().exists()).toBe(false);
           });
         });
       
      -  describe('Registration token', () => {
      -    it('Displays dropdown form for the registration token', () => {
      -      createComponent();
      -
      -      expect(findTokenDropdownItem().exists()).toBe(true);
      -    });
      -
      -    it('Displays masked value as password input by default', () => {
      -      const mockToken = '0123456789';
      -
      +  describe('when registration token is enabled', () => {
      +    it.each`
      +      type             | text
      +      ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
      +      ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
      +      ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
      +    `('Dropdown text for type $type is "$text"', ({ type, text }) => {
             createComponent(
               {
      -          props: { registrationToken: mockToken },
      +          props: {
      +            allowRegistrationToken: true,
      +            registrationToken: mockRegistrationToken,
      +            type,
      +          },
               },
               mountExtended,
             );
       
      -      expect(findRegistrationTokenInput().classes()).toContain('input-copy-show-disc');
      -    });
      -  });
      -
      -  describe('Reset token item', () => {
      -    it('Displays registration token reset item', () => {
      -      createComponent();
      -
      -      expect(findTokenResetDropdownItem().exists()).toBe(true);
      +      expect(wrapper.text()).toContain(text);
           });
       
      -    it.each([INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE])('Set up token reset for %s', (type) => {
      -      createComponent({ props: { type } });
      -
      -      expect(findTokenResetDropdownItem().props('type')).toBe(type);
      -    });
      -  });
      -
      -  describe('Dropdown is expanded', () => {
      -    beforeEach(() => {
      -      createComponent({}, mountExtended);
      -      findDropdownBtn().vm.$emit('click');
      -    });
      -
      -    it('has aria-expanded set to true', () => {
      -      expect(findDropdownBtn().attributes('aria-expanded')).toBe('true');
      -    });
      -
      -    describe('when token is copied', () => {
      -      it('should close dropdown', async () => {
      -        findRegistrationToken().vm.$emit('copy');
      -        await nextTick();
      -
      -        expect(findDropdownBtn().attributes('aria-expanded')).toBe('false');
      +    it('Passes attributes to dropdown', () => {
      +      createComponent({
      +        props: {
      +          allowRegistrationToken: true,
      +          registrationToken: mockRegistrationToken,
      +        },
      +        attrs: { right: true },
             });
      -    });
      -  });
       
      -  describe('When token is reset', () => {
      -    const newToken = 'mock1';
      -
      -    const resetToken = async () => {
      -      findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
      -      await nextTick();
      -    };
      -
      -    it('Updates token input', async () => {
      -      createComponent({}, mountExtended);
      -
      -      expect(findRegistrationToken().props('value')).not.toBe(newToken);
      -
      -      await resetToken();
      -
      -      expect(findRegistrationToken().props('value')).toBe(newToken);
      +      expect(findDropdown().attributes()).toMatchObject({ right: 'true' });
           });
       
      -    it('Updates token in modal', async () => {
      -      createComponentWithModal({}, mountExtended);
      -
      -      await openModal();
      -
      -      expect(findModalContent()).toContain(mockRegistrationToken);
      -
      -      await resetToken();
      -
      -      expect(findModalContent()).toContain(newToken);
      -    });
      -  });
      -
      -  describe('When showing a "deprecated" warning', () => {
      -    it('passes deprecated variant props and attributes to dropdown', () => {
      -      createComponent();
      +    it('Passes default props and attributes to dropdown', () => {
      +      createComponent({
      +        props: {
      +          allowRegistrationToken: true,
      +          registrationToken: mockRegistrationToken,
      +        },
      +      });
       
             expect(findDropdown().props()).toMatchObject({
               category: 'tertiary',
               variant: 'default',
      -        toggleText: I18N_REGISTER_INSTANCE_TYPE,
      -        textSrOnly: true,
             });
       
             expect(findDropdown().attributes()).toMatchObject({
      @@ -263,30 +164,200 @@ describe('RegistrationDropdown', () => {
             });
           });
       
      -    it.each`
      -      type             | text
      -      ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
      -      ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
      -      ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
      -    `('dropdown text for type $type is "$text"', ({ type, text }) => {
      -      createComponent({ props: { type } }, mountExtended);
      +    describe('Instructions dropdown item', () => {
      +      it('Displays "Show runner" dropdown item', () => {
      +        createComponent({
      +          props: {
      +            allowRegistrationToken: true,
      +            registrationToken: mockRegistrationToken,
      +          },
      +        });
       
      -      expect(wrapper.text()).toContain(text);
      +        expect(findRegistrationInstructionsDropdownItem().text()).toBe(
      +          'Show runner installation and registration instructions',
      +        );
      +      });
      +
      +      describe('When the dropdown item is clicked', () => {
      +        beforeEach(async () => {
      +          createComponentWithModal(
      +            {
      +              props: {
      +                allowRegistrationToken: true,
      +                registrationToken: mockRegistrationToken,
      +              },
      +            },
      +            mountExtended,
      +          );
      +
      +          await openModal();
      +        });
      +
      +        it('opens the modal with contents', () => {
      +          const modalText = findModalContent();
      +
      +          expect(modalText).toContain('Install a runner');
      +
      +          // Environment selector
      +          expect(modalText).toContain('Environment');
      +          expect(modalText).toContain('Linux macOS Windows Docker Kubernetes');
      +
      +          // Architecture selector
      +          expect(modalText).toContain('Architecture');
      +          expect(modalText).toContain('amd64 amd64 386 arm arm64');
      +
      +          expect(modalText).toContain('Download and install binary');
      +        });
      +      });
           });
       
      -    it('shows warning text', () => {
      -      createComponent({}, mountExtended);
      +    describe('Registration token', () => {
      +      it('Displays dropdown form for the registration token', () => {
      +        createComponent({
      +          props: {
      +            allowRegistrationToken: true,
      +            registrationToken: mockRegistrationToken,
      +          },
      +        });
       
      -      const text = wrapper.findByText(s__('Runners|Support for registration tokens is deprecated'));
      +        expect(findTokenDropdownItem().exists()).toBe(true);
      +      });
       
      -      expect(text.exists()).toBe(true);
      +      it('Displays masked value as password input by default', () => {
      +        const mockToken = '0123456789';
      +
      +        createComponent(
      +          {
      +            props: { allowRegistrationToken: true, registrationToken: mockToken },
      +          },
      +          mountExtended,
      +        );
      +
      +        expect(findRegistrationTokenInput().classes()).toContain('input-copy-show-disc');
      +      });
           });
       
      -    it('button shows ellipsis icon', () => {
      -      createComponent({}, mountExtended);
      +    describe('Reset token item', () => {
      +      describe.each([INSTANCE_TYPE, GROUP_TYPE, PROJECT_TYPE])(
      +        'Set up token reset for %s',
      +        (type) => {
      +          beforeEach(() => {
      +            createComponent({
      +              props: {
      +                allowRegistrationToken: true,
      +                registrationToken: mockRegistrationToken,
      +                type,
      +              },
      +            });
      +          });
       
      -      expect(findDropdownBtn().findComponent(GlIcon).props('name')).toBe('ellipsis_v');
      -      expect(findDropdownBtn().findAllComponents(GlIcon)).toHaveLength(1);
      +          it('Displays registration token reset item', () => {
      +            expect(findTokenResetDropdownItem().props('type')).toBe(type);
      +          });
      +        },
      +      );
      +    });
      +
      +    describe('When token is reset', () => {
      +      const newToken = 'mock1';
      +
      +      const resetToken = async () => {
      +        findTokenResetDropdownItem().vm.$emit('tokenReset', newToken);
      +        await nextTick();
      +      };
      +
      +      it('Updates token input', async () => {
      +        createComponent(
      +          { props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
      +          mountExtended,
      +        );
      +
      +        expect(findRegistrationToken().props('value')).not.toBe(newToken);
      +
      +        await resetToken();
      +
      +        expect(findRegistrationToken().props('value')).toBe(newToken);
      +      });
      +
      +      it('Updates token in modal', async () => {
      +        createComponentWithModal(
      +          { props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
      +          mountExtended,
      +        );
      +
      +        await openModal();
      +
      +        expect(findModalContent()).toContain(mockRegistrationToken);
      +
      +        await resetToken();
      +
      +        expect(findModalContent()).toContain(newToken);
      +      });
      +    });
      +
      +    describe('When showing a "deprecated" warning', () => {
      +      it('passes deprecated variant props and attributes to dropdown', () => {
      +        createComponent({
      +          props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken },
      +        });
      +
      +        expect(findDropdown().props()).toMatchObject({
      +          category: 'tertiary',
      +          variant: 'default',
      +          toggleText: I18N_REGISTER_INSTANCE_TYPE,
      +          textSrOnly: true,
      +        });
      +
      +        expect(findDropdown().attributes()).toMatchObject({
      +          toggleclass: 'gl-px-3!',
      +        });
      +      });
      +
      +      it.each`
      +        type             | text
      +        ${INSTANCE_TYPE} | ${I18N_REGISTER_INSTANCE_TYPE}
      +        ${GROUP_TYPE}    | ${I18N_REGISTER_GROUP_TYPE}
      +        ${PROJECT_TYPE}  | ${I18N_REGISTER_PROJECT_TYPE}
      +      `('dropdown text for type $type is "$text"', ({ type, text }) => {
      +        createComponent({ props: { type } }, mountExtended);
      +
      +        expect(wrapper.text()).toContain(text);
      +      });
      +
      +      it('shows warning text', () => {
      +        createComponent(
      +          {
      +            props: {
      +              allowRegistrationToken: true,
      +              registrationToken: mockRegistrationToken,
      +            },
      +          },
      +          mountExtended,
      +        );
      +
      +        const text = wrapper.findByText('Support for registration tokens is deprecated');
      +        expect(text.exists()).toBe(true);
      +      });
      +
      +      it('button shows ellipsis icon', () => {
      +        createComponent(
      +          { props: { allowRegistrationToken: true, registrationToken: mockRegistrationToken } },
      +          mountExtended,
      +        );
      +
      +        expect(findDropdownBtn().findComponent(GlIcon).props('name')).toBe('ellipsis_v');
      +        expect(findDropdownBtn().findAllComponents(GlIcon)).toHaveLength(1);
      +      });
      +    });
      +  });
      +
      +  describe('when registration token is hidden due to user permissions', () => {
      +    beforeEach(() => {
      +      createComponent({ props: { allowRegistrationToken: true, registrationToken: null } });
      +    });
      +
      +    it('the component is not shown', () => {
      +      expect(wrapper.html()).toBe('');
           });
         });
       });
      diff --git a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js
      index 2af877f86c9..d739c953bd5 100644
      --- a/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js
      +++ b/spec/frontend/ci/runner/group_runners/group_runners_app_spec.js
      @@ -479,10 +479,15 @@ describe('GroupRunnersApp', () => {
           it('shows the register group runner button', () => {
             createComponent({
               props: {
      +          allowRegistrationToken: true,
                 registrationToken: mockRegistrationToken,
               },
             });
      -      expect(findRegistrationDropdown().exists()).toBe(true);
      +      expect(findRegistrationDropdown().props()).toEqual({
      +        allowRegistrationToken: true,
      +        registrationToken: mockRegistrationToken,
      +        type: GROUP_TYPE,
      +      });
           });
       
           it('shows the create runner button', () => {
      @@ -497,15 +502,6 @@ describe('GroupRunnersApp', () => {
         });
       
         describe('when user has no permission to register group runner', () => {
      -    it('does not show the register group runner button', () => {
      -      createComponent({
      -        props: {
      -          registrationToken: null,
      -        },
      -      });
      -      expect(findRegistrationDropdown().exists()).toBe(false);
      -    });
      -
           it('shows the create runner button', () => {
             createComponent({
               props: {
      diff --git a/spec/frontend/integrations/edit/components/dynamic_field_spec.js b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
      index f00dcc50ec9..00319eb6636 100644
      --- a/spec/frontend/integrations/edit/components/dynamic_field_spec.js
      +++ b/spec/frontend/integrations/edit/components/dynamic_field_spec.js
      @@ -1,7 +1,7 @@
       import { GlFormGroup, GlFormCheckbox, GlFormInput, GlFormSelect, GlFormTextarea } from '@gitlab/ui';
       import { mount } from '@vue/test-utils';
       
      -import Vue from 'vue';
      +import Vue, { nextTick } from 'vue';
       // eslint-disable-next-line no-restricted-imports
       import Vuex from 'vuex';
       
      @@ -238,6 +238,15 @@ describe('DynamicField', () => {
             });
           });
       
      +    it('emits update event when model is changed', async () => {
      +      createComponent();
      +      findGlFormInput().vm.$emit('input', 'example');
      +
      +      await nextTick();
      +
      +      expect(wrapper.emitted('update')).toEqual([['example']]);
      +    });
      +
           describe('label text', () => {
             it('renders label with title', () => {
               createComponent();
      diff --git a/spec/frontend/integrations/edit/components/sections/configuration_spec.js b/spec/frontend/integrations/edit/components/sections/configuration_spec.js
      index b300f493a97..12cc06529bb 100644
      --- a/spec/frontend/integrations/edit/components/sections/configuration_spec.js
      +++ b/spec/frontend/integrations/edit/components/sections/configuration_spec.js
      @@ -61,6 +61,24 @@ describe('IntegrationSectionCoonfiguration', () => {
               });
             });
       
      +      it('emits update event with field when Dynamic text field emits event', () => {
      +        const fields = [{ name: 'username', type: 'text' }];
      +
      +        createComponent({
      +          props: {
      +            fields,
      +          },
      +        });
      +
      +        const dynamicFields = findAllDynamicFields();
      +
      +        const [dynamicField] = dynamicFields.wrappers;
      +
      +        dynamicField.vm.$emit('update', 'example');
      +
      +        expect(wrapper.emitted('update')).toEqual([[{ value: 'example', field: fields[0] }]]);
      +      });
      +
             it('does not render DynamicField when field is empty', () => {
               createComponent();
       
      diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js
      index a0504458037..5395fb44b22 100644
      --- a/spec/frontend/lib/utils/dom_utils_spec.js
      +++ b/spec/frontend/lib/utils/dom_utils_spec.js
      @@ -1,5 +1,4 @@
       import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
      -
       import {
         addClassIfElementExists,
         canScrollUp,
      @@ -11,6 +10,7 @@ import {
         getParentByTagName,
         setAttributes,
         replaceCommentsWith,
      +  waitForElement,
       } from '~/lib/utils/dom_utils';
       
       const TEST_MARGIN = 5;
      @@ -285,4 +285,59 @@ describe('DOM Utils', () => {
             );
           });
         });
      +
      +  describe('waitForElement', () => {
      +    const fixture = '
      '; + const mockElementSelector = 'some-selector'; + const mockElement = document.createElement('div'); + mockElement.classList.add(mockElementSelector); + + beforeEach(() => setHTMLFixture(fixture)); + + afterEach(() => resetHTMLFixture()); + + it('resolves immediately if element is already in the DOM', async () => { + document.querySelector('.wrapper').appendChild(mockElement); + const result = await waitForElement(`.${mockElementSelector}`); + + expect(result).toBe(mockElement); + }); + + it('resolves after element is added to the DOM', async () => { + const waitForElementPromise = waitForElement(`.${mockElementSelector}`); + document.querySelector('.wrapper').appendChild(mockElement); + const result = await waitForElementPromise; + + expect(result).toBe(mockElement); + }); + + describe('if no element found', () => { + const mockDisconnect = jest.fn(); + let OriginalMutationObserver; + const timeoutDelay = 100; + class MutationObserverMock { + constructor() { + this.observe = jest.fn(); + this.disconnect = mockDisconnect; + } + } + + beforeEach(() => { + OriginalMutationObserver = global.MutationObserver; + global.MutationObserver = MutationObserverMock; + }); + + afterEach(() => { + global.MutationObserver = OriginalMutationObserver; + }); + + it('disconnects the observer and rejects the promise after the timeout delay', async () => { + const waitForElementPromise = waitForElement('.some-unavailable-element', timeoutDelay); + jest.advanceTimersByTime(timeoutDelay); + + expect(mockDisconnect).toHaveBeenCalled(); + await expect(waitForElementPromise).rejects.toMatch('Timeout: Element not found'); + }); + }); + }); }); diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rules_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rules_spec.js index e8f9cb7d27c..5b95bdc2ea9 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rules_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_rules_spec.js @@ -70,6 +70,8 @@ describe('Container protection rules project settings', () => { }); describe('table "package protection rules"', () => { + const findTableRowCell = (i, j) => findTableRow(i).findAllByRole('cell').at(j); + it('renders table with Container protection rules', async () => { createComponent(); @@ -79,9 +81,10 @@ describe('Container protection rules project settings', () => { containerProtectionRuleQueryPayload().data.project.containerRegistryProtectionRules.nodes.forEach( (protectionRule, i) => { - expect(findTableRow(i).text()).toContain(protectionRule.repositoryPathPattern); - expect(findTableRow(i).text()).toContain('Maintainer'); - expect(findTableRow(i).text()).toContain('Maintainer'); + expect(findTableRow(i).findAllByRole('cell').length).toBe(3); + expect(findTableRowCell(i, 0).text()).toBe(protectionRule.repositoryPathPattern); + expect(findTableRowCell(i, 1).text()).toBe('Maintainer'); + expect(findTableRowCell(i, 2).text()).toBe('Maintainer'); }, ); }); diff --git a/spec/frontend/projects/behaviors_spec.js b/spec/frontend/projects/behaviors_spec.js new file mode 100644 index 00000000000..50bfe7492f2 --- /dev/null +++ b/spec/frontend/projects/behaviors_spec.js @@ -0,0 +1,23 @@ +import { initFindFileShortcut } from '~/projects/behaviors'; +import Shortcuts from '~/behaviors/shortcuts/shortcuts'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; + +describe('initFindFileShortcut', () => { + const fixture = ''; + + beforeEach(() => setHTMLFixture(fixture)); + + afterEach(() => resetHTMLFixture()); + + it('add a `click` eventListener to the find file button', () => { + const findFileButton = document.querySelector('.shortcuts-find-file'); + jest.spyOn(findFileButton, 'addEventListener'); + + initFindFileShortcut(); + + expect(findFileButton.addEventListener).toHaveBeenCalledWith( + 'click', + Shortcuts.focusSearchFile, + ); + }); +}); diff --git a/spec/frontend/repository/components/blob_controls_spec.js b/spec/frontend/repository/components/blob_controls_spec.js index 53ebabebf1d..90c1fb39905 100644 --- a/spec/frontend/repository/components/blob_controls_spec.js +++ b/spec/frontend/repository/components/blob_controls_spec.js @@ -10,6 +10,7 @@ import createRouter from '~/repository/router'; import { updateElementsVisibility } from '~/repository/utils/dom'; import { resetShortcutsForTests } from '~/behaviors/shortcuts'; import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob'; +import Shortcuts from '~/behaviors/shortcuts/shortcuts'; import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater'; import { blobControlsDataMock, refMock } from '../mock_data'; @@ -53,8 +54,12 @@ describe('Blob controls component', () => { beforeEach(() => createComponent()); - it('renders a find button with the correct href', () => { - expect(findFindButton().attributes('href')).toBe('find/file.js'); + it('triggers a `focusSearchFile` shortcut when the findFile button is clicked', () => { + const findFileButton = findFindButton(); + jest.spyOn(Shortcuts, 'focusSearchFile').mockResolvedValue(); + findFileButton.vm.$emit('click'); + + expect(Shortcuts.focusSearchFile).toHaveBeenCalled(); }); it('renders a blame button with the correct href', () => { diff --git a/spec/frontend/search/sidebar/components/app_spec.js b/spec/frontend/search/sidebar/components/app_spec.js index ba4c2ba93e4..bbf8805d544 100644 --- a/spec/frontend/search/sidebar/components/app_spec.js +++ b/spec/frontend/search/sidebar/components/app_spec.js @@ -33,7 +33,7 @@ describe('GlobalSearchSidebar', () => { currentScope: jest.fn(() => 'issues'), }; - const createComponent = (initialState = {}) => { + const createComponent = (initialState = {}, glFeatures = {}) => { const store = new Vuex.Store({ state: { urlQuery: MOCK_QUERY, @@ -44,6 +44,9 @@ describe('GlobalSearchSidebar', () => { wrapper = shallowMount(GlobalSearchSidebar, { store, + provide: { + glFeatures, + }, }); }; @@ -105,25 +108,34 @@ describe('GlobalSearchSidebar', () => { }); describe.each` - scope | searchType | isShown - ${'blobs'} | ${SEARCH_TYPE_BASIC} | ${false} - ${'blobs'} | ${SEARCH_TYPE_ADVANCED} | ${true} - ${'blobs'} | ${SEARCH_TYPE_ZOEKT} | ${true} - `('sidebar blobs scope:', ({ scope, searchType, isShown }) => { - beforeEach(() => { - getterSpies.currentScope = jest.fn(() => scope); - createComponent({ - urlQuery: { scope }, - searchType, + scope | filter | searchType | searchAddArchivedFilterToZoekt | isShown + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_BASIC} | ${true} | ${false} + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_BASIC} | ${false} | ${false} + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ADVANCED} | ${true} | ${true} + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ADVANCED} | ${false} | ${true} + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ZOEKT} | ${true} | ${true} + ${'blobs'} | ${findBlobsFilters} | ${SEARCH_TYPE_ZOEKT} | ${false} | ${false} + `( + 'sidebar blobs scope:', + ({ scope, filter, searchType, searchAddArchivedFilterToZoekt, isShown }) => { + beforeEach(() => { + getterSpies.currentScope = jest.fn(() => scope); + createComponent( + { + urlQuery: { scope }, + searchType, + }, + { searchAddArchivedFilterToZoekt }, + ); }); - }); - it(`does ${ - isShown ? '' : 'not ' - }render filter BlobsFilters when search_type ${searchType}`, () => { - expect(findBlobsFilters().exists()).toBe(isShown); - }); - }); + it(`does ${ + isShown ? '' : 'not ' + }render filter BlobsFilters when search_type ${searchType} and searchAddArchivedFilterToZoekt ${searchAddArchivedFilterToZoekt}`, () => { + expect(filter().exists()).toBe(isShown); + }); + }, + ); describe('with sidebar scope: projects', () => { beforeEach(() => { diff --git a/spec/graphql/types/merge_requests/mergeability_check_status_enum_spec.rb b/spec/graphql/types/merge_requests/mergeability_check_status_enum_spec.rb index 0a15d83f560..75fbc57a2e9 100644 --- a/spec/graphql/types/merge_requests/mergeability_check_status_enum_spec.rb +++ b/spec/graphql/types/merge_requests/mergeability_check_status_enum_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Types::MergeRequests::MergeabilityCheckStatusEnum, feature_catego it 'exposes all the existing mergeability check statuses' do expect(described_class.values.keys).to contain_exactly( - *%w[SUCCESS FAILED INACTIVE] + *%w[SUCCESS FAILED INACTIVE WARNING] ) end end diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb index 831f41cde0a..c43cc78f4ea 100644 --- a/spec/helpers/markup_helper_spec.rb +++ b/spec/helpers/markup_helper_spec.rb @@ -476,7 +476,7 @@ RSpec.describe MarkupHelper, feature_category: :team_planning do it 'preserves code color scheme' do object = create_object("```ruby\ndef test\n 'hello world'\nend\n```") - expected = "\n
      " \
      +        expected = "\n
      " \
                 "def test..." \
                 "
      \n" diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index 5fe9433cef3..08fccd85488 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -23,7 +23,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "highlights as plaintext" do result = filter('
      def fun end
      ') - expect(result.to_html.delete("\n")).to eq('
      def fun end
      ') + expect(result.to_html.delete("\n")).to eq('
      def fun end
      ') end include_examples "XSS prevention", "" @@ -33,7 +33,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "ignores mermaid blocks" do result = filter('
      mermaid code
      ') - expect(result.to_html.delete("\n")).to eq('
      mermaid code
      ') + expect(result.to_html.delete("\n")).to eq('
      mermaid code
      ') end end @@ -62,7 +62,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl text = "
      \n
      \nsomething\n
      else\n
      \n
      " result = filter(text) - expect(result.to_html.delete("\n")).to eq('
      somethingelse
      ') + expect(result.to_html.delete("\n")).to eq('
      somethingelse
      ') end end @@ -70,7 +70,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "highlights as that language" do result = filter('
      def fun end
      ') - expect(result.to_html.delete("\n")).to eq('
      def fun end
      ') + expect(result.to_html.delete("\n")).to eq('
      def fun end
      ') end include_examples "XSS prevention", "ruby" @@ -80,7 +80,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "highlights as plaintext" do result = filter('
      This is a test
      ') - expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') + expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') end include_examples "XSS prevention", "gnuplot" @@ -93,7 +93,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl result = filter(%(
      This is a test
      )) copy_code_btn = '' unless lang == 'suggestion' - expect(result.to_html.delete("\n")).to eq(%(
      This is a test
      #{copy_code_btn}
      )) + expect(result.to_html.delete("\n")).to eq(%(
      This is a test
      #{copy_code_btn}
      )) end include_examples "XSS prevention", lang @@ -105,13 +105,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "includes it in the highlighted code block" do result = filter('
      This is a test
      ') - expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') + expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') end it "escape sourcepos metadata to prevent XSS" do result = filter('
      ') - expect(result.to_html.delete("\n")).to eq('
      ') + expect(result.to_html.delete("\n")).to eq('
      ') end end @@ -125,7 +125,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl it "highlights as plaintext" do result = filter('
      This is a test
      ') - expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') + expect(result.to_html.delete("\n")).to eq('
      This is a test
      ') end include_examples "XSS prevention", "ruby" diff --git a/spec/lib/click_house/write_buffer_spec.rb b/spec/lib/click_house/write_buffer_spec.rb new file mode 100644 index 00000000000..31a6f9caedc --- /dev/null +++ b/spec/lib/click_house/write_buffer_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ClickHouse::WriteBuffer, :clean_gitlab_redis_shared_state, feature_category: :database do + describe '.write_event' do + subject(:write_event) { described_class.write_event(event_hash) } + + let(:event_hash) { { foo: 'bar' } } + + it 'saves ClickHouse event to Redis' do + expect do + write_event + end.to change { + Gitlab::Redis::SharedState.with do |redis| + redis.lrange(described_class::BUFFER_KEY, 0, 10) + end + }.from([]).to([event_hash.to_json]) + end + end +end diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb index d07ee10cf7f..1dd0260b224 100644 --- a/spec/lib/gitlab/asciidoc_spec.rb +++ b/spec/lib/gitlab/asciidoc_spec.rb @@ -98,7 +98,7 @@ module Gitlab
      -
      +
      @@ -369,7 +369,7 @@ module Gitlab
      -
      console.log('hello world')
      +
      console.log('hello world')
      @@ -399,7 +399,7 @@ module Gitlab
      class.cpp
      -
      #include <stdio.h>
      +            
      #include <stdio.h>
                   
                   for (int i = 0; i < 5; i++) {
                     std::cout<<"*"<<std::endl;
      @@ -457,7 +457,7 @@ module Gitlab
                   stem:[2+2] is 4
                 MD
       
      -          expect(render(input, context)).to include('
      eta_x gamma
      ') + expect(render(input, context)).to include('
      eta_x gamma
      ') expect(render(input, context)).to include('

      2+2 is 4

      ') end end diff --git a/spec/lib/gitlab/ci/pipeline/chain/component_usage_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/component_usage_spec.rb index f4291f4938f..ce27de2db43 100644 --- a/spec/lib/gitlab/ci/pipeline/chain/component_usage_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/chain/component_usage_spec.rb @@ -40,6 +40,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::ComponentUsage, feature_category: :p let(:value) { 1 } # Default resource_type end + it 'creates a component usage record' do + expect { perform }.to change { Ci::Catalog::Resources::Components::Usage.count }.by(1) + end + + context 'when component usage has already been recorded', :freeze_time do + it 'does not create a component usage record' do + step.perform! + + expect { perform }.not_to change { Ci::Catalog::Resources::Components::Usage.count } + end + end + context 'when the FF `ci_track_catalog_component_usage` is disabled' do before do stub_feature_flags(ci_track_catalog_component_usage: false) @@ -50,6 +62,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::ComponentUsage, feature_category: :p perform end + + it 'does not create a component usage record' do + expect { perform }.not_to change { Ci::Catalog::Resources::Components::Usage.count } + end end end end diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb index 321a47c0634..1d6ed11c4a2 100644 --- a/spec/lib/gitlab/ci/trace_spec.rb +++ b/spec/lib/gitlab/ci/trace_spec.rb @@ -2,8 +2,8 @@ require 'spec_helper' -RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_default: :keep do - let_it_be(:project) { create_default(:project).freeze } +RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_default: :keep, feature_category: :continuous_integration do + let_it_be(:project) { create_default(:project, :allow_runner_registration_token).freeze } let_it_be_with_reload(:build) { create(:ci_build, :success) } let(:trace) { described_class.new(build) } diff --git a/spec/lib/gitlab/doctor/reset_tokens_spec.rb b/spec/lib/gitlab/doctor/reset_tokens_spec.rb index b2155ee83ad..11e999f2520 100644 --- a/spec/lib/gitlab/doctor/reset_tokens_spec.rb +++ b/spec/lib/gitlab/doctor/reset_tokens_spec.rb @@ -12,9 +12,14 @@ RSpec.describe Gitlab::Doctor::ResetTokens, feature_category: :fleet_visibility let_it_be(:functional_project) { create(:project).tap(&:runners_token) } let_it_be(:functional_group) { create(:group).tap(&:runners_token) } - let(:broken_project) { create(:project).tap { |project| project.update_columns(runners_token_encrypted: 'aaa') } } + let(:broken_project) do + create(:project, :allow_runner_registration_token).tap do |project| + project.update_columns(runners_token_encrypted: 'aaa') + end + end + let(:project_with_cipher_error) do - create(:project).tap do |project| + create(:project, :allow_runner_registration_token).tap do |project| project.update_columns( runners_token_encrypted: '|rXs75DSHXPE9MGAIgyxcut8pZc72gaa/2ojU0GS1+R+cXNqkbUB13Vb5BaMwf47d98980fc1') end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 054dba5d7f6..baa5d0c270f 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -489,7 +489,11 @@ RSpec.describe Group, feature_category: :groups_and_projects do it_behaves_like 'a BulkUsersByEmailLoad model' - it_behaves_like 'ensures runners_token is prefixed', :group + it_behaves_like 'ensures runners_token is prefixed' do + subject(:record) do + create(:group, namespace_settings: create(:namespace_settings, allow_runner_registration_token: true)) + end + end context 'after initialized' do it 'has a group_feature' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 858d4f5512a..f1fc865c7fd 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -14,7 +14,13 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr it_behaves_like 'having unique enum values' - it_behaves_like 'ensures runners_token is prefixed', :project + context 'when runner registration is allowed' do + let_it_be(:project) { create(:project, :allow_runner_registration_token) } + + it_behaves_like 'ensures runners_token is prefixed' do + subject(:record) { project } + end + end describe 'associations' do it { is_expected.to belong_to(:organization) } @@ -1143,15 +1149,24 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr end end - describe 'project token' do - it 'sets an random token if none provided' do - project = FactoryBot.create(:project, runners_token: '') - expect(project.runners_token).not_to eq('') + describe 'runner registration token' do + let(:project) { create(:project, :allow_runner_registration_token, runners_token: initial_token) } + + context 'when no token provided' do + let(:initial_token) { '' } + + it 'sets an random token' do + expect(project.runners_token).not_to be_nil + expect(project.runners_token).not_to eq(initial_token) + end end - it 'does not set an random token if one provided' do - project = FactoryBot.create(:project, runners_token: "#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token") - expect(project.runners_token).to eq("#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token") + context 'when initial token exists' do + let(:initial_token) { "#{RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX}my-token" } + + it 'does not set an random token' do + expect(project.runners_token).to eq(initial_token) + end end end diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index a5fc4bba4fb..e917c2ae0f8 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -1410,6 +1410,14 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it { is_expected.to be_allowed(:register_group_runners) } end + + context 'with specific group runner registration token disallowed' do + before do + group.allow_runner_registration_token = false + end + + it { is_expected.to be_disallowed(:register_group_runners) } + end end end @@ -1438,6 +1446,14 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it { is_expected.to be_disallowed(:register_group_runners) } end + + context 'with specific group runner registration token disallowed' do + before do + group.allow_runner_registration_token = false + end + + it { is_expected.to be_disallowed(:register_group_runners) } + end end context 'with maintainer' do diff --git a/spec/requests/admin/projects_controller_spec.rb b/spec/requests/admin/projects_controller_spec.rb index 16e1827b912..88c95ac5e9d 100644 --- a/spec/requests/admin/projects_controller_spec.rb +++ b/spec/requests/admin/projects_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Admin::ProjectsController, :enable_admin_mode, feature_category: :groups_and_projects do - let_it_be(:project) { create(:project, :public, name: 'test', description: 'test') } + let_it_be(:project) { create(:project, :public, :allow_runner_registration_token, name: 'test', description: 'test') } let_it_be(:admin) { create(:admin) } describe 'PUT #update' do diff --git a/spec/requests/api/ci/runners_reset_registration_token_spec.rb b/spec/requests/api/ci/runners_reset_registration_token_spec.rb index 0b6a6abf419..9baa0052e5d 100644 --- a/spec/requests/api/ci/runners_reset_registration_token_spec.rb +++ b/spec/requests/api/ci/runners_reset_registration_token_spec.rb @@ -132,7 +132,7 @@ RSpec.describe API::Ci::Runners, feature_category: :fleet_visibility do describe '/api/v4/projects/:id/runners/reset_registration_token' do describe 'POST /api/v4/projects/:id/runners/reset_registration_token' do - let_it_be(:project) { create_default(:project) } + let_it_be(:project) { create_default(:project, :allow_runner_registration_token) } let(:prefix) { "/projects/#{project.id}" } diff --git a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb index 4bb92e99019..7faf02d3257 100644 --- a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb +++ b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb @@ -41,6 +41,66 @@ RSpec.describe 'container repository details', feature_category: :container_regi end end + shared_examples 'returning proper responses with different permissions' do |raw_tags:| + context 'with different permissions' do + let_it_be(:user) { create(:user) } + + let(:repository_tags) { instance_exec(&raw_tags) } + let(:tags_response) { container_repository_details_response.dig('tags', 'edges') } + let(:variables) do + { id: container_repository_global_id, n: 'NAME_ASC' } + end + + let(:query) do + <<~GQL + query($id: ContainerRepositoryID!, $n: ContainerRepositoryTagSort) { + containerRepository(id: $id) { + canDelete + tags(sort: $n) { + edges { + node { + #{all_graphql_fields_for('ContainerRepositoryTag')} + } + } + } + } + } + GQL + end + + where(:project_visibility, :role, :access_granted, :can_delete) do + :private | :maintainer | true | true + :private | :developer | true | true + :private | :reporter | true | false + :private | :guest | false | false + :private | :anonymous | false | false + :public | :maintainer | true | true + :public | :developer | true | true + :public | :reporter | true | false + :public | :guest | true | false + :public | :anonymous | true | false + end + + with_them do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false)) + project.add_member(user, role) unless role == :anonymous + end + + it 'return the proper response' do + subject + + if access_granted + expect(tags_response.size).to eq(repository_tags.size) + expect(container_repository_details_response.dig('canDelete')).to eq(can_delete) + else + expect(container_repository_details_response).to eq(nil) + end + end + end + end + end + it_behaves_like 'a working graphql query' do before do subject @@ -51,42 +111,7 @@ RSpec.describe 'container repository details', feature_category: :container_regi end end - context 'with different permissions' do - let_it_be(:user) { create(:user) } - - let(:tags_response) { container_repository_details_response.dig('tags', 'nodes') } - - where(:project_visibility, :role, :access_granted, :can_delete) do - :private | :maintainer | true | true - :private | :developer | true | true - :private | :reporter | true | false - :private | :guest | false | false - :private | :anonymous | false | false - :public | :maintainer | true | true - :public | :developer | true | true - :public | :reporter | true | false - :public | :guest | true | false - :public | :anonymous | true | false - end - - with_them do - before do - project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false)) - project.add_member(user, role) unless role == :anonymous - end - - it 'return the proper response' do - subject - - if access_granted - expect(tags_response.size).to eq(tags.size) - expect(container_repository_details_response.dig('canDelete')).to eq(can_delete) - else - expect(container_repository_details_response).to eq(nil) - end - end - end - end + it_behaves_like 'returning proper responses with different permissions', raw_tags: -> { tags } context 'with a giant size tag' do let(:tags) { %w[latest] } @@ -331,42 +356,7 @@ RSpec.describe 'container repository details', feature_category: :container_regi end end - context 'with different permissions' do # OK - let_it_be(:user) { create(:user) } - - let(:tags_response) { container_repository_details_response.dig('tags', 'nodes') } - - where(:project_visibility, :role, :access_granted, :can_delete) do - :private | :maintainer | true | true - :private | :developer | true | true - :private | :reporter | true | false - :private | :guest | false | false - :private | :anonymous | false | false - :public | :maintainer | true | true - :public | :developer | true | true - :public | :reporter | true | false - :public | :guest | true | false - :public | :anonymous | true | false - end - - with_them do - before do - project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility.to_s.upcase, false)) - project.add_member(user, role) unless role == :anonymous - end - - it 'return the proper response' do - subject - - if access_granted - expect(tags_response.size).to eq(raw_tags_response.size) - expect(container_repository_details_response.dig('canDelete')).to eq(can_delete) - else - expect(container_repository_details_response).to eq(nil) - end - end - end - end + it_behaves_like 'returning proper responses with different permissions', raw_tags: -> { raw_tags_response } context 'querying' do let(:name) { 'l' } diff --git a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb index ef752448966..84baeb035c7 100644 --- a/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb +++ b/spec/requests/api/graphql/mutations/ci/runners_registration_token/reset_spec.rb @@ -62,7 +62,7 @@ RSpec.describe 'RunnersRegistrationTokenReset', feature_category: :fleet_visibil end context 'applied to project' do - let_it_be(:project) { create_default(:project) } + let_it_be(:project) { create_default(:project, :allow_runner_registration_token) } let(:target) { project } let(:input) { { type: 'PROJECT_TYPE', id: project.to_global_id.to_s } } diff --git a/spec/requests/application_controller_spec.rb b/spec/requests/application_controller_spec.rb index 0834f5c5c49..b5c70c83869 100644 --- a/spec/requests/application_controller_spec.rb +++ b/spec/requests/application_controller_spec.rb @@ -13,6 +13,14 @@ RSpec.describe ApplicationController, type: :request, feature_category: :shared subject(:request) { get root_path } end + it 'does not send Link header', :use_clean_rails_redis_caching do + sign_in(user) + + get root_path + + expect(response.headers['Link']).to be_nil + end + describe 'session expiration' do context 'when user is authenticated' do it 'does not set the expire_after option' do diff --git a/spec/services/ci/components/usages/create_service_spec.rb b/spec/services/ci/components/usages/create_service_spec.rb new file mode 100644 index 00000000000..81c96e5598f --- /dev/null +++ b/spec/services/ci/components/usages/create_service_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Ci::Components::Usages::CreateService, feature_category: :pipeline_composition do + let_it_be(:project) { create(:project) } + let_it_be(:component) { create(:ci_catalog_resource_component) } + + let(:service) { described_class.new(component, used_by_project: project) } + + describe '#execute' do + subject(:execute) { service.execute } + + it 'creates a usage record', :aggregate_failures do + expect { execute }.to change { Ci::Catalog::Resources::Components::Usage.count }.by(1) + expect(execute).to be_success + expect(execute.message).to eq('Usage recorded') + + usage = Ci::Catalog::Resources::Components::Usage.find_by(component: component) + + expect(usage.catalog_resource).to eq(component.catalog_resource) + expect(usage.project).to eq(component.project) + expect(usage.used_by_project_id).to eq(project.id) + end + + context 'when usage has already been recorded', :freeze_time do + it 'does not create a usage record' do + service.execute + + expect { execute }.not_to change { Ci::Catalog::Resources::Components::Usage.count } + expect(execute).to be_success + expect(execute.message).to eq('Usage already recorded for today') + end + end + + context 'when usage is invalid' do + it 'does not create a usage record and returns error' do + usage = instance_double( + Ci::Catalog::Resources::Components::Usage, valid?: false, + errors: instance_double(ActiveModel::Errors, full_messages: ['msg 1', 'msg 2'], size: 2)) + + allow(Ci::Catalog::Resources::Components::Usage).to receive(:new).and_return(usage) + + expect { execute }.not_to change { Ci::Catalog::Resources::Components::Usage.count } + expect(execute).to be_error + expect(execute.message).to eq('msg 1, msg 2') + end + end + end +end diff --git a/spec/services/ci/runners/register_runner_service_spec.rb b/spec/services/ci/runners/register_runner_service_spec.rb index aabf30d975a..991de6a449d 100644 --- a/spec/services/ci/runners/register_runner_service_spec.rb +++ b/spec/services/ci/runners/register_runner_service_spec.rb @@ -130,8 +130,8 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute', feature_categor context 'when project registration token is used' do let_it_be(:project) { create(:project, :with_namespace_settings) } + let_it_be(:token) { project.runners_token } - let(:token) { project.runners_token } let(:allow_group_runner_registration_token) { true } before do @@ -209,8 +209,8 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute', feature_categor context 'when group registration token is used' do let_it_be_with_refind(:group) { create(:group) } + let_it_be(:token) { group.runners_token } - let(:token) { group.runners_token } let(:allow_group_runner_registration_token) { true } before do diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 4f11f65b13c..e253c06125f 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -1255,7 +1255,7 @@ RSpec.describe MergeRequests::UpdateService, :mailer, feature_category: :code_re end before do - allow(ProtectedBranch).to receive(:protected?).with(source_project, 'fixes') { false } + allow(ProtectedBranch).to receive(:protected?).and_return(false) end it 'does not allow a maintainer of the target project to set `allow_collaboration`' do diff --git a/spec/support/shared_examples/models/ci/token_format_shared_examples.rb b/spec/support/shared_examples/models/ci/token_format_shared_examples.rb index 7aa7d2be520..2cc9a0ed9f6 100644 --- a/spec/support/shared_examples/models/ci/token_format_shared_examples.rb +++ b/spec/support/shared_examples/models/ci/token_format_shared_examples.rb @@ -1,8 +1,6 @@ # frozen_string_literal: true -RSpec.shared_examples_for 'ensures runners_token is prefixed' do |factory| - subject(:record) { FactoryBot.build(factory) } - +RSpec.shared_examples_for 'ensures runners_token is prefixed' do describe '#runners_token', feature_category: :system_access do let(:runners_prefix) { RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX } @@ -11,7 +9,9 @@ RSpec.shared_examples_for 'ensures runners_token is prefixed' do |factory| end context 'when record has an invalid token' do - subject(:record) { FactoryBot.build(factory, runners_token: invalid_runners_token) } + before do + record.update!(runners_token: invalid_runners_token) + end let(:invalid_runners_token) { "not_start_with_runners_prefix" } diff --git a/spec/tasks/gitlab/doctor/secrets_rake_spec.rb b/spec/tasks/gitlab/doctor/secrets_rake_spec.rb index 123b8745d65..a1df7554e11 100644 --- a/spec/tasks/gitlab/doctor/secrets_rake_spec.rb +++ b/spec/tasks/gitlab/doctor/secrets_rake_spec.rb @@ -7,7 +7,7 @@ RSpec.describe 'gitlab:doctor:reset_encrypted_tokens', :silence_stdout, feature_ let(:token_names) { 'runners_token' } let(:project_with_cipher_error) do - create(:project).tap do |project| + create(:project, :allow_runner_registration_token).tap do |project| project.update_columns(runners_token_encrypted: '|rXs75DSHXPE9MGAIgyxcut8pZc72gaa/2ojU0GS1+R+cXNqkbUB13Vb5BaMwf47d98980fc1') end @@ -26,7 +26,7 @@ RSpec.describe 'gitlab:doctor:reset_encrypted_tokens', :silence_stdout, feature_ run_rake_task('gitlab:doctor:reset_encrypted_tokens') end - it 'properly parces parameters from the environment variables' do + it 'properly parses parameters from the environment variables' do expect_next_instance_of(::Gitlab::Doctor::ResetTokens, anything, model_names: %w[Project Group], token_names: %w[runners_token], diff --git a/spec/tooling/lib/tooling/find_tests_spec.rb b/spec/tooling/lib/tooling/find_tests_spec.rb index 67b6650b335..d0fadcc66b6 100644 --- a/spec/tooling/lib/tooling/find_tests_spec.rb +++ b/spec/tooling/lib/tooling/find_tests_spec.rb @@ -101,7 +101,7 @@ RSpec.describe Tooling::FindTests, feature_category: :tooling do it 'loads the direct matching pattern file' do expect(TestFileFinder::MappingStrategies::DirectMatching) .to receive(:load_json) - .with('crystalball-test/mapping.json') + .with('crystalball-test/mapping.json', limit_min: 14, limit_percentage: 50) subject end diff --git a/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb b/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb index d2a30f2c5c0..eec792ba1f9 100644 --- a/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb +++ b/spec/views/admin/application_settings/ci_cd.html.haml_spec.rb @@ -14,7 +14,7 @@ RSpec.describe 'admin/application_settings/ci_cd.html.haml' do allow(view).to receive(:current_user).and_return(user) end - describe 'CI CD Runners' do + describe 'CI CD Runners', feature_category: :runner do it 'has the setting section' do render @@ -25,10 +25,9 @@ RSpec.describe 'admin/application_settings/ci_cd.html.haml' do render expect(rendered).to have_content("Runner registration") - expect(rendered).to have_content(s_("Runners|If both settings are disabled, new runners cannot be registered.")) - expect(rendered).to have_content( - s_("Runners|Fetch GitLab Runner release version data from GitLab.com") - ) + expect(rendered).to have_content("Allow runner registration token") + expect(rendered).to have_content("Members of the project can create runners") + expect(rendered).to have_content("Members of the group can create runners") end end end diff --git a/tooling/lib/tooling/find_tests.rb b/tooling/lib/tooling/find_tests.rb index 7feb6990aa2..3257e4fd89d 100644 --- a/tooling/lib/tooling/find_tests.rb +++ b/tooling/lib/tooling/find_tests.rb @@ -15,7 +15,14 @@ module Tooling def execute tff = TestFileFinder::FileFinder.new(paths: changed_files).tap do |file_finder| if ENV['RSPEC_TESTS_MAPPING_ENABLED'] == 'true' - file_finder.use TestFileFinder::MappingStrategies::DirectMatching.load_json(ENV['RSPEC_TESTS_MAPPING_PATH']) + # Run 50% of the predictive backend tests for any file changed, with a minimum of 20 backend test files. + # + # See https://gitlab.com/gitlab-org/gitlab/-/issues/450374#note_1836131381 + file_finder.use TestFileFinder::MappingStrategies::DirectMatching.load_json( + ENV['RSPEC_TESTS_MAPPING_PATH'], + limit_percentage: 50, + limit_min: 14 + ) end file_finder.use TestFileFinder::MappingStrategies::PatternMatching.load('tests.yml')