Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-02 06:09:00 +00:00
parent 455e6650ee
commit 03c509e17b
61 changed files with 2077 additions and 1058 deletions

View File

@ -156,7 +156,7 @@ Dangerfile @gl-quality/eng-prod
/app/assets/javascripts/ci_variable_list/ @gitlab-org/ci-cd/verify/frontend
/app/assets/javascripts/pipeline_schedules/ @gitlab-org/ci-cd/verify/frontend
/app/assets/javascripts/pipeline_editor/ @gitlab-org/ci-cd/verify/frontend
/ee/app/assets/javascripts/ci_minutes_usage/ @gitlab-org/ci-cd/verify/frontend
/ee/app/assets/javascripts/ci/ci_minutes_usage/ @gitlab-org/ci-cd/verify/frontend
/ee/app/assets/javascripts/usage_quotas/ci_minutes_usage/ @gitlab-org/ci-cd/verify/frontend
/ee/app/assets/javascripts/usage_quotas/pipelines/ @gitlab-org/ci-cd/verify/frontend
/ee/app/assets/javascripts/reports/ @gitlab-org/ci-cd/verify/frontend

View File

@ -57,46 +57,38 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
# frozen_string_literal: true
class CreateCoolWidgetRegistry < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def change
create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
t.bigint :cool_widget_id, null: false
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :verified_at
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.integer :state, default: 0, null: false, limit: 2
t.integer :verification_state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2, null: false
t.integer :verification_retry_count, default: 0, limit: 2, null: false
t.boolean :checksum_mismatch, default: false, null: false
t.boolean :force_to_redownload, default: false, null: false
t.boolean :missing_on_primary, default: false, null: false
t.binary :verification_checksum
t.binary :verification_checksum_mismatched
t.text :verification_failure, limit: 255
t.text :last_sync_failure, limit: 255
def up
Geo::TrackingBase.transaction do
create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
t.bigint :cool_widget_id, null: false
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :verified_at
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.integer :state, default: 0, null: false, limit: 2
t.integer :verification_state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2, null: false
t.integer :verification_retry_count, default: 0, limit: 2, null: false
t.boolean :checksum_mismatch, default: false, null: false
t.boolean :force_to_redownload, default: false, null: false
t.boolean :missing_on_primary, default: false, null: false
t.binary :verification_checksum
t.binary :verification_checksum_mismatched
t.text :verification_failure, limit: 255
t.text :last_sync_failure, limit: 255
t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
t.index :retry_at
t.index :state
# To optimize performance of CoolWidgetRegistry.verification_failed_batch
t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
# To optimize performance of CoolWidgetRegistry.needs_verification_count
t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
# To optimize performance of CoolWidgetRegistry.verification_pending_batch
t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
end
t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
t.index :retry_at
t.index :state
# To optimize performance of CoolWidgetRegistry.verification_failed_batch
t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
# To optimize performance of CoolWidgetRegistry.needs_verification_count
t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
# To optimize performance of CoolWidgetRegistry.verification_pending_batch
t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
end
end
def down
drop_table :cool_widget_registry
end
end
```

View File

@ -59,44 +59,36 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
# frozen_string_literal: true
class CreateCoolWidgetRegistry < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
def change
create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
t.bigint :cool_widget_id, null: false
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :verified_at
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.integer :state, default: 0, null: false, limit: 2
t.integer :verification_state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2, null: false
t.integer :verification_retry_count, default: 0, limit: 2, null: false
t.boolean :checksum_mismatch, default: false, null: false
t.binary :verification_checksum
t.binary :verification_checksum_mismatched
t.text :verification_failure, limit: 255
t.text :last_sync_failure, limit: 255
def up
Geo::TrackingBase.transaction do
create_table :cool_widget_registry, id: :bigserial, force: :cascade do |t|
t.bigint :cool_widget_id, null: false
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :last_synced_at
t.datetime_with_timezone :retry_at
t.datetime_with_timezone :verified_at
t.datetime_with_timezone :verification_started_at
t.datetime_with_timezone :verification_retry_at
t.integer :state, default: 0, null: false, limit: 2
t.integer :verification_state, default: 0, null: false, limit: 2
t.integer :retry_count, default: 0, limit: 2, null: false
t.integer :verification_retry_count, default: 0, limit: 2, null: false
t.boolean :checksum_mismatch, default: false, null: false
t.binary :verification_checksum
t.binary :verification_checksum_mismatched
t.text :verification_failure, limit: 255
t.text :last_sync_failure, limit: 255
t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
t.index :retry_at
t.index :state
# To optimize performance of CoolWidgetRegistry.verification_failed_batch
t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
# To optimize performance of CoolWidgetRegistry.needs_verification_count
t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
# To optimize performance of CoolWidgetRegistry.verification_pending_batch
t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
end
t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
t.index :retry_at
t.index :state
# To optimize performance of CoolWidgetRegistry.verification_failed_batch
t.index :verification_retry_at, name: :cool_widget_registry_failed_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 3))"
# To optimize performance of CoolWidgetRegistry.needs_verification_count
t.index :verification_state, name: :cool_widget_registry_needs_verification, where: "((state = 2) AND (verification_state = ANY (ARRAY[0, 3])))"
# To optimize performance of CoolWidgetRegistry.verification_pending_batch
t.index :verified_at, name: :cool_widget_registry_pending_verification, order: "NULLS FIRST", where: "((state = 2) AND (verification_state = 0))"
end
end
def down
drop_table :cool_widget_registry
end
end
```

View File

@ -47,6 +47,7 @@ export default {
data() {
return {
loadDeferred: false,
skipBeforeUnload: false,
};
},
computed: {
@ -78,9 +79,14 @@ export default {
mounted() {
window.onbeforeunload = (e) => this.onBeforeUnload(e);
eventHub.$on('skip-beforeunload', this.handleSkipBeforeUnload);
if (this.themeName)
document.querySelector('.navbar-gitlab').classList.add(`theme-${this.themeName}`);
},
destroyed() {
eventHub.$off('skip-beforeunload', this.handleSkipBeforeUnload);
},
beforeCreate() {
performanceMarkAndMeasure({
mark: WEBIDE_MARK_APP_START,
@ -94,6 +100,11 @@ export default {
methods: {
...mapActions(['toggleFileFinder']),
onBeforeUnload(e = {}) {
if (this.skipBeforeUnload) {
this.skipBeforeUnload = false;
return undefined;
}
const returnValue = __('Are you sure you want to lose unsaved changes?');
if (!this.someUncommittedChanges) return undefined;
@ -103,6 +114,9 @@ export default {
});
return returnValue;
},
handleSkipBeforeUnload() {
this.skipBeforeUnload = true;
},
openFile(file) {
this.$router.push(this.getUrlForPath(file.path));
},

View File

@ -13,6 +13,11 @@ export default {
required: false,
default: () => [],
},
initOpenView: {
type: String,
required: false,
default: '',
},
side: {
type: String,
required: true,
@ -44,6 +49,9 @@ export default {
return this.tabViews.filter((view) => this.isAliveView(view.name));
},
},
created() {
this.openViewByName(this.initOpenView);
},
methods: {
...mapActions({
toggleOpen(dispatch) {
@ -53,6 +61,13 @@ export default {
return dispatch(`${this.namespace}/open`, view);
},
}),
openViewByName(viewName) {
const view = viewName && this.tabViews.find((x) => x.name === viewName);
if (view) {
this.open(view);
}
},
},
};
</script>

View File

@ -7,6 +7,7 @@ import PipelinesList from '../pipelines/list.vue';
import Clientside from '../preview/clientside.vue';
import ResizablePanel from '../resizable_panel.vue';
import TerminalView from '../terminal/view.vue';
import SwitchEditorsView from '../switch_editors/switch_editors_view.vue';
import CollapsibleSidebar from './collapsible_sidebar.vue';
// Need to add the width of the nav buttons since the resizable container contains those as well
@ -20,7 +21,7 @@ export default {
},
computed: {
...mapState('terminal', { isTerminalVisible: 'isVisible' }),
...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled']),
...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled', 'canUseNewWebIde']),
...mapGetters(['packageJson']),
...mapState('rightPane', ['isOpen']),
showLivePreview() {
@ -28,6 +29,12 @@ export default {
},
rightExtensionTabs() {
return [
{
show: this.canUseNewWebIde,
title: __('Switch editors'),
views: [{ component: SwitchEditorsView, ...rightSidebarViews.switchEditors }],
icon: 'bullhorn',
},
{
show: true,
title: __('Pipelines'),
@ -53,6 +60,7 @@ export default {
},
},
WIDTH,
SWITCH_EDITORS_VIEW_NAME: rightSidebarViews.switchEditors.name,
};
</script>
@ -64,6 +72,11 @@ export default {
:min-size="$options.WIDTH"
:resizable="isOpen"
>
<collapsible-sidebar class="gl-w-full" :extension-tabs="rightExtensionTabs" side="right" />
<collapsible-sidebar
class="gl-w-full"
:extension-tabs="rightExtensionTabs"
:init-open-view="$options.SWITCH_EDITORS_VIEW_NAME"
side="right"
/>
</resizable-panel>
</template>

View File

@ -0,0 +1,103 @@
<script>
import { GlButton, GlEmptyState, GlLink } from '@gitlab/ui';
import { mapState } from 'vuex';
import { createAlert } from '~/flash';
import { logError } from '~/lib/logger';
import axios from '~/lib/utils/axios_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { s__, __ } from '~/locale';
import eventHub from '../../eventhub';
export const MSG_DESCRIPTION = s__('WebIDE|You are invited to experience the new Web IDE.');
export const MSG_BUTTON_TEXT = s__('WebIDE|Switch to new Web IDE');
export const MSG_LEARN_MORE = __('Learn more');
export const MSG_TITLE = s__('WebIDE|Ready for something new?');
export const MSG_CONFIRM = s__(
'WebIDE|Are you sure you want to switch editors? You will lose any unsaved changes.',
);
export const MSG_ERROR_ALERT = s__(
'WebIDE|Something went wrong while updating the user preferences. Please see developer console for details.',
);
export default {
components: {
GlButton,
GlEmptyState,
GlLink,
},
data() {
return {
loading: false,
};
},
computed: {
...mapState(['switchEditorSvgPath', 'links', 'userPreferencesPath']),
},
methods: {
async submitSwitch() {
const confirmed = await confirmAction(MSG_CONFIRM, {
primaryBtnText: __('Switch editors'),
cancelBtnText: __('Cancel'),
});
if (!confirmed) {
return;
}
try {
await axios.put(this.userPreferencesPath, {
user: { use_legacy_web_ide: false },
});
} catch (e) {
// why: We do not want to translate console logs
// eslint-disable-next-line @gitlab/require-i18n-strings
logError('Error while updating user preferences', e);
createAlert({
message: MSG_ERROR_ALERT,
});
return;
}
eventHub.$emit('skip-beforeunload');
window.location.reload();
},
// what: ignoreWhilePending prevents double confirmation boxes
onSwitchClicked: ignoreWhilePending(async function onSwitchClicked() {
this.loading = true;
try {
await this.submitSwitch();
} finally {
this.loading = false;
}
}),
},
MSG_TITLE,
MSG_DESCRIPTION,
MSG_BUTTON_TEXT,
MSG_LEARN_MORE,
};
</script>
<template>
<div class="gl-h-full gl-display-flex gl-flex-direction-column gl-justify-content-center">
<gl-empty-state :svg-path="switchEditorSvgPath" :svg-height="150" :title="$options.MSG_TITLE">
<template #description>
<span>{{ $options.MSG_DESCRIPTION }}</span>
<gl-link :href="links.newWebIDEHelpPagePath">{{ $options.MSG_LEARN_MORE }}</gl-link
>.
</template>
<template #actions>
<gl-button
category="primary"
variant="confirm"
:loading="loading"
@click="onSwitchClicked"
>{{ $options.MSG_BUTTON_TEXT }}</gl-button
>
</template>
</gl-empty-state>
</div>
</template>

View File

@ -61,6 +61,7 @@ export const leftSidebarViews = {
};
export const rightSidebarViews = {
switchEditors: { name: 'switch-editors', keepAlive: true },
pipelines: { name: 'pipelines-list', keepAlive: true },
jobsDetail: { name: 'jobs-detail', keepAlive: false },
mergeRequestInfo: { name: 'merge-request-info', keepAlive: true },

View File

@ -60,9 +60,11 @@ export const initLegacyWebIDE = (el, options = {}) => {
committedStateSvgPath: el.dataset.committedStateSvgPath,
pipelinesEmptyStateSvgPath: el.dataset.pipelinesEmptyStateSvgPath,
promotionSvgPath: el.dataset.promotionSvgPath,
switchEditorSvgPath: el.dataset.switchEditorSvgPath,
});
this.setLinks({
webIDEHelpPagePath: el.dataset.webIdeHelpPagePath,
newWebIDEHelpPagePath: el.dataset.newWebIdeHelpPagePath,
forkInfo: el.dataset.forkInfo ? JSON.parse(el.dataset.forkInfo) : null,
});
this.init({
@ -72,6 +74,8 @@ export const initLegacyWebIDE = (el, options = {}) => {
codesandboxBundlerUrl: el.dataset.codesandboxBundlerUrl,
environmentsGuidanceAlertDismissed: !parseBoolean(el.dataset.enableEnvironmentsGuidance),
previewMarkdownPath: el.dataset.previewMarkdownPath,
canUseNewWebIde: parseBoolean(el.dataset.canUseNewWebIde),
userPreferencesPath: el.dataset.userPreferencesPath,
});
},
beforeDestroy() {

View File

@ -110,6 +110,7 @@ export default {
committedStateSvgPath,
pipelinesEmptyStateSvgPath,
promotionSvgPath,
switchEditorSvgPath,
},
) {
Object.assign(state, {
@ -118,6 +119,7 @@ export default {
committedStateSvgPath,
pipelinesEmptyStateSvgPath,
promotionSvgPath,
switchEditorSvgPath,
});
},
[types.TOGGLE_FILE_FINDER](state, fileFindVisible) {

View File

@ -33,4 +33,6 @@ export default () => ({
environmentsGuidanceAlertDismissed: false,
environmentsGuidanceAlertDetected: false,
previewMarkdownPath: '',
userPreferencesPath: '',
canUseNewWebIde: false,
});

View File

@ -0,0 +1,54 @@
import { GlButton } from '@gitlab/ui';
import { MOCK_HTML } from '../../../../../../spec/frontend/vue_shared/components/markdown_drawer/mock_data';
import MarkdownDrawer from './markdown_drawer.vue';
export default {
component: MarkdownDrawer,
title: 'vue_shared/markdown_drawer',
parameters: {
mirage: {
timing: 1000,
handlers: {
get: {
'/help/user/search/global_search/advanced_search_syntax.json': [
200,
{},
{ html: MOCK_HTML },
],
},
},
},
},
};
const createStory = ({ ...options }) => (_, { argTypes }) => ({
components: { MarkdownDrawer, GlButton },
props: Object.keys(argTypes),
data() {
return {
render: false,
};
},
methods: {
toggleDrawer() {
this.$refs.drawer.toggleDrawer();
},
},
mounted() {
window.requestAnimationFrame(() => {
this.render = true;
});
},
template: `
<div v-if="render">
<gl-button @click="toggleDrawer">Open Drawer</gl-button>
<markdown-drawer
:documentPath="'user/search/global_search/advanced_search_syntax.json'"
ref="drawer"
/>
</div>
`,
...options,
});
export const Default = createStory({});

View File

@ -0,0 +1,117 @@
<script>
import { GlSafeHtmlDirective as SafeHtml, GlDrawer, GlAlert, GlSkeletonLoader } from '@gitlab/ui';
import $ from 'jquery';
import '~/behaviors/markdown/render_gfm';
import { s__ } from '~/locale';
import { contentTop } from '~/lib/utils/common_utils';
import { getRenderedMarkdown } from './utils/fetch';
export const cache = {};
export default {
name: 'MarkdownDrawer',
components: {
GlDrawer,
GlAlert,
GlSkeletonLoader,
},
directives: {
SafeHtml,
},
i18n: {
alert: s__('MardownDrawer|Could not fetch help contents.'),
},
props: {
documentPath: {
type: String,
required: true,
},
},
data() {
return {
loading: false,
hasFetchError: false,
title: '',
body: null,
open: false,
};
},
computed: {
drawerOffsetTop() {
return `${contentTop()}px`;
},
},
watch: {
documentPath: {
immediate: true,
handler: 'fetchMarkdown',
},
open(open) {
if (open && this.body) {
this.renderGLFM();
}
},
},
methods: {
async fetchMarkdown() {
const cached = cache[this.documentPath];
this.hasFetchError = false;
this.title = '';
if (cached) {
this.title = cached.title;
this.body = cached.body;
if (this.open) {
this.renderGLFM();
}
} else {
this.loading = true;
const { body, title, hasFetchError } = await getRenderedMarkdown(this.documentPath);
this.title = title;
this.body = body;
this.loading = false;
this.hasFetchError = hasFetchError;
if (this.open) {
this.renderGLFM();
}
cache[this.documentPath] = { title, body };
}
},
renderGLFM() {
this.$nextTick(() => {
$(this.$refs['content-element']).renderGFM();
});
},
closeDrawer() {
this.open = false;
},
toggleDrawer() {
this.open = !this.open;
},
openDrawer() {
this.open = true;
},
},
safeHtmlConfig: {
ADD_TAGS: ['copy-code'],
},
};
</script>
<template>
<gl-drawer :header-height="drawerOffsetTop" :open="open" header-sticky @close="closeDrawer">
<template #title>
<h4 data-testid="title-element" class="gl-m-0">{{ title }}</h4>
</template>
<template #default>
<div v-if="hasFetchError">
<gl-alert :dismissible="false" variant="danger">{{ $options.i18n.alert }}</gl-alert>
</div>
<gl-skeleton-loader v-else-if="loading" />
<div
v-else
ref="content-element"
v-safe-html:[$options.safeHtmlConfig]="body"
class="md"
></div>
</template>
</gl-drawer>
</template>

View File

@ -0,0 +1,32 @@
import * as Sentry from '@sentry/browser';
import { helpPagePath } from '~/helpers/help_page_helper';
import axios from '~/lib/utils/axios_utils';
export const splitDocument = (htmlString) => {
const htmlDocument = new DOMParser().parseFromString(htmlString, 'text/html');
const title = htmlDocument.querySelector('h1')?.innerText;
htmlDocument.querySelector('h1')?.remove();
return {
title,
body: htmlDocument.querySelector('body').innerHTML.toString(),
};
};
export const getRenderedMarkdown = (documentPath) => {
return axios
.get(helpPagePath(documentPath))
.then(({ data }) => {
const { body, title } = splitDocument(data.html);
return {
body,
title,
hasFetchError: false,
};
})
.catch((e) => {
Sentry.captureException(e);
return {
hasFetchError: true,
};
});
};

View File

@ -5,6 +5,7 @@ module IdeHelper
{
'can-use-new-web-ide' => can_use_new_web_ide?.to_s,
'use-new-web-ide' => use_new_web_ide?.to_s,
'new-web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md', anchor: 'vscode-reimplementation'),
'user-preferences-path' => profile_preferences_path,
'branch-name' => @branch
}.merge(use_new_web_ide? ? new_ide_data : legacy_ide_data)
@ -33,6 +34,7 @@ module IdeHelper
'no-changes-state-svg-path' => image_path('illustrations/multi-editor_no_changes_empty.svg'),
'committed-state-svg-path' => image_path('illustrations/multi-editor_all_changes_committed_empty.svg'),
'pipelines-empty-state-svg-path': image_path('illustrations/pipelines_empty.svg'),
'switch-editor-svg-path': image_path('illustrations/rocket-launch-md.svg'),
'promotion-svg-path': image_path('illustrations/web-ide_promotion.svg'),
'ci-help-page-path' => help_page_path('ci/quick_start/index'),
'web-ide-help-page-path' => help_page_path('user/project/web_ide/index.md'),

View File

@ -218,10 +218,6 @@ module Ci
preload(:job_artifacts_archive, :job_artifacts, :tags, project: [:namespace])
end
def extra_accessors
[]
end
def clone_accessors
%i[pipeline project ref tag options name
allow_failure stage stage_idx trigger_request

View File

@ -5,10 +5,10 @@
removal_date: "2022-05-22"
breaking_change: true
body: |
[GitLab Serverless](https://docs.gitlab.com/ee/user/project/clusters/serverless/) is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
GitLab Serverless is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
We decided to remove the GitLab Serverless features as they never really resonated with our users. Besides, given the continuous development of Kubernetes and Knative, our current implementations do not even work with recent versions.
stage: Configure
tiers: [Core, Premium, Ultimate]
issue_url: "https://gitlab.com/groups/gitlab-org/configure/-/epics/6"
documentation_url: "https://docs.gitlab.com/ee/user/project/clusters/serverless/"
documentation_url: "https://gitlab.com/groups/gitlab-org/configure/-/epics/6"

View File

@ -6,11 +6,11 @@
body: | # Do not modify this line, instead modify the lines below.
The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/index.html).
Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects.
Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/web_ide/index.html) for more information, including how to remove the configuration files from existing projects.
# The following items are not published on the docs page, but may be used in the future.
stage: Create # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347137 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/user/project/static_site_editor/ # (optional) This is a link to the current documentation page
documentation_url: https://docs.gitlab.com/ee/user/project/web_ide/index.html # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -14,4 +14,4 @@
stage: Enablement
tiers: [Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350275
documentation_url: https://docs.gitlab.com/ee/integration/elasticsearch.html#version-requirements
documentation_url: https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html#version-requirements

View File

@ -6,7 +6,7 @@
breaking_change: true
reporter: iroussos
body: | # Do not modify this line, instead modify the lines below.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/index.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.
@ -16,4 +16,4 @@
stage: Monitor
tiers: [Free, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/352488
documentation_url: https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html
documentation_url: https://docs.gitlab.com/ee/administration/monitoring/performance/index.html

View File

@ -5,4 +5,4 @@
issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325931'
breaking_change: true
body: |
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora/metrics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).

View File

@ -4,7 +4,7 @@
reporter: jheimbuck_gl
breaking_change: true
body: |
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/ci/testing/code_quality.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
Relevant Issue: [Rename default Browser Performance Testing job](https://gitlab.com/gitlab-org/gitlab/-/issues/225914)
- name: "Code Quality RuboCop support changed"
@ -13,7 +13,7 @@
reporter: jheimbuck_gl
breaking_change: true
body: |
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#rubocop-errors).
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/ci/testing/code_quality.html#rubocop-errors).
Relevant Issue: [Default `codeclimate-rubocop` engine does not support Ruby 2.6+](https://gitlab.com/gitlab-org/ci-cd/codequality/-/issues/28)
- name: "Ruby version changed in `Ruby.gitlab-ci.yml`"

View File

@ -10,7 +10,7 @@
If you use Elasticsearch 6.8, **you must upgrade your Elasticsearch version to 7.x** prior to upgrading to GitLab 15.0.
You should not upgrade to Elasticsearch 8 until you have completed the GitLab 15.0 upgrade.
View the [version requirements](https://docs.gitlab.com/ee/integration/elasticsearch.html#version-requirements) for details.
View the [version requirements](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html#version-requirements) for details.
# The following items are not published on the docs page, but may be used in the future.
stage: "Enablement"
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350275

View File

@ -6,7 +6,7 @@
breaking_change: true
reporter: iroussos
body: | # Do not modify this line, instead modify the lines below.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) has been removed in GitLab 15.0.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/index.html) has been removed in GitLab 15.0.
We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.

View File

@ -8,10 +8,10 @@
stage: create # (required) String value of the stage that the feature was created in. e.g., Growth
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347137 # (required) Link to the deprecation issue in GitLab
body: | # (required) Do not modify this line, instead modify the lines below.
The Static Site Editor was deprecated in GitLab 14.7 and the feature is being removed in GitLab 15.0. Incoming requests to the Static Site Editor will be redirected and open the target file to edit in the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects. We will continue investing in improvements to the Markdown editing experience by [maturing the Content Editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) and making it available as a way to edit content across GitLab.
The Static Site Editor was deprecated in GitLab 14.7 and the feature is being removed in GitLab 15.0. Incoming requests to the Static Site Editor will be redirected and open the target file to edit in the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/web_ide/index.html) for more information, including how to remove the configuration files from existing projects. We will continue investing in improvements to the Markdown editing experience by [maturing the Content Editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) and making it available as a way to edit content across GitLab.
# The following items are not published on the docs page, but may be used in the future.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/ee/user/project/static_site_editor/
documentation_url: https://docs.gitlab.com/ee/user/project/web_ide/index.html
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -23,7 +23,7 @@
self-managed: true
gitlab-com: true
available_in: [Free, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-widget
documentation_link: https://docs.gitlab.com/ee/ci/testing/code_quality.html#code-quality-widget
image_url: https://about.gitlab.com/images/13_6/code_quality_severity.png
published_at: 2020-11-22
release: 13.6

View File

@ -41,12 +41,12 @@
release: 13.10
- name: "DORA4-based lead time for changes"
description: |
Measuring the efficiency of your software development lifecycle is an important step to grow DevOps adoption for any organization. In the previous milestone, we added support for [DORA4-based Deployment Frequency](https://docs.gitlab.com/ee/api/dora4_project_analytics.html). In this release, we are excited to announce the support of a new API for lead time for changes (via merge requests) on the project level. The lead time for changes gives you an indication of how long it takes for code to be committed and deployed to your production environment. Understanding and tracking this data is a great starting point in your journey to continuous improvement in your DevOps process.
Measuring the efficiency of your software development lifecycle is an important step to grow DevOps adoption for any organization. In the previous milestone, we added support for [DORA4-based Deployment Frequency](https://docs.gitlab.com/ee/api/dora/metrics.html). In this release, we are excited to announce the support of a new API for lead time for changes (via merge requests) on the project level. The lead time for changes gives you an indication of how long it takes for code to be committed and deployed to your production environment. Understanding and tracking this data is a great starting point in your journey to continuous improvement in your DevOps process.
stage: Release
self-managed: true
gitlab-com: true
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-merge-request-lead-times
documentation_link: https://docs.gitlab.com/ee/api/dora/metrics.html#list-project-merge-request-lead-times
image_url: https://about.gitlab.com/images/13_10/api.png
published_at: 2021-03-22
release: 13.10

View File

@ -74,7 +74,7 @@
self-managed: true
gitlab-com: true
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#code-quality-in-diff-view
documentation_link: https://docs.gitlab.com/ee/ci/testing/code_quality.html#code-quality-in-diff-view
image_url: https://about.gitlab.com/images/13_12/code-quality-mr-diff-mvc.png
published_at: 2021-05-22
release: 13.12

View File

@ -22,7 +22,7 @@
self-managed: true # Boolean value (true or false)
gitlab-com: true # Boolean value (true or false)
available_in: [Premium, Ultimate] # Array of strings. The Array brackets are required here. e.g., [Free, Starter, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/integration/elasticsearch.html # This is the documentation URL, but can be a URL to a video if there is one
documentation_link: https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html # This is the documentation URL, but can be a URL to a video if there is one
image_url: https://about.gitlab.com/images/15_0/gitlab_advanced_search_is_now_compatible_with_opensearch.png # This should be a full URL, generally taken from the release post content. If a video, use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
published_at: 2022-05-22 # YYYY-MM-DD
release: 15.0 # XX.Y

View File

@ -1079,7 +1079,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/index.html) is deprecated in GitLab 14.8 and scheduled for removal in GitLab 15.0.
We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.
@ -1672,7 +1672,7 @@ Planned removal: GitLab <span class="removal-milestone">15.0</span> (2022-05-22)
The Static Site Editor will no longer be available starting in GitLab 15.0. Improvements to the Markdown editing experience across GitLab will deliver smiliar benefit but with a wider reach. Incoming requests to the Static Site Editor will be redirected to the [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/index.html).
Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects.
Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/web_ide/index.html) for more information, including how to remove the configuration files from existing projects.
</div>
@ -2106,7 +2106,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[GitLab Serverless](https://docs.gitlab.com/ee/user/project/clusters/serverless/) is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
GitLab Serverless is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
We decided to remove the GitLab Serverless features as they never really resonated with our users. Besides, given the continuous development of Kubernetes and Knative, our current implementations do not even work with recent versions.

View File

@ -251,7 +251,7 @@ Elasticsearch 6.8 support has been removed in GitLab 15.0. Elasticsearch 6.8 has
If you use Elasticsearch 6.8, **you must upgrade your Elasticsearch version to 7.x** prior to upgrading to GitLab 15.0.
You should not upgrade to Elasticsearch 8 until you have completed the GitLab 15.0 upgrade.
View the [version requirements](https://docs.gitlab.com/ee/integration/elasticsearch.html#version-requirements) for details.
View the [version requirements](https://docs.gitlab.com/ee/integration/advanced_search/elasticsearch.html#version-requirements) for details.
### End of support for Python 3.6 in Dependency Scanning
@ -444,7 +444,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) has been removed in GitLab 15.0.
[Request profiling](https://docs.gitlab.com/ee/administration/monitoring/performance/index.html) has been removed in GitLab 15.0.
We're working on [consolidating our profiling tools](https://gitlab.com/groups/gitlab-org/-/epics/7327) and making them more easily accessible.
We [evaluated](https://gitlab.com/gitlab-org/gitlab/-/issues/350152) the use of this feature and we found that it is not widely used.
@ -574,7 +574,7 @@ If you installed GitLab from source, verify manually that both servers are confi
### Static Site Editor
The Static Site Editor was deprecated in GitLab 14.7 and the feature is being removed in GitLab 15.0. Incoming requests to the Static Site Editor will be redirected and open the target file to edit in the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects. We will continue investing in improvements to the Markdown editing experience by [maturing the Content Editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) and making it available as a way to edit content across GitLab.
The Static Site Editor was deprecated in GitLab 14.7 and the feature is being removed in GitLab 15.0. Incoming requests to the Static Site Editor will be redirected and open the target file to edit in the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/web_ide/index.html) for more information, including how to remove the configuration files from existing projects. We will continue investing in improvements to the Markdown editing experience by [maturing the Content Editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) and making it available as a way to edit content across GitLab.
### Support for `gitaly['internal_socket_dir']`
@ -849,7 +849,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html#rubocop-errors).
By default, the Code Quality feature has not provided support for Ruby 2.6+ if you're using the Code Quality template. To better support the latest versions of Ruby, the default RuboCop version is updated to add support for Ruby 2.4 through 3.0. As a result, support for Ruby 2.1, 2.2, and 2.3 is removed. You can re-enable support for older versions by [customizing your configuration](https://docs.gitlab.com/ee/ci/testing/code_quality.html#rubocop-errors).
Relevant Issue: [Default `codeclimate-rubocop` engine does not support Ruby 2.6+](https://gitlab.com/gitlab-org/ci-cd/codequality/-/issues/28)
@ -892,7 +892,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
Browser Performance Testing has run in a job named `performance` by default. With the introduction of [Load Performance Testing](https://docs.gitlab.com/ee/ci/testing/code_quality.html) in GitLab 13.2, this naming could be confusing. To make it clear which job is running [Browser Performance Testing](https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html), the default job name is changed from `performance` to `browser_performance` in the template in GitLab 14.0.
Relevant Issue: [Rename default Browser Performance Testing job](https://gitlab.com/gitlab-org/gitlab/-/issues/225914)
@ -1158,7 +1158,7 @@ WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
The [deployment frequency project-level API](https://docs.gitlab.com/ee/api/dora/metrics.html#list-project-deployment-frequencies) endpoint has been deprecated in favor of the [DORA 4 API](https://docs.gitlab.com/ee/api/dora/metrics.html), which consolidates all the metrics under one API with the specific metric as a required field. As a result, the timestamp field, which doesn't allow adding future extensions and causes performance issues, will be removed. With the old API, an example response would be `{ "2021-03-01": 3, "date": "2021-03-01", "value": 3 }`. The first key/value (`"2021-03-01": 3`) will be removed and replaced by the last two (`"date": "2021-03-01", "value": 3`).
### Release description in the Tags API

View File

@ -459,3 +459,12 @@ The Web IDE has a few limitations:
- If the terminal displays **Connection Failure**, then the terminal could not
connect to the runner. Try to stop and restart the terminal. If the
problem persists, double check your runner configuration.
## VSCode Reimplementation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95169) in GitLab 15.4 [with a flag](../../../administration/feature_flags.md) named `vscode_web_ide`. Disabled by default.
As announced in [this blog post](https://about.gitlab.com/blog/2022/05/23/the-future-of-the-gitlab-web-ide/),
the current implementation of the Web IDE will be replaced with a [VSCode inspired implementation](https://gitlab.com/groups/gitlab-org/-/epics/7683).
This effort is currently under development. Follow [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7683) for updates and more information.

View File

@ -2,22 +2,22 @@
02_01_00__preliminaries__tabs__001:
canonical: "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:2-1:13\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
data-sourcepos=\"1:2-1:13\" lang=\"plaintext\" class=\"code highlight js-syntax-highlight
language-plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre class=\"content-editor-code-block undefined code highlight\"><code>foo\tbaz\t\tbim</code></pre>"
02_01_00__preliminaries__tabs__002:
canonical: "<pre><code>foo\tbaz\t\tbim\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:4-1:15\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
data-sourcepos=\"1:4-1:15\" lang=\"plaintext\" class=\"code highlight js-syntax-highlight
language-plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
class=\"line\" lang=\"plaintext\">foo\tbaz\t\tbim</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre class=\"content-editor-code-block undefined code highlight\"><code>foo\tbaz\t\tbim</code></pre>"
02_01_00__preliminaries__tabs__003:
canonical: "<pre><code>a\ta\nὐ\ta\n</code></pre>\n"
static: "<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"1:5-2:9\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
data-sourcepos=\"1:5-2:9\" lang=\"plaintext\" class=\"code highlight js-syntax-highlight
language-plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
class=\"line\" lang=\"plaintext\">a\ta</span>\n<span id=\"LC2\" class=\"line\"
lang=\"plaintext\">ὐ\ta</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: "<pre class=\"content-editor-code-block undefined code highlight\"><code>a\ta\nὐ\ta</code></pre>"
@ -52,7 +52,7 @@
<li data-sourcepos="1:1-3:5">
<p data-sourcepos="1:3-1:5">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:2-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> bar</span></code></pre>
<pre data-sourcepos="3:2-3:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -68,7 +68,7 @@
static: |-
<blockquote data-sourcepos="1:1-1:6" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<pre data-sourcepos="1:3-1:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -86,7 +86,7 @@
<ul data-sourcepos="1:1-1:6" dir="auto">
<li data-sourcepos="1:1-1:6">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-1:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<pre data-sourcepos="1:3-1:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -100,7 +100,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:4" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
<pre data-sourcepos="1:5-2:4" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span>
<span id="LC2" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
@ -221,7 +221,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***</span></code></pre>
<pre data-sourcepos="1:5-1:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">***</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -464,7 +464,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo</span></code></pre>
<pre data-sourcepos="1:5-1:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"># foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -661,7 +661,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-4:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
<pre data-sourcepos="1:5-4:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">Foo</span>
<span id="LC2" class="line" lang="plaintext">---</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">Foo</span></code></pre>
@ -806,7 +806,7 @@
<p>Baz</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="s">Foo</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="s">Foo</span></span></code></pre>
<copy-code></copy-code>
</div>
<h2 data-sourcepos="4:1-6:3" dir="auto">
@ -829,7 +829,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -855,7 +855,7 @@
<hr />
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:5-1:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<hr data-sourcepos="2:1-2:3">
@ -953,7 +953,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:25" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a simple</span>
<pre data-sourcepos="1:5-2:25" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">a simple</span>
<span id="LC2" class="line" lang="plaintext"> indented code block</span></code></pre>
<copy-code></copy-code>
</div>
@ -1007,7 +1007,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-4:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a/&gt;</span>
<pre data-sourcepos="1:5-4:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;a/&gt;</span>
<span id="LC2" class="line" lang="plaintext">*hi*</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">- one</span></code></pre>
@ -1030,7 +1030,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-7:10" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<pre data-sourcepos="1:5-7:10" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext">chunk2</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -1051,7 +1051,7 @@
canonical: "<pre><code>chunk1\n \n chunk2\n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:12" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<pre data-sourcepos="1:5-3:12" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">chunk1</span>
<span id="LC2" class="line" lang="plaintext"> </span>
<span id="LC3" class="line" lang="plaintext"> chunk2</span></code></pre>
<copy-code></copy-code>
@ -1075,7 +1075,7 @@
<p>bar</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:5-1:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="2:1-2:3" dir="auto">bar</p>
@ -1095,13 +1095,13 @@
<h1 data-sourcepos="1:1-1:9" dir="auto">
<a id="user-content-heading" class="anchor" href="#heading" aria-hidden="true"></a>Heading</h1>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="2:5-2:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<h2 data-sourcepos="3:1-5:7" dir="auto">
<a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="5:5-5:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<hr data-sourcepos="6:1-6:4">
@ -1118,7 +1118,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
<pre data-sourcepos="1:5-2:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> foo</span>
<span id="LC2" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
@ -1131,7 +1131,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="3:5-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1140,7 +1140,7 @@
canonical: "<pre><code>foo \n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span></code></pre>
<pre data-sourcepos="1:5-1:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo </span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1152,7 +1152,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<span id="LC2" class="line" lang="plaintext"> &gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -1166,7 +1166,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;</span>
<span id="LC2" class="line" lang="plaintext"> &gt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -1187,7 +1187,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1201,7 +1201,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1215,7 +1215,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1229,7 +1229,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:4" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-4:4" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1241,7 +1241,7 @@
<pre><code></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-1:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-1:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1254,7 +1254,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext">```</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1273,7 +1273,7 @@
static: |-
<blockquote data-sourcepos="1:1-2:5" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-3:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:3-3:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -1285,7 +1285,7 @@
canonical: "<pre><code>\n \n</code></pre>\n"
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre data-sourcepos="1:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext"> </span></code></pre>
<copy-code></copy-code>
</div>
@ -1296,7 +1296,7 @@
<pre><code></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1308,7 +1308,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:2-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:2-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
@ -1323,7 +1323,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-5:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:3-5:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">aaa</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1340,7 +1340,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-5:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:4-5:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext"> aaa</span>
<span id="LC3" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
@ -1357,7 +1357,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
<pre data-sourcepos="1:5-3:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">```</span>
<span id="LC2" class="line" lang="plaintext">aaa</span>
<span id="LC3" class="line" lang="plaintext">```</span></code></pre>
<copy-code></copy-code>
@ -1372,7 +1372,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:1-3:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1383,7 +1383,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-3:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:4-3:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1395,7 +1395,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-3:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext"> ```</span></code></pre>
<copy-code></copy-code>
</div>
@ -1419,7 +1419,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<pre data-sourcepos="1:1-3:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span>
<span id="LC2" class="line" lang="plaintext">~~~ ~~</span></code></pre>
<copy-code></copy-code>
</div>
@ -1435,7 +1435,7 @@
static: |-
<p data-sourcepos="1:1-1:3" dir="auto">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:1-4:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="2:1-4:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:1-5:3" dir="auto">baz</p>
@ -1453,7 +1453,7 @@
<h2 data-sourcepos="1:1-3:3" dir="auto">
<a id="user-content-foo" class="anchor" href="#foo" aria-hidden="true"></a>foo</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:1-5:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:1-5:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<h1 data-sourcepos="6:1-6:5" dir="auto">
@ -1470,7 +1470,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<pre data-sourcepos="1:1-5:3" lang="ruby" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<span id="LC2" class="line" lang="ruby"> <span class="k">return</span> <span class="mi">3</span></span>
<span id="LC3" class="line" lang="ruby"><span class="k">end</span></span></code></pre>
<copy-code></copy-code>
@ -1487,7 +1487,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:7" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<pre data-sourcepos="1:1-5:7" lang="ruby" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">x</span><span class="p">)</span></span>
<span id="LC2" class="line" lang="ruby"> <span class="k">return</span> <span class="mi">3</span></span>
<span id="LC3" class="line" lang="ruby"><span class="k">end</span></span></code></pre>
<copy-code></copy-code>
@ -1501,7 +1501,7 @@
<pre><code class="language-;"></code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-2:4" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang=";" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:1-2:4" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang=";" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1522,7 +1522,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="aa" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="aa" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1533,7 +1533,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` aaa</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">``` aaa</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -1799,7 +1799,7 @@
<p>okay</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<pre lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"></span>
<span id="LC2" class="line" lang="plaintext">import Text.HTML.TagSoup</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">main :: IO ()</span>
@ -1989,8 +1989,8 @@
<pre><code>&lt;!-- foo --&gt;
</code></pre>
static: " \n<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre
data-sourcepos=\"3:5-3:16\" class=\"code highlight js-syntax-highlight language-plaintext\"
lang=\"plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
data-sourcepos=\"3:5-3:16\" lang=\"plaintext\" class=\"code highlight js-syntax-highlight
language-plaintext\" data-canonical-lang=\"\" v-pre=\"true\"><code><span id=\"LC1\"
class=\"line\" lang=\"plaintext\">&lt;!-- foo --&gt;</span></code></pre>\n<copy-code></copy-code>\n</div>"
wysiwyg: |-
<pre class="content-editor-code-block undefined code highlight"><code>&lt;!-- foo --&gt;</code></pre>
@ -2002,7 +2002,7 @@
static: |2-
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span></code></pre>
<pre data-sourcepos="3:5-3:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;div&gt;</span></code></pre>
<copy-code></copy-code>
</div>
</div>
@ -2113,7 +2113,7 @@
<table dir="auto">
<tr>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-8:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;td&gt;</span>
<pre data-sourcepos="5:5-8:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&lt;td&gt;</span>
<span id="LC2" class="line" lang="plaintext"> Hi</span>
<span id="LC3" class="line" lang="plaintext">&lt;/td&gt;</span></code></pre>
<copy-code></copy-code>
@ -2306,7 +2306,7 @@
<p>[foo]</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title"</span></code></pre>
<pre data-sourcepos="1:5-2:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url "title"</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:1-3:5" dir="auto">[foo]</p>
@ -2320,7 +2320,7 @@
<p>[foo]</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[foo]: /url</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:1-5:5" dir="auto">[foo]</p>
@ -2489,7 +2489,7 @@
<p>bbb</p>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<pre data-sourcepos="1:5-1:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">aaa</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="2:1-2:3" dir="auto">bbb</p>
@ -2836,7 +2836,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
<pre data-sourcepos="1:5-3:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">&gt; # Foo</span>
<span id="LC2" class="line" lang="plaintext">&gt; bar</span>
<span id="LC3" class="line" lang="plaintext">&gt; baz</span></code></pre>
<copy-code></copy-code>
@ -2926,12 +2926,12 @@
static: |-
<blockquote data-sourcepos="1:1-1:9" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:7-1:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:7-1:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:5-2:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="2:5-2:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -2947,13 +2947,13 @@
static: |-
<blockquote data-sourcepos="1:1-1:5" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:3-2:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<pre data-sourcepos="1:3-2:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
<p data-sourcepos="2:1-2:3" dir="auto">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<pre data-sourcepos="3:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3184,7 +3184,7 @@
static: |-
<blockquote data-sourcepos="1:1-1:10" dir="auto">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:7-1:10" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<pre data-sourcepos="1:7-1:10" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<copy-code></copy-code>
</div>
</blockquote>
@ -3207,7 +3207,7 @@
<p data-sourcepos="1:1-2:15" dir="auto">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:5-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:5-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:1-6:16" dir="auto">
@ -3237,7 +3237,7 @@
<p data-sourcepos="1:5-2:19">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:9-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:9-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:5-6:20">
@ -3291,7 +3291,7 @@
<li data-sourcepos="1:2-2:0">one</li>
</ul>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-3:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> two</span></code></pre>
<pre data-sourcepos="3:5-3:8" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> two</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3405,7 +3405,7 @@
<li data-sourcepos="1:1-9:9">
<p data-sourcepos="1:5-1:7">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:5-5:7" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:5-5:7" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="7:5-7:7">baz</p>
@ -3433,7 +3433,7 @@
<li data-sourcepos="1:1-6:9">
<p data-sourcepos="1:3-1:5">Foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:7-6:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span>
<pre data-sourcepos="3:7-6:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">baz</span></code></pre>
@ -3507,7 +3507,7 @@
<li data-sourcepos="1:1-3:9">
<p data-sourcepos="1:3-1:5">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:7-3:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:7-3:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3528,7 +3528,7 @@
<li data-sourcepos="1:3-3:14">
<p data-sourcepos="1:8-1:10">foo</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:12-3:14" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="3:12-3:14" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3544,12 +3544,12 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="1:5-2:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:1-3:9" dir="auto">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:13" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:5-5:13" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -3571,12 +3571,12 @@
<ol data-sourcepos="1:1-5:16" dir="auto">
<li data-sourcepos="1:1-5:16">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="1:8-2:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:4-3:12">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:8-5:16" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3598,12 +3598,12 @@
<ol data-sourcepos="1:1-5:16" dir="auto">
<li data-sourcepos="1:1-5:16">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:8-2:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> indented code</span></code></pre>
<pre data-sourcepos="1:8-2:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> indented code</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="3:4-3:12">paragraph</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:8-5:16" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<pre data-sourcepos="5:8-5:16" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">more code</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3669,13 +3669,13 @@
<li data-sourcepos="1:1-2:5">foo</li>
<li data-sourcepos="3:1-6:5">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:3-6:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<pre data-sourcepos="4:3-6:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">bar</span></code></pre>
<copy-code></copy-code>
</div>
</li>
<li data-sourcepos="7:1-8:9">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="8:7-8:9" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">baz</span></code></pre>
<pre data-sourcepos="8:7-8:9" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">baz</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -3803,7 +3803,7 @@
<p data-sourcepos="1:6-2:20">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:10-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:10-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:6-6:21">
@ -3833,7 +3833,7 @@
<p data-sourcepos="1:7-2:21">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:11-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:7-6:22">
@ -3863,7 +3863,7 @@
<p data-sourcepos="1:8-2:22">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:12-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:12-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:8-6:23">
@ -3885,7 +3885,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-6:24" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. A paragraph</span>
<pre data-sourcepos="1:5-6:24" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">1. A paragraph</span>
<span id="LC2" class="line" lang="plaintext"> with two lines.</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext"> indented code</span>
@ -3919,7 +3919,7 @@
<p data-sourcepos="1:7-2:15">A paragraph
with two lines.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="4:11-5:0" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<pre data-sourcepos="4:11-5:0" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">indented code</span></code></pre>
<copy-code></copy-code>
</div>
<blockquote data-sourcepos="6:7-6:22">
@ -4345,7 +4345,7 @@
</ul>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="9:5-9:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<pre data-sourcepos="9:5-9:8" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">code</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4443,7 +4443,7 @@
</li>
</ol>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:5-5:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">3. c</span></code></pre>
<pre data-sourcepos="5:5-5:8" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">3. c</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4573,7 +4573,7 @@
<li data-sourcepos="1:1-1:3">a</li>
<li data-sourcepos="2:1-6:5">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="2:3-6:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">b</span>
<pre data-sourcepos="2:3-6:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">b</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"></span></code></pre>
<copy-code></copy-code>
@ -4650,7 +4650,7 @@
<p data-sourcepos="2:5-2:5">b</p>
</blockquote>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="3:3-5:5" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">c</span></code></pre>
<pre data-sourcepos="3:3-5:5" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">c</span></code></pre>
<copy-code></copy-code>
</div>
</li>
@ -4701,7 +4701,7 @@
<ol data-sourcepos="1:1-5:6" dir="auto">
<li data-sourcepos="1:1-5:6">
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:4-3:6" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:4-3:6" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="5:4-5:6">bar</p>
@ -4848,7 +4848,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:8" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<pre data-sourcepos="1:5-1:8" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4859,7 +4859,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">\[\]</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4899,7 +4899,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="foo+bar" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="foo+bar" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -4989,7 +4989,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="föö" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="föö" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">foo</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -5007,7 +5007,7 @@
</code></pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:5-1:18" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">f&amp;ouml;f&amp;ouml;</span></code></pre>
<pre data-sourcepos="1:5-1:18" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">f&amp;ouml;f&amp;ouml;</span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7741,7 +7741,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">YAML front matter</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">YAML front matter</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7755,7 +7755,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-toml" lang="toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="err">title:</span> <span class="err">TOML</span> <span class="err">front</span> <span class="err">matter</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="toml" class="code highlight js-syntax-highlight language-toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="err">title:</span> <span class="err">TOML</span> <span class="err">front</span> <span class="err">matter</span></span></code></pre>
<copy-code></copy-code>
</div>
wysiwyg: |-
@ -7771,7 +7771,7 @@
</pre>
static: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" class="code highlight js-syntax-highlight language-json" lang="json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<pre data-sourcepos="1:1-5:3" lang="json" class="code highlight js-syntax-highlight language-json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"JSON front matter"</span></span>
<span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
<copy-code></copy-code>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<pre data-sourcepos="1:1-4:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -20,7 +20,7 @@ examples may be split into multiple top-level headings in the future.</p>
<p data-sourcepos="22:1-23:143" dir="auto">See
<a href="https://docs.gitlab.com/ee/user/markdown.html#footnotes" rel="nofollow noreferrer noopener" target="_blank">the footnotes section of the user-facing documentation for GitLab Flavored Markdown</a>.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="25:1-49:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">footnote reference tag [^fortytwo]</span>
<pre data-sourcepos="25:1-49:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">footnote reference tag [^fortytwo]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext">[^fortytwo]: footnote text</span>
<span id="LC4" class="line" lang="plaintext">.</span>
@ -57,7 +57,7 @@ GitLab Flavored Markdown specification.</p>
<p data-sourcepos="63:1-63:80" dir="auto">The following are some basic examples; more examples may be added in the future.</p>
<p data-sourcepos="65:1-65:16" dir="auto">Incomplete task:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="67:1-77:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span>
<pre data-sourcepos="67:1-77:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span>
<span id="LC2" class="line" lang="plaintext">.</span>
<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
@ -70,7 +70,7 @@ GitLab Flavored Markdown specification.</p>
</div>
<p data-sourcepos="79:1-79:15" dir="auto">Completed task:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="81:1-91:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span>
<pre data-sourcepos="81:1-91:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span>
<span id="LC2" class="line" lang="plaintext">.</span>
<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
@ -83,7 +83,7 @@ GitLab Flavored Markdown specification.</p>
</div>
<p data-sourcepos="93:1-93:18" dir="auto">Inapplicable task:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="95:1-107:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<pre data-sourcepos="95:1-107:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<span id="LC2" class="line" lang="plaintext">.</span>
<span id="LC3" class="line" lang="plaintext">&lt;ul&gt;</span>
<span id="LC4" class="line" lang="plaintext">&lt;li&gt;</span>
@ -99,7 +99,7 @@ GitLab Flavored Markdown specification.</p>
<p data-sourcepos="109:1-110:50" dir="auto">Inapplicable task in a "loose" list. Note that the <code>&lt;del&gt;</code> tag is not applied to the
loose text; it has strikethrough applied with CSS.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="112:1-131:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<pre data-sourcepos="112:1-131:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"> text in loose list</span>
<span id="LC4" class="line" lang="plaintext">.</span>
@ -127,7 +127,7 @@ loose text; it has strikethrough applied with CSS.</p>
This data can be used by static site generators like Jekyll, Hugo, and many other applications.</p>
<p data-sourcepos="141:1-141:18" dir="auto">YAML front matter:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="143:1-153:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
<pre data-sourcepos="143:1-153:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
<span id="LC3" class="line" lang="plaintext">---</span>
<span id="LC4" class="line" lang="plaintext">.</span>
@ -140,7 +140,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
</div>
<p data-sourcepos="155:1-155:18" dir="auto">TOML front matter:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="157:1-167:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
<pre data-sourcepos="157:1-167:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
<span id="LC2" class="line" lang="plaintext">title: TOML front matter</span>
<span id="LC3" class="line" lang="plaintext">+++</span>
<span id="LC4" class="line" lang="plaintext">.</span>
@ -153,7 +153,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
</div>
<p data-sourcepos="169:1-169:18" dir="auto">JSON front matter:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="171:1-185:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
<pre data-sourcepos="171:1-185:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
<span id="LC2" class="line" lang="plaintext">{</span>
<span id="LC3" class="line" lang="plaintext"> "title": "JSON front matter"</span>
<span id="LC4" class="line" lang="plaintext">}</span>
@ -170,7 +170,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
</div>
<p data-sourcepos="187:1-187:66" dir="auto">Front matter blocks should be inserted at the top of the document:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="189:1-199:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
<pre data-sourcepos="189:1-199:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext">---</span>
<span id="LC4" class="line" lang="plaintext">title: YAML front matter</span>
@ -183,7 +183,7 @@ This data can be used by static site generators like Jekyll, Hugo, and many othe
</div>
<p data-sourcepos="201:1-201:74" dir="auto">Front matter block delimiters shouldnt be preceded by space characters:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="203:1-210:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
<pre data-sourcepos="203:1-210:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
<span id="LC3" class="line" lang="plaintext">---</span>
<span id="LC4" class="line" lang="plaintext">.</span>
@ -209,7 +209,7 @@ Add either the <code>[[_TOC_]]</code> or </p><ul class="section-nav">
</li>
</ul> tag on its own line.
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="221:1-238:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
<pre data-sourcepos="221:1-238:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -228,7 +228,7 @@ Add either the <code>[[_TOC_]]</code> or </p><ul class="section-nav">
<copy-code></copy-code>
</div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="240:1-257:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<pre data-sourcepos="240:1-257:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
<span id="LC4" class="line" lang="plaintext"></span>
@ -249,7 +249,7 @@ Add either the <code>[[_TOC_]]</code> or </p><ul class="section-nav">
<p data-sourcepos="259:1-260:5" dir="auto">A table of contents is a block element. It should preceded and followed by a blank
line.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="262:1-271:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<pre data-sourcepos="262:1-271:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext">text</span>
<span id="LC3" class="line" lang="plaintext"></span>
<span id="LC4" class="line" lang="plaintext">text</span>
@ -261,7 +261,7 @@ line.</p>
</div>
<p data-sourcepos="273:1-273:60" dir="auto">A table of contents can be indented with up to three spaces.</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="275:1-286:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
<pre data-sourcepos="275:1-286:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
<span id="LC2" class="line" lang="plaintext"></span>
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
<span id="LC4" class="line" lang="plaintext">.</span>

View File

@ -10,7 +10,7 @@ module Banzai
# HTML filter that implements our math syntax, adding class="code math"
#
class MathFilter < HTML::Pipeline::Filter
CSS_MATH = 'pre.code.language-math'
CSS_MATH = 'pre[lang="math"] > code'
XPATH_MATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_MATH).freeze
CSS_CODE = 'code'
XPATH_CODE = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_CODE).freeze
@ -125,9 +125,10 @@ module Banzai
# corresponds to the "```math...```" syntax
def process_math_codeblock
doc.xpath(XPATH_MATH).each do |el|
el[STYLE_ATTRIBUTE] = 'display'
el[:class] += " #{TAG_CLASS}"
doc.xpath(XPATH_MATH).each do |node|
pre_node = node.parent
pre_node[STYLE_ATTRIBUTE] = 'display'
pre_node[:class] = TAG_CLASS
end
end

View File

@ -14,8 +14,9 @@ module Banzai
LANG_PARAMS_DELIMITER = ':'
LANG_PARAMS_ATTR = 'data-lang-params'
CSS_CLASSES = 'code highlight js-syntax-highlight'
CSS = 'pre:not([data-math-style]):not([data-mermaid-style]):not([data-kroki-style]) > code:only-child'
CSS = 'pre:not([data-kroki-style]) > code:only-child'
XPATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS).freeze
def call
@ -27,9 +28,7 @@ module Banzai
end
def highlight_node(node)
css_classes = +'code highlight js-syntax-highlight'
lang, lang_params = parse_lang_params(node)
sourcepos = node.parent.attr('data-sourcepos')
retried = false
if use_rouge?(lang)
@ -42,7 +41,6 @@ module Banzai
begin
code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, node.text), tag: language)
css_classes << " language-#{language}" if language
rescue StandardError
# Gracefully handle syntax highlighter bugs/errors to ensure users can
# still access an issue/comment/etc. First, retry with the plain text
@ -57,16 +55,26 @@ module Banzai
retry
end
sourcepos_attr = sourcepos ? "data-sourcepos=\"#{escape_once(sourcepos)}\"" : ''
# maintain existing attributes already added. e.g math and mermaid nodes
node.children = code
pre_node = node.parent
highlighted = %(<div class="gl-relative markdown-code-block js-markdown-code"><pre #{sourcepos_attr} class="#{css_classes}"
lang="#{language}"
#{lang != language ? "data-canonical-lang=\"#{escape_once(lang)}\"" : ""}
#{lang_params}
v-pre="true"><code>#{code}</code></pre><copy-code></copy-code></div>)
# ensure there are no extra children, such as a text node that might
# show up from an XSS attack
pre_node.children = node
pre_node[:lang] = language
pre_node.add_class(CSS_CLASSES)
pre_node.add_class("language-#{language}") if language
pre_node.set_attribute('data-canonical-lang', escape_once(lang)) if lang != language
pre_node.set_attribute(LANG_PARAMS_ATTR, escape_once(lang_params)) if lang_params.present?
pre_node.set_attribute('v-pre', 'true')
pre_node.remove_attribute('data-meta')
highlighted = %(<div class="gl-relative markdown-code-block js-markdown-code">#{pre_node.to_html}<copy-code></copy-code></div>)
# Extracted to a method to measure it
replace_parent_pre_element(node, highlighted)
replace_pre_element(pre_node, highlighted)
end
private
@ -94,9 +102,8 @@ module Banzai
language, language_params = language.split(LANG_PARAMS_DELIMITER, 2)
language_params = [node.attr('data-meta'), language_params].compact.join(' ')
formatted_language_params = format_language_params(language_params)
[language, formatted_language_params]
[language, language_params]
end
# Separate method so it can be instrumented.
@ -108,20 +115,14 @@ module Banzai
(Rouge::Lexer.find(language) || Rouge::Lexers::PlainText).new
end
# Replace the parent `pre` element with the entire highlighted block
def replace_parent_pre_element(node, highlighted)
node.parent.replace(highlighted)
# Replace the `pre` element with the entire highlighted block
def replace_pre_element(pre_node, highlighted)
pre_node.replace(highlighted)
end
def use_rouge?(language)
(%w(math suggestion) + ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES).exclude?(language)
end
def format_language_params(language_params)
return if language_params.blank?
%(#{LANG_PARAMS_ATTR}="#{escape_once(language_params)}")
end
end
end
end

View File

@ -7,13 +7,13 @@ module Banzai
FilterArray[
Filter::AsciiDocSanitizationFilter,
Filter::AssetProxyFilter,
Filter::SyntaxHighlightFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
Filter::ColorFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
Filter::WikiLinkFilter,
Filter::SyntaxHighlightFilter,
Filter::AsciiDocPostProcessingFilter
]
end

View File

@ -17,7 +17,6 @@ module Banzai
Filter::SanitizationFilter,
Filter::KrokiFilter,
Filter::AssetProxyFilter,
Filter::SyntaxHighlightFilter,
Filter::MathFilter,
Filter::ColorFilter,
Filter::MermaidFilter,
@ -37,7 +36,8 @@ module Banzai
Filter::CustomEmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
Filter::SetDirectionFilter
Filter::SetDirectionFilter,
Filter::SyntaxHighlightFilter
]
end

View File

@ -1,4 +1,4 @@
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
# Read more about the feature here: https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html
browser_performance:
stage: performance

View File

@ -1,4 +1,4 @@
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
# Read more about the feature here: https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html
browser_performance:
stage: performance

View File

@ -3,7 +3,7 @@
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.gitlab-ci.yml
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
# Read more about the feature here: https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html
stages:
- build

View File

@ -3,7 +3,7 @@
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Browser-Performance.latest.gitlab-ci.yml
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
# Read more about the feature here: https://docs.gitlab.com/ee/ci/testing/browser_performance_testing.html
stages:
- build

View File

@ -3,7 +3,7 @@
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Verify/Load-Performance-Testing.gitlab-ci.yml
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/load_performance_testing.html
# Read more about the feature here: https://docs.gitlab.com/ee/ci/testing/code_quality.html
stages:
- build

View File

@ -24783,6 +24783,9 @@ msgstr ""
msgid "March"
msgstr ""
msgid "MardownDrawer|Could not fetch help contents."
msgstr ""
msgid "Mark as done"
msgstr ""
@ -39618,6 +39621,9 @@ msgstr ""
msgid "Switch branch/tag"
msgstr ""
msgid "Switch editors"
msgstr ""
msgid "Switch to GitLab Next"
msgstr ""
@ -45286,6 +45292,9 @@ msgstr ""
msgid "WebAuthn only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
msgid "WebIDE|Are you sure you want to switch editors? You will lose any unsaved changes."
msgstr ""
msgid "WebIDE|Fork project"
msgstr ""
@ -45301,12 +45310,24 @@ msgstr ""
msgid "WebIDE|Quickly and easily edit multiple files in your project. Press . to open"
msgstr ""
msgid "WebIDE|Ready for something new?"
msgstr ""
msgid "WebIDE|Something went wrong while updating the user preferences. Please see developer console for details."
msgstr ""
msgid "WebIDE|Switch to new Web IDE"
msgstr ""
msgid "WebIDE|This project does not accept unsigned commits."
msgstr ""
msgid "WebIDE|This project does not accept unsigned commits. You cant commit changes through the Web IDE."
msgstr ""
msgid "WebIDE|You are invited to experience the new Web IDE."
msgstr ""
msgid "WebIDE|You cant edit files directly in this project. Fork this project and submit a merge request with your changes."
msgstr ""

View File

@ -3,47 +3,90 @@
require 'spec_helper'
RSpec.describe 'IDE', :js do
describe 'sub-groups' do
let(:ide_iframe_selector) { '#ide iframe' }
let(:user) { create(:user) }
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let(:subgroup_project) { create(:project, :repository, namespace: subgroup) }
include WebIdeSpecHelpers
before do
stub_feature_flags(vscode_web_ide: vscode_ff)
subgroup_project.add_maintainer(user)
sign_in(user)
let_it_be(:ide_iframe_selector) { '#ide iframe' }
let_it_be(:normal_project) { create(:project, :repository) }
visit project_path(subgroup_project)
let(:project) { normal_project }
let(:vscode_ff) { false }
let(:user) { create(:user) }
click_link('Web IDE')
before do
project.add_maintainer(user)
stub_feature_flags(vscode_web_ide: vscode_ff)
wait_for_requests
sign_in(user)
end
shared_examples "legacy Web IDE" do
it 'loads legacy Web IDE', :aggregate_failures do
expect(page).to have_selector('.context-header', text: project.name)
# Assert new Web IDE is not loaded
expect(page).not_to have_selector(ide_iframe_selector)
end
end
context 'with vscode feature flag on' do
let(:vscode_ff) { true }
shared_examples "new Web IDE" do
it 'loads new Web IDE', :aggregate_failures do
expect(page).not_to have_selector('.context-header')
it 'loads project in Web IDE' do
iframe = find(ide_iframe_selector)
iframe = find(ide_iframe_selector)
page.within_frame(iframe) do
expect(page).to have_selector('.title', text: subgroup_project.name.upcase)
end
end
end
context 'with vscode feature flag off' do
let(:vscode_ff) { false }
it 'loads project in legacy Web IDE' do
expect(page).to have_selector('.context-header', text: subgroup_project.name)
end
it 'does not load new Web IDE' do
expect(page).not_to have_selector(ide_iframe_selector)
page.within_frame(iframe) do
expect(page).to have_selector('.title', text: project.name.upcase)
end
end
end
context 'with vscode feature flag off' do
before do
ide_visit(project)
end
it_behaves_like 'legacy Web IDE'
it 'does not show switch button' do
expect(page).not_to have_button('Switch to new Web IDE')
end
end
context 'with vscode feature flag on and use_legacy_web_ide=true' do
let(:vscode_ff) { true }
let(:user) { create(:user, use_legacy_web_ide: true) }
before do
ide_visit(project)
end
it_behaves_like 'legacy Web IDE'
describe 'when user switches to new Web IDE' do
before do
click_button('Switch to new Web IDE')
# Confirm modal
page.within('#confirmationModal') do
click_button('Switch editors')
end
end
it_behaves_like 'new Web IDE'
end
end
describe 'sub-groups' do
let_it_be(:group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:subgroup_project) { create(:project, :repository, namespace: subgroup) }
let(:project) { subgroup_project }
before do
ide_visit(project)
end
it_behaves_like 'legacy Web IDE'
end
end

View File

@ -297,7 +297,7 @@
```
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-javascript" lang="javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="javascript" class="code highlight js-syntax-highlight language-javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -308,7 +308,7 @@
```
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> plaintext</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> plaintext</span></code></pre>
<copy-code></copy-code>
</div>
@ -319,7 +319,7 @@
```
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="foobar" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> custom_language = &gt;&gt; this &lt;&lt;</span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="foobar" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> custom_language = &gt;&gt; this &lt;&lt;</span></code></pre>
<copy-code></copy-code>
</div>
@ -531,7 +531,7 @@
;;;
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" class="code highlight js-syntax-highlight language-json" lang="json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<pre data-sourcepos="1:1-5:3" lang="json" class="code highlight js-syntax-highlight language-json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
<span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Page title"</span></span>
<span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
<copy-code></copy-code>
@ -544,7 +544,7 @@
+++
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-toml" lang="toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="py">title</span> <span class="p">=</span> <span class="s">"Page title"</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="toml" class="code highlight js-syntax-highlight language-toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="py">title</span> <span class="p">=</span> <span class="s">"Page title"</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -555,7 +555,7 @@
---
html: |-
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">Page title</span></span></code></pre>
<pre data-sourcepos="1:1-3:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">Page title</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -690,7 +690,7 @@
<p data-sourcepos="1:1-1:36" dir="auto">This math is inline <code class="code math js-render-math" data-math-style="inline">a^2+b^2=c^2</code>.</p>
<p data-sourcepos="3:1-3:27" dir="auto">This is on a separate line:</p>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="5:1-7:3" class="code highlight js-syntax-highlight language-math js-render-math" lang="math" v-pre="true" data-math-style="display"><code><span id="LC1" class="line" lang="math">a^2+b^2=c^2</span></code></pre>
<pre data-sourcepos="5:1-7:3" lang="math" data-math-style="display" class="js-render-math code highlight js-syntax-highlight language-math" v-pre="true"><code><span id="LC1" class="line" lang="math">a^2+b^2=c^2</span></code></pre>
<copy-code></copy-code>
</div>

View File

@ -3,9 +3,11 @@ import Vue from 'vue';
import Vuex from 'vuex';
import waitForPromises from 'helpers/wait_for_promises';
import { stubPerformanceWebAPI } from 'helpers/performance';
import { __ } from '~/locale';
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
import ErrorMessage from '~/ide/components/error_message.vue';
import Ide from '~/ide/components/ide.vue';
import eventHub from '~/ide/eventhub';
import { MSG_CANNOT_PUSH_CODE_GO_TO_FORK, MSG_GO_TO_FORK } from '~/ide/messages';
import { createStore } from '~/ide/stores';
import { file } from '../helpers';
@ -14,6 +16,7 @@ import { projectData } from '../mock_data';
Vue.use(Vuex);
const TEST_FORK_IDE_PATH = '/test/ide/path';
const MSG_ARE_YOU_SURE = __('Are you sure you want to lose unsaved changes?');
describe('WebIDE', () => {
const emptyProjData = { ...projectData, empty_repo: true, branches: {} };
@ -40,6 +43,8 @@ describe('WebIDE', () => {
const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
const callOnBeforeUnload = (e = {}) => window.onbeforeunload(e);
beforeEach(() => {
stubPerformanceWebAPI();
@ -49,6 +54,7 @@ describe('WebIDE', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
window.onbeforeunload = null;
});
describe('ide component, empty repo', () => {
@ -90,7 +96,8 @@ describe('WebIDE', () => {
describe('onBeforeUnload', () => {
it('returns undefined when no staged files or changed files', () => {
createComponent();
expect(wrapper.vm.onBeforeUnload()).toBe(undefined);
expect(callOnBeforeUnload()).toBe(undefined);
});
it('returns warning text when their are changed files', () => {
@ -100,7 +107,10 @@ describe('WebIDE', () => {
},
});
expect(wrapper.vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
const e = {};
expect(callOnBeforeUnload(e)).toBe(MSG_ARE_YOU_SURE);
expect(e.returnValue).toBe(MSG_ARE_YOU_SURE);
});
it('returns warning text when their are staged files', () => {
@ -110,20 +120,27 @@ describe('WebIDE', () => {
},
});
expect(wrapper.vm.onBeforeUnload()).toBe('Are you sure you want to lose unsaved changes?');
const e = {};
expect(callOnBeforeUnload(e)).toBe(MSG_ARE_YOU_SURE);
expect(e.returnValue).toBe(MSG_ARE_YOU_SURE);
});
it('updates event object', () => {
const event = {};
it('returns undefined once after "skip-beforeunload" was emitted', () => {
createComponent({
state: {
stagedFiles: [file()],
},
});
wrapper.vm.onBeforeUnload(event);
eventHub.$emit('skip-beforeunload');
const e = {};
expect(event.returnValue).toBe('Are you sure you want to lose unsaved changes?');
expect(callOnBeforeUnload()).toBe(undefined);
expect(e.returnValue).toBe(undefined);
expect(callOnBeforeUnload(e)).toBe(MSG_ARE_YOU_SURE);
expect(e.returnValue).toBe(MSG_ARE_YOU_SURE);
});
});

View File

@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import IdeSidebarNav from '~/ide/components/ide_sidebar_nav.vue';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
@ -127,5 +127,29 @@ describe('ide/components/panes/collapsible_sidebar.vue', () => {
});
});
});
describe('with initOpenView that does not exist', () => {
beforeEach(async () => {
createComponent({ extensionTabs, initOpenView: 'does-not-exist' });
await nextTick();
});
it('nothing is dispatched', () => {
expect(store.dispatch).not.toHaveBeenCalled();
});
});
describe('with initOpenView that does exist', () => {
beforeEach(async () => {
createComponent({ extensionTabs, initOpenView: fakeView.name });
await nextTick();
});
it('dispatches open with view on create', () => {
expect(store.dispatch).toHaveBeenCalledWith('rightPane/open', fakeView);
});
});
});
});

View File

@ -3,12 +3,16 @@ import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
import CollapsibleSidebar from '~/ide/components/panes/collapsible_sidebar.vue';
import RightPane from '~/ide/components/panes/right.vue';
import SwitchEditorsView from '~/ide/components/switch_editors/switch_editors_view.vue';
import { rightSidebarViews } from '~/ide/constants';
import { createStore } from '~/ide/stores';
import extendStore from '~/ide/stores/extend';
import { __ } from '~/locale';
Vue.use(Vuex);
const SWITCH_EDITORS_VIEW_NAME = 'switch-editors';
describe('ide/components/panes/right.vue', () => {
let wrapper;
let store;
@ -33,6 +37,19 @@ describe('ide/components/panes/right.vue', () => {
wrapper = null;
});
describe('default', () => {
beforeEach(() => {
createComponent();
});
it('renders collapsible-sidebar', () => {
expect(wrapper.findComponent(CollapsibleSidebar).props()).toMatchObject({
side: 'right',
initOpenView: SWITCH_EDITORS_VIEW_NAME,
});
});
});
describe('pipelines tab', () => {
it('is always shown', () => {
createComponent();
@ -113,4 +130,32 @@ describe('ide/components/panes/right.vue', () => {
);
});
});
describe('switch editors tab', () => {
beforeEach(() => {
createComponent();
});
it.each`
desc | canUseNewWebIde | expectedShow
${'is shown'} | ${true} | ${true}
${'is not shown'} | ${false} | ${false}
`('with canUseNewWebIde=$canUseNewWebIde, $desc', async ({ canUseNewWebIde, expectedShow }) => {
Object.assign(store.state, { canUseNewWebIde });
await nextTick();
expect(wrapper.findComponent(CollapsibleSidebar).props('extensionTabs')).toEqual(
expect.arrayContaining([
expect.objectContaining({
show: expectedShow,
title: __('Switch editors'),
views: [
{ component: SwitchEditorsView, name: SWITCH_EDITORS_VIEW_NAME, keepAlive: true },
],
}),
]),
);
});
});
});

View File

@ -0,0 +1,214 @@
import { GlButton, GlEmptyState, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { logError } from '~/lib/logger';
import { __ } from '~/locale';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import SwitchEditorsView, {
MSG_ERROR_ALERT,
MSG_CONFIRM,
MSG_TITLE,
MSG_LEARN_MORE,
MSG_DESCRIPTION,
} from '~/ide/components/switch_editors/switch_editors_view.vue';
import eventHub from '~/ide/eventhub';
import { createStore } from '~/ide/stores';
jest.mock('~/flash');
jest.mock('~/lib/logger');
jest.mock('~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal');
const TEST_USER_PREFERENCES_PATH = '/test/user-pref/path';
const TEST_SWITCH_EDITOR_SVG_PATH = '/test/switch/editor/path.svg';
const TEST_HREF = '/test/new/web/ide/href';
describe('~/ide/components/switch_editors/switch_editors_view.vue', () => {
useMockLocationHelper();
let store;
let wrapper;
let confirmResolve;
let requestSpy;
let skipBeforeunloadSpy;
let axiosMock;
// region: finders ------------------
const findButton = () => wrapper.findComponent(GlButton);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
// region: actions ------------------
const triggerSwitchPreference = () => findButton().vm.$emit('click');
const submitConfirm = async (val) => {
confirmResolve(val);
// why: We need to wait for promises for the immediate next lines to be executed
await waitForPromises();
};
const createComponent = () => {
wrapper = shallowMount(SwitchEditorsView, {
store,
stubs: {
GlEmptyState,
},
});
};
// region: test setup ------------------
beforeEach(() => {
// Setup skip-beforeunload side-effect
skipBeforeunloadSpy = jest.fn();
eventHub.$on('skip-beforeunload', skipBeforeunloadSpy);
// Setup request side-effect
requestSpy = jest.fn().mockImplementation(() => new Promise(() => {}));
axiosMock = new MockAdapter(axios);
axiosMock.onPut(TEST_USER_PREFERENCES_PATH).reply(({ data }) => requestSpy(data));
// Setup store
store = createStore();
store.state.userPreferencesPath = TEST_USER_PREFERENCES_PATH;
store.state.switchEditorSvgPath = TEST_SWITCH_EDITOR_SVG_PATH;
store.state.links = {
newWebIDEHelpPagePath: TEST_HREF,
};
// Setup user confirm side-effect
confirmAction.mockImplementation(
() =>
new Promise((resolve) => {
confirmResolve = resolve;
}),
);
});
afterEach(() => {
eventHub.$off('skip-beforeunload', skipBeforeunloadSpy);
axiosMock.restore();
});
// region: tests ------------------
describe('default', () => {
beforeEach(() => {
createComponent();
});
it('render empty state', () => {
expect(findEmptyState().props()).toMatchObject({
svgPath: TEST_SWITCH_EDITOR_SVG_PATH,
svgHeight: 150,
title: MSG_TITLE,
});
});
it('render link', () => {
expect(wrapper.findComponent(GlLink).attributes('href')).toBe(TEST_HREF);
expect(wrapper.findComponent(GlLink).text()).toBe(MSG_LEARN_MORE);
});
it('renders description', () => {
expect(findEmptyState().text()).toContain(MSG_DESCRIPTION);
});
it('is not loading', () => {
expect(findButton().props('loading')).toBe(false);
});
});
describe('when user triggers switch preference', () => {
beforeEach(() => {
createComponent();
triggerSwitchPreference();
});
it('creates a single confirm', () => {
// Call again to ensure that we only show 1 confirm action
triggerSwitchPreference();
expect(confirmAction).toHaveBeenCalledTimes(1);
expect(confirmAction).toHaveBeenCalledWith(MSG_CONFIRM, {
primaryBtnText: __('Switch editors'),
cancelBtnText: __('Cancel'),
});
});
it('starts loading', () => {
expect(findButton().props('loading')).toBe(true);
});
describe('when user cancels confirm', () => {
beforeEach(async () => {
await submitConfirm(false);
});
it('does not make request', () => {
expect(requestSpy).not.toHaveBeenCalled();
});
it('can be triggered again', () => {
triggerSwitchPreference();
expect(confirmAction).toHaveBeenCalledTimes(2);
});
});
describe('when user accepts confirm and response success', () => {
beforeEach(async () => {
requestSpy.mockReturnValue([200, {}]);
await submitConfirm(true);
});
it('does not handle error', () => {
expect(logError).not.toHaveBeenCalled();
expect(createAlert).not.toHaveBeenCalled();
});
it('emits "skip-beforeunload" and reloads', () => {
expect(skipBeforeunloadSpy).toHaveBeenCalledTimes(1);
expect(window.location.reload).toHaveBeenCalledTimes(1);
});
it('calls request', () => {
expect(requestSpy).toHaveBeenCalledTimes(1);
expect(requestSpy).toHaveBeenCalledWith(
JSON.stringify({ user: { use_legacy_web_ide: false } }),
);
});
it('is not loading', () => {
expect(findButton().props('loading')).toBe(false);
});
});
describe('when user accepts confirm and response fails', () => {
beforeEach(async () => {
requestSpy.mockReturnValue([400, {}]);
await submitConfirm(true);
});
it('handles error', () => {
expect(logError).toHaveBeenCalledTimes(1);
expect(logError).toHaveBeenCalledWith(
'Error while updating user preferences',
expect.any(Error),
);
expect(createAlert).toHaveBeenCalledTimes(1);
expect(createAlert).toHaveBeenCalledWith({
message: MSG_ERROR_ALERT,
});
});
it('does not reload', () => {
expect(skipBeforeunloadSpy).not.toHaveBeenCalled();
expect(window.location.reload).not.toHaveBeenCalled();
});
});
});
});

View File

@ -87,11 +87,13 @@ describe('Multi-file store mutations', () => {
emptyStateSvgPath: 'emptyState',
noChangesStateSvgPath: 'noChanges',
committedStateSvgPath: 'committed',
switchEditorSvgPath: 'switchEditorSvg',
});
expect(localState.emptyStateSvgPath).toBe('emptyState');
expect(localState.noChangesStateSvgPath).toBe('noChanges');
expect(localState.committedStateSvgPath).toBe('committed');
expect(localState.switchEditorSvgPath).toBe('switchEditorSvg');
});
});

View File

@ -0,0 +1,205 @@
import { GlDrawer, GlAlert, GlSkeletonLoader } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import MarkdownDrawer, { cache } from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
import { getRenderedMarkdown } from '~/vue_shared/components/markdown_drawer/utils/fetch';
import { contentTop } from '~/lib/utils/common_utils';
jest.mock('~/vue_shared/components/markdown_drawer/utils/fetch', () => ({
getRenderedMarkdown: jest.fn().mockReturnValue({
title: 'test title test',
body: `<div id="content-body">
<div class="documentation md gl-mt-3">
test body
</div>
</div>`,
}),
}));
jest.mock('~/lib/utils/common_utils', () => ({
contentTop: jest.fn(),
}));
describe('MarkdownDrawer', () => {
let wrapper;
const defaultProps = {
documentPath: 'user/search/global_search/advanced_search_syntax.json',
};
const createComponent = (props) => {
wrapper = shallowMountExtended(MarkdownDrawer, {
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
Object.keys(cache).forEach((key) => delete cache[key]);
});
const findDrawer = () => wrapper.findComponent(GlDrawer);
const findAlert = () => wrapper.findComponent(GlAlert);
const findSkeleton = () => wrapper.findComponent(GlSkeletonLoader);
const findDrawerTitle = () => wrapper.findComponent('[data-testid="title-element"]');
const findDrawerBody = () => wrapper.findComponent({ ref: 'content-element' });
describe('component', () => {
beforeEach(() => {
createComponent();
});
it('renders correctly', () => {
expect(findDrawer().exists()).toBe(true);
expect(findDrawerTitle().text()).toBe('test title test');
expect(findDrawerBody().text()).toBe('test body');
});
});
describe.each`
hasNavbar | navbarHeight
${false} | ${0}
${true} | ${100}
`('computes offsetTop', ({ hasNavbar, navbarHeight }) => {
beforeEach(() => {
global.document.querySelector = jest.fn(() =>
hasNavbar
? {
dataset: {
page: 'test',
},
}
: undefined,
);
contentTop.mockReturnValue(navbarHeight);
createComponent();
});
afterEach(() => {
contentTop.mockClear();
});
it(`computes offsetTop ${hasNavbar ? 'with' : 'without'} .navbar-gitlab`, () => {
expect(findDrawer().attributes('headerheight')).toBe(`${navbarHeight}px`);
});
});
describe('watcher', () => {
let renderGLFMSpy;
let fetchMarkdownSpy;
beforeEach(async () => {
renderGLFMSpy = jest.spyOn(MarkdownDrawer.methods, 'renderGLFM');
fetchMarkdownSpy = jest.spyOn(MarkdownDrawer.methods, 'fetchMarkdown');
global.document.querySelector = jest.fn(() => ({
getBoundingClientRect: jest.fn(() => ({ bottom: 100 })),
dataset: {
page: 'test',
},
}));
createComponent();
await nextTick();
});
afterEach(() => {
renderGLFMSpy.mockClear();
fetchMarkdownSpy.mockClear();
});
it('for documentPath triggers fetch', async () => {
expect(fetchMarkdownSpy).toHaveBeenCalledTimes(1);
await wrapper.setProps({ documentPath: '/test/me' });
await nextTick();
expect(fetchMarkdownSpy).toHaveBeenCalledTimes(2);
});
it('for open triggers renderGLFM', async () => {
wrapper.vm.fetchMarkdown();
wrapper.vm.openDrawer();
await nextTick();
expect(renderGLFMSpy).toHaveBeenCalled();
});
});
describe('Markdown fetching', () => {
let renderGLFMSpy;
beforeEach(async () => {
renderGLFMSpy = jest.spyOn(MarkdownDrawer.methods, 'renderGLFM');
createComponent();
await nextTick();
});
afterEach(() => {
renderGLFMSpy.mockClear();
});
it('fetches the Markdown and caches it', async () => {
expect(getRenderedMarkdown).toHaveBeenCalledTimes(1);
expect(Object.keys(cache)).toHaveLength(1);
});
it('when the document changes, fetches it and caches it as well', async () => {
expect(getRenderedMarkdown).toHaveBeenCalledTimes(1);
expect(Object.keys(cache)).toHaveLength(1);
await wrapper.setProps({ documentPath: '/test/me2' });
await nextTick();
expect(getRenderedMarkdown).toHaveBeenCalledTimes(2);
expect(Object.keys(cache)).toHaveLength(2);
});
it('when re-using an already fetched document, gets it from the cache', async () => {
await wrapper.setProps({ documentPath: '/test/me2' });
await nextTick();
expect(getRenderedMarkdown).toHaveBeenCalledTimes(2);
expect(Object.keys(cache)).toHaveLength(2);
await wrapper.setProps({ documentPath: defaultProps.documentPath });
await nextTick();
expect(getRenderedMarkdown).toHaveBeenCalledTimes(2);
expect(Object.keys(cache)).toHaveLength(2);
});
});
describe('Markdown fetching returns error', () => {
beforeEach(async () => {
getRenderedMarkdown.mockReturnValue({
hasFetchError: true,
});
createComponent();
await nextTick();
});
afterEach(() => {
getRenderedMarkdown.mockClear();
});
it('shows alert', () => {
expect(findAlert().exists()).toBe(true);
});
});
describe('While Markdown is fetching', () => {
beforeEach(async () => {
getRenderedMarkdown.mockReturnValue(new Promise(() => {}));
createComponent();
});
afterEach(() => {
getRenderedMarkdown.mockClear();
});
it('shows skeleton', async () => {
expect(findSkeleton().exists()).toBe(true);
});
});
});

View File

@ -0,0 +1,42 @@
export const MOCK_HTML = `<!DOCTYPE html>
<html>
<body>
<div id="content-body">
<h1>test title <strong>test</strong></h1>
<div class="documentation md gl-mt-3">
<a href="../advanced_search.md">Advanced Search</a>
<a href="../advanced_search2.md">Advanced Search2</a>
<h2>test header h2</h2>
<table class="testClass">
<tr>
<td>Emil</td>
<td>Tobias</td>
<td>Linus</td>
</tr>
<tr>
<td>16</td>
<td>14</td>
<td>10</td>
</tr>
</table>
</div>
</div>
</body>
</html>`.replace(/\n/g, '');
export const MOCK_DRAWER_DATA = {
hasFetchError: false,
title: 'test title test',
body: ` <div id="content-body"> <div class="documentation md gl-mt-3"> <a href="../advanced_search.md">Advanced Search</a> <a href="../advanced_search2.md">Advanced Search2</a> <h2>test header h2</h2> <table class="testClass"> <tbody><tr> <td>Emil</td> <td>Tobias</td> <td>Linus</td> </tr> <tr> <td>16</td> <td>14</td> <td>10</td> </tr> </tbody></table> </div> </div>`,
};
export const MOCK_DRAWER_DATA_ERROR = {
hasFetchError: true,
};
export const MOCK_TABLE_DATA_BEFORE = `<head></head><body><h1>test</h1></test><table><tbody><tr><td></td></tr></tbody></table></body>`;
export const MOCK_HTML_DATA_AFTER = {
body: '<table><tbody><tr><td></td></tr></tbody></table>',
title: 'test',
};

View File

@ -0,0 +1,43 @@
import MockAdapter from 'axios-mock-adapter';
import {
getRenderedMarkdown,
splitDocument,
} from '~/vue_shared/components/markdown_drawer/utils/fetch';
import axios from '~/lib/utils/axios_utils';
import {
MOCK_HTML,
MOCK_DRAWER_DATA,
MOCK_DRAWER_DATA_ERROR,
MOCK_TABLE_DATA_BEFORE,
MOCK_HTML_DATA_AFTER,
} from '../mock_data';
describe('utils/fetch', () => {
let mock;
afterEach(() => {
mock.restore();
});
describe.each`
axiosMock | type | toExpect
${{ code: 200, res: { html: MOCK_HTML } }} | ${'success'} | ${MOCK_DRAWER_DATA}
${{ code: 500, res: null }} | ${'error'} | ${MOCK_DRAWER_DATA_ERROR}
`('process markdown data', ({ axiosMock, type, toExpect }) => {
describe(`if api fetch responds with ${type}`, () => {
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet().reply(axiosMock.code, axiosMock.res);
});
it(`should update drawer correctly`, async () => {
expect(await getRenderedMarkdown('/any/path')).toStrictEqual(toExpect);
});
});
});
describe('splitDocument', () => {
it(`should update tables correctly`, () => {
expect(splitDocument(MOCK_TABLE_DATA_BEFORE)).toStrictEqual(MOCK_HTML_DATA_AFTER);
});
});
});

View File

@ -26,6 +26,8 @@ RSpec.describe IdeHelper do
'can-use-new-web-ide' => 'true',
'use-new-web-ide' => 'true',
'user-preferences-path' => profile_preferences_path,
'new-web-ide-help-page-path' =>
help_page_path('user/project/web_ide/index.md', anchor: 'vscode-reimplementation'),
'branch-name' => 'master',
'project-path' => project.path_with_namespace,
'csp-nonce' => 'test-csp-nonce'

View File

@ -111,35 +111,35 @@ RSpec.describe Banzai::Filter::MathFilter do
describe 'display math using ```math...``` syntax' do
it 'adds data-math-style display attribute to display math' do
doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
doc = filter('<pre lang="math"><code>2+2</code></pre>')
pre = doc.xpath('descendant-or-self::pre').first
expect(pre['data-math-style']).to eq 'display'
end
it 'adds js-render-math class to display math' do
doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
doc = filter('<pre lang="math"><code>2+2</code></pre>')
pre = doc.xpath('descendant-or-self::pre').first
expect(pre[:class]).to include("js-render-math")
end
it 'ignores code blocks that are not math' do
input = '<pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code>2+2</code></pre>'
input = '<pre lang="plaintext"><code>2+2</code></pre>'
doc = filter(input)
expect(doc.to_s).to eq input
end
it 'requires the pre to contain both code and math' do
input = '<pre class="highlight js-syntax-highlight language-plaintext language-math" v-pre="true"><code>2+2</code></pre>'
input = '<pre lang="math">something</pre>'
doc = filter(input)
expect(doc.to_s).to eq input
end
it 'dollar signs around to display math' do
doc = filter('$<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>$')
doc = filter('$<pre lang="math"><code>2+2</code></pre>$')
before = doc.xpath('descendant-or-self::text()[1]').first
after = doc.xpath('descendant-or-self::text()[3]').first

View File

@ -23,7 +23,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do
result = filter('<pre><code>def fun end</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", ""
@ -31,9 +31,9 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
context "when contains mermaid diagrams" do
it "ignores mermaid blocks" do
result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
result = filter('<pre data-mermaid-style="display" lang="mermaid"><code class="js-render-mermaid">mermaid code</code></pre>')
expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-mermaid-style="display" lang="mermaid" class="code highlight js-syntax-highlight language-mermaid" v-pre="true"><code class="js-render-mermaid"><span id="LC1" class="line" lang="mermaid">mermaid code</span></code></pre><copy-code></copy-code></div>')
end
end
@ -49,7 +49,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as that language" do
result = filter('<pre lang="ruby"><code>def fun end</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="ruby" class="code highlight js-syntax-highlight language-ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"
@ -59,7 +59,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do
result = filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="gnuplot" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="gnuplot" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "gnuplot"
@ -74,7 +74,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext but with the correct language attribute and class" do
result = filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="#{lang}" class="code highlight js-syntax-highlight language-#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
end
include_examples "XSS prevention", lang
@ -87,7 +87,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "includes data-lang-params tag with extra information" do
result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params}"><code>This is a test</code></pre>})
expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="#{lang}" class="code highlight js-syntax-highlight language-#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
end
include_examples "XSS prevention", lang
@ -105,7 +105,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
let(:lang_params) { '-1+10' }
let(:expected_result) do
%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>}
%{<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="#{lang}" class="code highlight js-syntax-highlight language-#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>}
end
context 'when delimiter is space' do
@ -130,13 +130,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "includes it in the highlighted code block" do
result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code lang="plaintext"><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
end
it "escape sourcepos metadata to prevent XSS" do
result = filter('<pre data-sourcepos="&#34;%22 href=&#34;x&#34;></pre><base href=http://unsafe-website.com/><pre x=&#34;"><code></code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos=\'"%22 href="x"&gt;&lt;/pre&gt;&lt;base href=http://unsafe-website.com/&gt;&lt;pre x="\' class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="" v-pre="true"><code></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos=\'"%22 href="x"&gt;&lt;/pre&gt;&lt;base href=http://unsafe-website.com/&gt;&lt;pre x="\' lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="" v-pre="true"><code></code></pre><copy-code></copy-code></div>')
end
end
@ -150,7 +150,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do
result = filter('<pre lang="ruby"><code>This is a test</code></pre>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight" lang="" data-canonical-lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre lang="" class="code highlight js-syntax-highlight" data-canonical-lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"

View File

@ -94,9 +94,18 @@ module Gitlab
# Move this test back to the items hash when removing `use_cmark_renderer` feature flag.
it "does not convert dangerous fenced code with inline script into HTML" do
input = '```mypre"><script>alert(3)</script>'
output = "<div>\n<div>\n<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" data-canonical-lang=\"mypre\" v-pre=\"true\"><code></code></pre>\n<copy-code></copy-code>\n</div>\n</div>\n</div>"
output = <<~HTML
<div>
<div>
<div class=\"gl-relative markdown-code-block js-markdown-code\">
<pre lang=\"plaintext\" class=\"code highlight js-syntax-highlight language-plaintext\" data-canonical-lang=\"mypre\" v-pre=\"true\"><code></code></pre>
<copy-code></copy-code>
</div>
</div>
</div>
HTML
expect(render(input, context)).to include(output)
expect(render(input, context)).to include(output.strip)
end
it 'does not allow locked attributes to be overridden' do
@ -360,7 +369,7 @@ module Gitlab
<div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre class="code highlight js-syntax-highlight language-javascript" lang="javascript" data-canonical-lang="js" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<pre lang="javascript" class="code highlight js-syntax-highlight language-javascript" data-canonical-lang="js" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<copy-code></copy-code>
</div>
</div>
@ -390,7 +399,7 @@ module Gitlab
<div>class.cpp</div>
<div>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre class="code highlight js-syntax-highlight language-cpp" lang="cpp" data-canonical-lang="c++" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span></span>
<pre lang="cpp" class="code highlight js-syntax-highlight language-cpp" data-canonical-lang="c++" v-pre="true"><code><span id="LC1" class="line" lang="cpp"><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span></span>
<span id="LC2" class="line" lang="cpp"></span>
<span id="LC3" class="line" lang="cpp"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span></span>
<span id="LC4" class="line" lang="cpp"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="o">&lt;&lt;</span><span class="s">"*"</span><span class="o">&lt;&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span></span>
@ -448,7 +457,7 @@ module Gitlab
stem:[2+2] is 4
MD
expect(render(input, context)).to include('<pre data-math-style="display" class="code math js-render-math"><code>eta_x gamma</code></pre>')
expect(render(input, context)).to include('<pre data-math-style="display" lang="plaintext" class="code math js-render-math" data-canonical-lang="" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">eta_x gamma</span></code></pre>')
expect(render(input, context)).to include('<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>')
end
end

View File

@ -52,7 +52,11 @@ RSpec.describe Ci::Processable do
let_it_be(:internal_job_variable) { create(:ci_job_variable, job: processable) }
let(:clone_accessors) { ::Ci::Build.clone_accessors.without(::Ci::Build.extra_accessors) }
let(:clone_accessors) do
%i[pipeline project ref tag options name allow_failure stage stage_idx trigger_request yaml_variables
when environment coverage_regex description tag_list protected needs_attributes job_variables_attributes
resource_group scheduling_type ci_stage partition_id id_tokens]
end
let(:reject_accessors) do
%i[id status user token_encrypted coverage runner artifacts_expire_at
@ -83,7 +87,8 @@ RSpec.describe Ci::Processable do
resource resource_group_id processed security_scans author
pipeline_id report_results pending_state pages_deployments
queuing_entry runtime_metadata trace_metadata
dast_site_profile dast_scanner_profile stage_id].freeze
dast_site_profile dast_scanner_profile stage_id dast_site_profiles_build
dast_scanner_profiles_build].freeze
end
before_all do
@ -177,10 +182,7 @@ RSpec.describe Ci::Processable do
Ci::Build.attribute_names.map(&:to_sym) +
Ci::Build.attribute_aliases.keys.map(&:to_sym) +
Ci::Build.reflect_on_all_associations.map(&:name) +
[:tag_list, :needs_attributes, :job_variables_attributes, :id_tokens] -
# ToDo: Move EE accessors to ee/
::Ci::Build.extra_accessors -
[:dast_site_profiles_build, :dast_scanner_profiles_build]
[:tag_list, :needs_attributes, :job_variables_attributes, :id_tokens]
current_accessors.uniq!

View File

@ -292,7 +292,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
expected_spec_html = <<~RENDERED_HTML
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<pre data-sourcepos="1:1-4:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -311,7 +311,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
expected_snapshot_spec_html = <<~RENDERED_HTML
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<pre data-sourcepos="1:1-4:3" lang="yaml" class="code highlight js-syntax-highlight language-yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
<copy-code></copy-code>
</div>
@ -320,7 +320,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
<h2 data-sourcepos="7:1-7:9" dir="auto">
<a id="user-content-strong" class="anchor" href="#strong" aria-hidden="true"></a>Strong</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="9:1-13:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__bold__</span>
<pre data-sourcepos="9:1-13:32" lang="plaintext" class="code highlight js-syntax-highlight language-plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__bold__</span>
<span id="LC2" class="line" lang="plaintext">.</span>
<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;bold&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
<copy-code></copy-code>