Prettify merge_conflicts monitoring and notebook modules
This commit is contained in:
parent
f7a3e8ff53
commit
56914c1ac9
19 changed files with 343 additions and 356 deletions
|
@ -6,7 +6,7 @@ import axios from '~/lib/utils/axios_utils';
|
|||
import flash from '~/flash';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
((global) => {
|
||||
(global => {
|
||||
global.mergeConflicts = global.mergeConflicts || {};
|
||||
|
||||
global.mergeConflicts.diffFileEditor = Vue.extend({
|
||||
|
@ -35,10 +35,10 @@ import { __ } from '~/locale';
|
|||
computed: {
|
||||
classObject() {
|
||||
return {
|
||||
'saved': this.saved,
|
||||
'is-loading': this.loading
|
||||
saved: this.saved,
|
||||
'is-loading': this.loading,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
['file.showEditor'](val) {
|
||||
|
@ -49,7 +49,7 @@ import { __ } from '~/locale';
|
|||
}
|
||||
|
||||
this.loadEditor();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.file.loadEditor) {
|
||||
|
@ -60,7 +60,8 @@ import { __ } from '~/locale';
|
|||
loadEditor() {
|
||||
this.loading = true;
|
||||
|
||||
axios.get(this.file.content_path)
|
||||
axios
|
||||
.get(this.file.content_path)
|
||||
.then(({ data }) => {
|
||||
const content = this.$el.querySelector('pre');
|
||||
const fileContent = document.createTextNode(data.content);
|
||||
|
@ -101,7 +102,7 @@ import { __ } from '~/locale';
|
|||
},
|
||||
acceptDiscardConfirmation(file) {
|
||||
this.onAcceptDiscardConfirmation(file);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -4,7 +4,7 @@ import Vue from 'vue';
|
|||
import actionsMixin from '../mixins/line_conflict_actions';
|
||||
import utilsMixin from '../mixins/line_conflict_utils';
|
||||
|
||||
((global) => {
|
||||
(global => {
|
||||
global.mergeConflicts = global.mergeConflicts || {};
|
||||
|
||||
global.mergeConflicts.parallelConflictLines = Vue.extend({
|
||||
|
|
|
@ -4,7 +4,7 @@ import $ from 'jquery';
|
|||
import Vue from 'vue';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
((global) => {
|
||||
(global => {
|
||||
global.mergeConflicts = global.mergeConflicts || {};
|
||||
|
||||
const diffViewType = Cookies.get('diff_view');
|
||||
|
@ -17,11 +17,11 @@ import Cookies from 'js-cookie';
|
|||
const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
|
||||
const VIEW_TYPES = {
|
||||
INLINE: 'inline',
|
||||
PARALLEL: 'parallel'
|
||||
PARALLEL: 'parallel',
|
||||
};
|
||||
const CONFLICT_TYPES = {
|
||||
TEXT: 'text',
|
||||
TEXT_EDITOR: 'text-editor'
|
||||
TEXT_EDITOR: 'text-editor',
|
||||
};
|
||||
|
||||
global.mergeConflicts.mergeConflictsStore = {
|
||||
|
@ -31,7 +31,7 @@ import Cookies from 'js-cookie';
|
|||
isSubmitting: false,
|
||||
isParallel: diffViewType === VIEW_TYPES.PARALLEL,
|
||||
diffViewType: diffViewType,
|
||||
conflictsData: {}
|
||||
conflictsData: {},
|
||||
},
|
||||
|
||||
setConflictsData(data) {
|
||||
|
@ -47,7 +47,7 @@ import Cookies from 'js-cookie';
|
|||
},
|
||||
|
||||
decorateFiles(files) {
|
||||
files.forEach((file) => {
|
||||
files.forEach(file => {
|
||||
file.content = '';
|
||||
file.resolutionData = {};
|
||||
file.promptDiscardConfirmation = false;
|
||||
|
@ -72,7 +72,7 @@ import Cookies from 'js-cookie';
|
|||
setInlineLine(file) {
|
||||
file.inlineLines = [];
|
||||
|
||||
file.sections.forEach((section) => {
|
||||
file.sections.forEach(section => {
|
||||
let currentLineType = 'new';
|
||||
const { conflict, lines, id } = section;
|
||||
|
||||
|
@ -80,7 +80,7 @@ import Cookies from 'js-cookie';
|
|||
file.inlineLines.push(this.getHeadHeaderLine(id));
|
||||
}
|
||||
|
||||
lines.forEach((line) => {
|
||||
lines.forEach(line => {
|
||||
const { type } = line;
|
||||
|
||||
if ((type === 'new' || type === 'old') && currentLineType !== type) {
|
||||
|
@ -102,7 +102,7 @@ import Cookies from 'js-cookie';
|
|||
file.parallelLines = [];
|
||||
const linesObj = { left: [], right: [] };
|
||||
|
||||
file.sections.forEach((section) => {
|
||||
file.sections.forEach(section => {
|
||||
const { conflict, lines, id } = section;
|
||||
|
||||
if (conflict) {
|
||||
|
@ -110,7 +110,7 @@ import Cookies from 'js-cookie';
|
|||
linesObj.right.push(this.getHeadHeaderLine(id));
|
||||
}
|
||||
|
||||
lines.forEach((line) => {
|
||||
lines.forEach(line => {
|
||||
const { type } = line;
|
||||
|
||||
if (conflict) {
|
||||
|
@ -131,10 +131,7 @@ import Cookies from 'js-cookie';
|
|||
});
|
||||
|
||||
for (let i = 0, len = linesObj.left.length; i < len; i += 1) {
|
||||
file.parallelLines.push([
|
||||
linesObj.right[i],
|
||||
linesObj.left[i]
|
||||
]);
|
||||
file.parallelLines.push([linesObj.right[i], linesObj.left[i]]);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -159,9 +156,9 @@ import Cookies from 'js-cookie';
|
|||
const { files } = this.state.conflictsData;
|
||||
let count = 0;
|
||||
|
||||
files.forEach((file) => {
|
||||
files.forEach(file => {
|
||||
if (file.type === CONFLICT_TYPES.TEXT) {
|
||||
file.sections.forEach((section) => {
|
||||
file.sections.forEach(section => {
|
||||
if (section.conflict) {
|
||||
count += 1;
|
||||
}
|
||||
|
@ -198,7 +195,7 @@ import Cookies from 'js-cookie';
|
|||
isHeader: true,
|
||||
isHead: true,
|
||||
isSelected: false,
|
||||
isUnselected: false
|
||||
isUnselected: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -229,7 +226,7 @@ import Cookies from 'js-cookie';
|
|||
section: isHead ? 'head' : 'origin',
|
||||
richText: rich_text,
|
||||
isSelected: false,
|
||||
isUnselected: false
|
||||
isUnselected: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -243,7 +240,7 @@ import Cookies from 'js-cookie';
|
|||
isHeader: true,
|
||||
isOrigin: true,
|
||||
isSelected: false,
|
||||
isUnselected: false
|
||||
isUnselected: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -290,14 +287,14 @@ import Cookies from 'js-cookie';
|
|||
},
|
||||
|
||||
restoreFileLinesState(file) {
|
||||
file.inlineLines.forEach((line) => {
|
||||
file.inlineLines.forEach(line => {
|
||||
if (line.hasConflict || line.isHeader) {
|
||||
line.isSelected = false;
|
||||
line.isUnselected = false;
|
||||
}
|
||||
});
|
||||
|
||||
file.parallelLines.forEach((lines) => {
|
||||
file.parallelLines.forEach(lines => {
|
||||
const left = lines[0];
|
||||
const right = lines[1];
|
||||
const isLeftMatch = left.hasConflict || left.isHeader;
|
||||
|
@ -354,7 +351,7 @@ import Cookies from 'js-cookie';
|
|||
const initial = 'Commit to source branch';
|
||||
const inProgress = 'Committing...';
|
||||
|
||||
return this.state ? this.state.isSubmitting ? inProgress : initial : initial;
|
||||
return this.state ? (this.state.isSubmitting ? inProgress : initial) : initial;
|
||||
},
|
||||
|
||||
getCommitData() {
|
||||
|
@ -362,13 +359,13 @@ import Cookies from 'js-cookie';
|
|||
|
||||
commitData = {
|
||||
commit_message: this.state.conflictsData.commitMessage,
|
||||
files: []
|
||||
files: [],
|
||||
};
|
||||
|
||||
this.state.conflictsData.files.forEach((file) => {
|
||||
this.state.conflictsData.files.forEach(file => {
|
||||
const addFile = {
|
||||
old_path: file.old_path,
|
||||
new_path: file.new_path
|
||||
new_path: file.new_path,
|
||||
};
|
||||
|
||||
if (file.type === CONFLICT_TYPES.TEXT) {
|
||||
|
@ -391,13 +388,13 @@ import Cookies from 'js-cookie';
|
|||
handleSelected(file, sectionId, selection) {
|
||||
Vue.set(file.resolutionData, sectionId, selection);
|
||||
|
||||
file.inlineLines.forEach((line) => {
|
||||
file.inlineLines.forEach(line => {
|
||||
if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
|
||||
this.markLine(line, selection);
|
||||
}
|
||||
});
|
||||
|
||||
file.parallelLines.forEach((lines) => {
|
||||
file.parallelLines.forEach(lines => {
|
||||
const left = lines[0];
|
||||
const right = lines[1];
|
||||
const hasSameId = right.id === sectionId || left.id === sectionId;
|
||||
|
@ -430,6 +427,6 @@ import Cookies from 'js-cookie';
|
|||
|
||||
fileTextTypePresent() {
|
||||
return this.state.conflictsData.files.some(f => f.type === CONFLICT_TYPES.TEXT);
|
||||
}
|
||||
},
|
||||
};
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -148,7 +148,7 @@ export default {
|
|||
point = point.matrixTransform(this.$refs.graphData.getScreenCTM().inverse());
|
||||
point.x += 7;
|
||||
|
||||
this.seriesUnderMouse = this.timeSeries.filter((series) => {
|
||||
this.seriesUnderMouse = this.timeSeries.filter(series => {
|
||||
const mouseX = series.timeSeriesScaleX.invert(point.x);
|
||||
let minDistance = Infinity;
|
||||
|
||||
|
@ -221,21 +221,18 @@ export default {
|
|||
.scale(axisYScale)
|
||||
.ticks(measurements.yTicks);
|
||||
|
||||
d3
|
||||
.select(this.$refs.baseSvg)
|
||||
d3.select(this.$refs.baseSvg)
|
||||
.select('.x-axis')
|
||||
.call(xAxis);
|
||||
|
||||
const width = this.graphWidth;
|
||||
d3
|
||||
.select(this.$refs.baseSvg)
|
||||
d3.select(this.$refs.baseSvg)
|
||||
.select('.y-axis')
|
||||
.call(yAxis)
|
||||
.selectAll('.tick')
|
||||
.each(function createTickLines(d, i) {
|
||||
if (i > 0) {
|
||||
d3
|
||||
.select(this)
|
||||
d3.select(this)
|
||||
.select('line')
|
||||
.attr('x2', width)
|
||||
.attr('class', 'axis-tick');
|
||||
|
|
|
@ -38,38 +38,25 @@ export default {
|
|||
computed: {
|
||||
textTransform() {
|
||||
const yCoordinate =
|
||||
(this.graphHeight -
|
||||
this.margin.top +
|
||||
this.measurements.axisLabelLineOffset) /
|
||||
2 || 0;
|
||||
(this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 || 0;
|
||||
|
||||
return `translate(15, ${yCoordinate}) rotate(-90)`;
|
||||
},
|
||||
|
||||
rectTransform() {
|
||||
const yCoordinate =
|
||||
(this.graphHeight -
|
||||
this.margin.top +
|
||||
this.measurements.axisLabelLineOffset) /
|
||||
2 +
|
||||
(this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 +
|
||||
this.yLabelWidth / 2 || 0;
|
||||
|
||||
return `translate(0, ${yCoordinate}) rotate(-90)`;
|
||||
},
|
||||
|
||||
xPosition() {
|
||||
return (
|
||||
(this.graphWidth + this.measurements.axisLabelLineOffset) / 2 -
|
||||
this.margin.right || 0
|
||||
);
|
||||
return (this.graphWidth + this.measurements.axisLabelLineOffset) / 2 - this.margin.right || 0;
|
||||
},
|
||||
|
||||
yPosition() {
|
||||
return (
|
||||
this.graphHeight -
|
||||
this.margin.top +
|
||||
this.measurements.axisLabelLineOffset || 0
|
||||
);
|
||||
return this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset || 0;
|
||||
},
|
||||
|
||||
yAxisLabelSentenceCase() {
|
||||
|
|
|
@ -92,7 +92,8 @@ export default {
|
|||
methods: {
|
||||
seriesMetricValue(seriesIndex, series) {
|
||||
const indexFromCoordinates = this.currentCoordinates[series.metricTag]
|
||||
? this.currentCoordinates[series.metricTag].currentDataIndex : 0;
|
||||
? this.currentCoordinates[series.metricTag].currentDataIndex
|
||||
: 0;
|
||||
const index = this.deploymentFlagData
|
||||
? this.deploymentFlagData.seriesIndex
|
||||
: indexFromCoordinates;
|
||||
|
|
|
@ -26,4 +26,3 @@ export default {
|
|||
{{ summaryMetrics }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -33,4 +33,3 @@ export default {
|
|||
</svg>
|
||||
</td>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const mixins = {
|
|||
if (!this.reducedDeploymentData) return false;
|
||||
|
||||
let dataFound = false;
|
||||
this.reducedDeploymentData = this.reducedDeploymentData.map((d) => {
|
||||
this.reducedDeploymentData = this.reducedDeploymentData.map(d => {
|
||||
const deployment = d;
|
||||
if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) {
|
||||
dataFound = d.xPos + 1;
|
||||
|
@ -61,7 +61,7 @@ const mixins = {
|
|||
|
||||
this.currentCoordinates = {};
|
||||
|
||||
this.seriesUnderMouse.forEach((series) => {
|
||||
this.seriesUnderMouse.forEach(series => {
|
||||
const currentDataIndex = bisectDate(series.values, this.hoverData.hoveredDate);
|
||||
const currentData = series.values[currentDataIndex];
|
||||
const currentX = Math.floor(series.timeSeriesScaleX(currentData.time));
|
||||
|
|
|
@ -8,18 +8,20 @@ const MAX_REQUESTS = 3;
|
|||
function backOffRequest(makeRequestCallback) {
|
||||
let requestCounter = 0;
|
||||
return backOff((next, stop) => {
|
||||
makeRequestCallback().then((resp) => {
|
||||
if (resp.status === statusCodes.NO_CONTENT) {
|
||||
requestCounter += 1;
|
||||
if (requestCounter < MAX_REQUESTS) {
|
||||
next();
|
||||
makeRequestCallback()
|
||||
.then(resp => {
|
||||
if (resp.status === statusCodes.NO_CONTENT) {
|
||||
requestCounter += 1;
|
||||
if (requestCounter < MAX_REQUESTS) {
|
||||
next();
|
||||
} else {
|
||||
stop(new Error('Failed to connect to the prometheus server'));
|
||||
}
|
||||
} else {
|
||||
stop(new Error('Failed to connect to the prometheus server'));
|
||||
stop(resp);
|
||||
}
|
||||
} else {
|
||||
stop(resp);
|
||||
}
|
||||
}).catch(stop);
|
||||
})
|
||||
.catch(stop);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,7 +35,7 @@ export default class MonitoringService {
|
|||
getGraphsData() {
|
||||
return backOffRequest(() => axios.get(this.metricsEndpoint))
|
||||
.then(resp => resp.data)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
if (!response || !response.data) {
|
||||
throw new Error(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
|
||||
}
|
||||
|
@ -47,22 +49,27 @@ export default class MonitoringService {
|
|||
}
|
||||
return backOffRequest(() => axios.get(this.deploymentEndpoint))
|
||||
.then(resp => resp.data)
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
if (!response || !response.deployments) {
|
||||
throw new Error(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
|
||||
throw new Error(
|
||||
s__('Metrics|Unexpected deployment data response from prometheus endpoint'),
|
||||
);
|
||||
}
|
||||
return response.deployments;
|
||||
});
|
||||
}
|
||||
|
||||
getEnvironmentsData() {
|
||||
return axios.get(this.environmentsEndpoint)
|
||||
.then(resp => resp.data)
|
||||
.then((response) => {
|
||||
if (!response || !response.environments) {
|
||||
throw new Error(s__('Metrics|There was an error fetching the environments data, please try again'));
|
||||
}
|
||||
return response.environments;
|
||||
});
|
||||
return axios
|
||||
.get(this.environmentsEndpoint)
|
||||
.then(resp => resp.data)
|
||||
.then(response => {
|
||||
if (!response || !response.environments) {
|
||||
throw new Error(
|
||||
s__('Metrics|There was an error fetching the environments data, please try again'),
|
||||
);
|
||||
}
|
||||
return response.environments;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export default {
|
||||
small: { // Covers both xs and sm screen sizes
|
||||
small: {
|
||||
// Covers both xs and sm screen sizes
|
||||
margin: {
|
||||
top: 40,
|
||||
right: 40,
|
||||
|
@ -18,7 +19,8 @@ export default {
|
|||
},
|
||||
axisLabelLineOffset: -20,
|
||||
},
|
||||
large: { // This covers both md and lg screen sizes
|
||||
large: {
|
||||
// This covers both md and lg screen sizes
|
||||
margin: {
|
||||
top: 80,
|
||||
right: 80,
|
||||
|
|
|
@ -66,7 +66,8 @@ function queryTimeSeries(query, graphDrawData, lineStyle) {
|
|||
// offset the same amount as the original data
|
||||
const [minX, maxX] = graphDrawData.xDom;
|
||||
const offset = d3.timeMinute(minX) - Number(minX);
|
||||
const datesWithoutGaps = d3.timeSecond.every(60)
|
||||
const datesWithoutGaps = d3.timeSecond
|
||||
.every(60)
|
||||
.range(d3.timeMinute.offset(minX, -1), maxX)
|
||||
.map(d => d - offset);
|
||||
|
||||
|
@ -208,9 +209,7 @@ export default function createTimeSeries(queries, graphWidth, graphHeight, graph
|
|||
|
||||
const timeSeries = queries.reduce((series, query, index) => {
|
||||
const lineStyle = defaultStyleOrder[index % defaultStyleOrder.length];
|
||||
return series.concat(
|
||||
queryTimeSeries(query, graphDrawData, lineStyle),
|
||||
);
|
||||
return series.concat(queryTimeSeries(query, graphDrawData, lineStyle));
|
||||
}, []);
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
<script>
|
||||
import Prism from '../../lib/highlight';
|
||||
import Prompt from '../prompt.vue';
|
||||
import Prism from '../../lib/highlight';
|
||||
import Prompt from '../prompt.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
},
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
props: {
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
code() {
|
||||
return this.rawCode;
|
||||
},
|
||||
promptType() {
|
||||
const type = this.type.split('put')[0];
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
code() {
|
||||
return this.rawCode;
|
||||
},
|
||||
promptType() {
|
||||
const type = this.type.split('put')[0];
|
||||
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
},
|
||||
return type.charAt(0).toUpperCase() + type.slice(1);
|
||||
},
|
||||
mounted() {
|
||||
Prism.highlightElement(this.$refs.code);
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
Prism.highlightElement(this.$refs.code);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script>
|
||||
/* global katex */
|
||||
import marked from 'marked';
|
||||
import sanitize from 'sanitize-html';
|
||||
import Prompt from './prompt.vue';
|
||||
/* global katex */
|
||||
import marked from 'marked';
|
||||
import sanitize from 'sanitize-html';
|
||||
import Prompt from './prompt.vue';
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
/*
|
||||
/*
|
||||
Regex to match KaTex blocks.
|
||||
|
||||
Supports the following:
|
||||
|
@ -17,7 +17,7 @@
|
|||
|
||||
The matched text then goes through the KaTex renderer & then outputs the HTML
|
||||
*/
|
||||
const katexRegexString = `(
|
||||
const katexRegexString = `(
|
||||
^\\\\begin{[a-zA-Z]+}\\s
|
||||
|
|
||||
^\\$\\$
|
||||
|
@ -32,66 +32,69 @@
|
|||
|
|
||||
\\$
|
||||
)
|
||||
`.replace(/\s/g, '').trim();
|
||||
`
|
||||
.replace(/\s/g, '')
|
||||
.trim();
|
||||
|
||||
renderer.paragraph = (t) => {
|
||||
let text = t;
|
||||
let inline = false;
|
||||
renderer.paragraph = t => {
|
||||
let text = t;
|
||||
let inline = false;
|
||||
|
||||
if (typeof katex !== 'undefined') {
|
||||
const katexString = text.replace(/&/g, '&')
|
||||
.replace(/&=&/g, '\\space=\\space')
|
||||
.replace(/<(\/?)em>/g, '_');
|
||||
const regex = new RegExp(katexRegexString, 'gi');
|
||||
const matchLocation = katexString.search(regex);
|
||||
const numberOfMatches = katexString.match(regex);
|
||||
if (typeof katex !== 'undefined') {
|
||||
const katexString = text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/&=&/g, '\\space=\\space')
|
||||
.replace(/<(\/?)em>/g, '_');
|
||||
const regex = new RegExp(katexRegexString, 'gi');
|
||||
const matchLocation = katexString.search(regex);
|
||||
const numberOfMatches = katexString.match(regex);
|
||||
|
||||
if (numberOfMatches && numberOfMatches.length !== 0) {
|
||||
if (matchLocation > 0) {
|
||||
let matches = regex.exec(katexString);
|
||||
inline = true;
|
||||
if (numberOfMatches && numberOfMatches.length !== 0) {
|
||||
if (matchLocation > 0) {
|
||||
let matches = regex.exec(katexString);
|
||||
inline = true;
|
||||
|
||||
while (matches !== null) {
|
||||
const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
|
||||
text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
|
||||
matches = regex.exec(katexString);
|
||||
}
|
||||
} else {
|
||||
const matches = regex.exec(katexString);
|
||||
text = katex.renderToString(matches[2]);
|
||||
while (matches !== null) {
|
||||
const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
|
||||
text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
|
||||
matches = regex.exec(katexString);
|
||||
}
|
||||
} else {
|
||||
const matches = regex.exec(katexString);
|
||||
text = katex.renderToString(matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
|
||||
};
|
||||
return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
|
||||
};
|
||||
|
||||
marked.setOptions({
|
||||
sanitize: true,
|
||||
renderer,
|
||||
});
|
||||
marked.setOptions({
|
||||
sanitize: true,
|
||||
renderer,
|
||||
});
|
||||
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
},
|
||||
props: {
|
||||
cell: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
cell: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
markdown() {
|
||||
return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
|
||||
allowedTags: false,
|
||||
allowedAttributes: {
|
||||
'*': ['class'],
|
||||
},
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
markdown() {
|
||||
return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
|
||||
allowedTags: false,
|
||||
allowedAttributes: {
|
||||
'*': ['class'],
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -105,13 +108,13 @@
|
|||
</template>
|
||||
|
||||
<style>
|
||||
.markdown .katex {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.markdown .katex {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.markdown .inline-katex .katex {
|
||||
display: inline;
|
||||
text-align: initial;
|
||||
}
|
||||
.markdown .inline-katex .katex {
|
||||
display: inline;
|
||||
text-align: initial;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
<script>
|
||||
import sanitize from 'sanitize-html';
|
||||
import Prompt from '../prompt.vue';
|
||||
import sanitize from 'sanitize-html';
|
||||
import Prompt from '../prompt.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
},
|
||||
props: {
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
sanitizedOutput() {
|
||||
return sanitize(this.rawCode, {
|
||||
allowedTags: sanitize.defaults.allowedTags.concat(['img', 'svg']),
|
||||
allowedAttributes: {
|
||||
img: ['src'],
|
||||
},
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
sanitizedOutput() {
|
||||
return sanitize(this.rawCode, {
|
||||
allowedTags: sanitize.defaults.allowedTags.concat([
|
||||
'img', 'svg',
|
||||
]),
|
||||
allowedAttributes: {
|
||||
img: ['src'],
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<script>
|
||||
import Prompt from '../prompt.vue';
|
||||
import Prompt from '../prompt.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
export default {
|
||||
components: {
|
||||
prompt: Prompt,
|
||||
},
|
||||
props: {
|
||||
outputType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
outputType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rawCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,78 +1,78 @@
|
|||
<script>
|
||||
import CodeCell from '../code/index.vue';
|
||||
import Html from './html.vue';
|
||||
import Image from './image.vue';
|
||||
import CodeCell from '../code/index.vue';
|
||||
import Html from './html.vue';
|
||||
import Image from './image.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'code-cell': CodeCell,
|
||||
'html-output': Html,
|
||||
'image-output': Image,
|
||||
export default {
|
||||
components: {
|
||||
'code-cell': CodeCell,
|
||||
'html-output': Html,
|
||||
'image-output': Image,
|
||||
},
|
||||
props: {
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
props: {
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
output: {
|
||||
type: Object,
|
||||
requred: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
computed: {
|
||||
componentName() {
|
||||
if (this.output.text) {
|
||||
return 'code-cell';
|
||||
} else if (this.output.data['image/png']) {
|
||||
return 'image-output';
|
||||
} else if (this.output.data['text/html']) {
|
||||
return 'html-output';
|
||||
} else if (this.output.data['image/svg+xml']) {
|
||||
return 'html-output';
|
||||
}
|
||||
|
||||
output: {
|
||||
type: Object,
|
||||
requred: true,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
componentName() {
|
||||
if (this.output.text) {
|
||||
return 'code-cell';
|
||||
},
|
||||
rawCode() {
|
||||
if (this.output.text) {
|
||||
return this.output.text.join('');
|
||||
}
|
||||
} else if (this.output.data['image/png']) {
|
||||
return 'image-output';
|
||||
} else if (this.output.data['text/html']) {
|
||||
return 'html-output';
|
||||
} else if (this.output.data['image/svg+xml']) {
|
||||
return 'html-output';
|
||||
}
|
||||
|
||||
return this.dataForType(this.outputType);
|
||||
},
|
||||
outputType() {
|
||||
if (this.output.text) {
|
||||
return '';
|
||||
} else if (this.output.data['image/png']) {
|
||||
return 'image/png';
|
||||
} else if (this.output.data['text/html']) {
|
||||
return 'text/html';
|
||||
} else if (this.output.data['image/svg+xml']) {
|
||||
return 'image/svg+xml';
|
||||
}
|
||||
|
||||
return 'text/plain';
|
||||
},
|
||||
return 'code-cell';
|
||||
},
|
||||
methods: {
|
||||
dataForType(type) {
|
||||
let data = this.output.data[type];
|
||||
rawCode() {
|
||||
if (this.output.text) {
|
||||
return this.output.text.join('');
|
||||
}
|
||||
|
||||
if (typeof data === 'object') {
|
||||
data = data.join('');
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
return this.dataForType(this.outputType);
|
||||
},
|
||||
};
|
||||
outputType() {
|
||||
if (this.output.text) {
|
||||
return '';
|
||||
} else if (this.output.data['image/png']) {
|
||||
return 'image/png';
|
||||
} else if (this.output.data['text/html']) {
|
||||
return 'text/html';
|
||||
} else if (this.output.data['image/svg+xml']) {
|
||||
return 'image/svg+xml';
|
||||
}
|
||||
|
||||
return 'text/plain';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
dataForType(type) {
|
||||
let data = this.output.data[type];
|
||||
|
||||
if (typeof data === 'object') {
|
||||
data = data.join('');
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
hasKeys() {
|
||||
return this.type !== '' && this.count;
|
||||
},
|
||||
count: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasKeys() {
|
||||
return this.type !== '' && this.count;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -29,9 +29,9 @@
|
|||
</template>
|
||||
|
||||
<style scoped>
|
||||
.prompt {
|
||||
padding: 0 10px;
|
||||
min-width: 7em;
|
||||
font-family: monospace;
|
||||
}
|
||||
.prompt {
|
||||
padding: 0 10px;
|
||||
min-width: 7em;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,51 +1,48 @@
|
|||
<script>
|
||||
import {
|
||||
MarkdownCell,
|
||||
CodeCell,
|
||||
} from './cells';
|
||||
import { MarkdownCell, CodeCell } from './cells';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
'code-cell': CodeCell,
|
||||
'markdown-cell': MarkdownCell,
|
||||
export default {
|
||||
components: {
|
||||
'code-cell': CodeCell,
|
||||
'markdown-cell': MarkdownCell,
|
||||
},
|
||||
props: {
|
||||
notebook: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
notebook: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
codeCssClass: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
computed: {
|
||||
cells() {
|
||||
if (this.notebook.worksheets) {
|
||||
const data = {
|
||||
cells: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
cells() {
|
||||
if (this.notebook.worksheets) {
|
||||
const data = {
|
||||
cells: [],
|
||||
};
|
||||
|
||||
return this.notebook.worksheets.reduce((cellData, sheet) => {
|
||||
const cellDataCopy = cellData;
|
||||
cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells);
|
||||
return cellDataCopy;
|
||||
}, data).cells;
|
||||
}
|
||||
return this.notebook.worksheets.reduce((cellData, sheet) => {
|
||||
const cellDataCopy = cellData;
|
||||
cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells);
|
||||
return cellDataCopy;
|
||||
}, data).cells;
|
||||
}
|
||||
|
||||
return this.notebook.cells;
|
||||
},
|
||||
hasNotebook() {
|
||||
return Object.keys(this.notebook).length;
|
||||
},
|
||||
return this.notebook.cells;
|
||||
},
|
||||
methods: {
|
||||
cellType(type) {
|
||||
return `${type}-cell`;
|
||||
},
|
||||
hasNotebook() {
|
||||
return Object.keys(this.notebook).length;
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cellType(type) {
|
||||
return `${type}-cell`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
Loading…
Reference in a new issue