Commit 56914c1a authored by Mike Greiling's avatar Mike Greiling

Prettify merge_conflicts monitoring and notebook modules

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