|
|
@ -1,13 +1,568 @@ |
|
|
|
// Although inspired by the https://github.com/bluef/gitgraph.js/blob/master/gitgraph.js
|
|
|
|
// this has been completely rewritten with almost no remaining code
|
|
|
|
|
|
|
|
// GitGraphCanvas is a canvas for drawing gitgraphs on to
|
|
|
|
class GitGraphCanvas { |
|
|
|
constructor(canvas, widthUnits, heightUnits, config) { |
|
|
|
this.ctx = canvas.getContext('2d'); |
|
|
|
|
|
|
|
const width = widthUnits * config.unitSize; |
|
|
|
this.height = heightUnits * config.unitSize; |
|
|
|
|
|
|
|
const ratio = window.devicePixelRatio || 1; |
|
|
|
|
|
|
|
canvas.width = width * ratio; |
|
|
|
canvas.height = this.height * ratio; |
|
|
|
|
|
|
|
canvas.style.width = `${width}px`; |
|
|
|
canvas.style.height = `${this.height}px`; |
|
|
|
|
|
|
|
this.ctx.lineWidth = config.lineWidth; |
|
|
|
this.ctx.lineJoin = 'round'; |
|
|
|
this.ctx.lineCap = 'round'; |
|
|
|
|
|
|
|
this.ctx.scale(ratio, ratio); |
|
|
|
this.config = config; |
|
|
|
} |
|
|
|
drawLine(moveX, moveY, lineX, lineY, color) { |
|
|
|
this.ctx.strokeStyle = color; |
|
|
|
this.ctx.beginPath(); |
|
|
|
this.ctx.moveTo(moveX, moveY); |
|
|
|
this.ctx.lineTo(lineX, lineY); |
|
|
|
this.ctx.stroke(); |
|
|
|
} |
|
|
|
drawLineRight(x, y, color) { |
|
|
|
this.drawLine( |
|
|
|
x - 0.5 * this.config.unitSize, |
|
|
|
y + this.config.unitSize / 2, |
|
|
|
x + 0.5 * this.config.unitSize, |
|
|
|
y + this.config.unitSize / 2, |
|
|
|
color |
|
|
|
); |
|
|
|
} |
|
|
|
drawLineUp(x, y, color) { |
|
|
|
this.drawLine( |
|
|
|
x, |
|
|
|
y + this.config.unitSize / 2, |
|
|
|
x, |
|
|
|
y - this.config.unitSize / 2, |
|
|
|
color |
|
|
|
); |
|
|
|
} |
|
|
|
drawNode(x, y, color) { |
|
|
|
this.ctx.strokeStyle = color; |
|
|
|
|
|
|
|
this.drawLineUp(x, y, color); |
|
|
|
|
|
|
|
this.ctx.beginPath(); |
|
|
|
this.ctx.arc(x, y, this.config.nodeRadius, 0, Math.PI * 2, true); |
|
|
|
this.ctx.fillStyle = color; |
|
|
|
this.ctx.fill(); |
|
|
|
} |
|
|
|
drawLineIn(x, y, color) { |
|
|
|
this.drawLine( |
|
|
|
x + 0.5 * this.config.unitSize, |
|
|
|
y + this.config.unitSize / 2, |
|
|
|
x - 0.5 * this.config.unitSize, |
|
|
|
y - this.config.unitSize / 2, |
|
|
|
color |
|
|
|
); |
|
|
|
} |
|
|
|
drawLineOut(x, y, color) { |
|
|
|
this.drawLine( |
|
|
|
x - 0.5 * this.config.unitSize, |
|
|
|
y + this.config.unitSize / 2, |
|
|
|
x + 0.5 * this.config.unitSize, |
|
|
|
y - this.config.unitSize / 2, |
|
|
|
color |
|
|
|
); |
|
|
|
} |
|
|
|
drawSymbol(symbol, columnNumber, rowNumber, color) { |
|
|
|
const y = this.height - this.config.unitSize * (rowNumber + 0.5); |
|
|
|
const x = this.config.unitSize * 0.5 * (columnNumber + 1); |
|
|
|
switch (symbol) { |
|
|
|
case '-': |
|
|
|
if (columnNumber % 2 === 1) { |
|
|
|
this.drawLineRight(x, y, color); |
|
|
|
} |
|
|
|
break; |
|
|
|
case '_': |
|
|
|
this.drawLineRight(x, y, color); |
|
|
|
break; |
|
|
|
case '*': |
|
|
|
this.drawNode(x, y, color); |
|
|
|
break; |
|
|
|
case '|': |
|
|
|
this.drawLineUp(x, y, color); |
|
|
|
break; |
|
|
|
case '/': |
|
|
|
this.drawLineOut(x, y, color); |
|
|
|
break; |
|
|
|
case '\\': |
|
|
|
this.drawLineIn(x, y, color); |
|
|
|
break; |
|
|
|
case '.': |
|
|
|
case ' ': |
|
|
|
break; |
|
|
|
default: |
|
|
|
console.error('Unknown symbol', symbol, color); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
class GitGraph { |
|
|
|
constructor(canvas, rawRows, config) { |
|
|
|
this.rows = []; |
|
|
|
let maxWidth = 0; |
|
|
|
|
|
|
|
for (let i = 0; i < rawRows.length; i++) { |
|
|
|
const rowStr = rawRows[i]; |
|
|
|
maxWidth = Math.max(rowStr.replace(/([_\s.-])/g, '').length, maxWidth); |
|
|
|
|
|
|
|
const rowArray = rowStr.split(''); |
|
|
|
|
|
|
|
this.rows.unshift(rowArray); |
|
|
|
} |
|
|
|
|
|
|
|
this.currentFlows = []; |
|
|
|
this.previousFlows = []; |
|
|
|
|
|
|
|
this.gitGraphCanvas = new GitGraphCanvas( |
|
|
|
canvas, |
|
|
|
maxWidth, |
|
|
|
this.rows.length, |
|
|
|
config |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
generateNewFlow(column) { |
|
|
|
let newId; |
|
|
|
|
|
|
|
do { |
|
|
|
newId = generateRandomColorString(); |
|
|
|
} while (this.hasFlow(newId, column)); |
|
|
|
|
|
|
|
return {id: newId, color: `#${newId}`}; |
|
|
|
} |
|
|
|
|
|
|
|
hasFlow(id, column) { |
|
|
|
// We want to find the flow with the current ID
|
|
|
|
// Possible flows are those in the currentFlows
|
|
|
|
// Or flows in previousFlows[column-2:...]
|
|
|
|
for ( |
|
|
|
let idx = column - 2 < 0 ? 0 : column - 2; |
|
|
|
idx < this.previousFlows.length; |
|
|
|
idx++ |
|
|
|
) { |
|
|
|
if (this.previousFlows[idx] && this.previousFlows[idx].id === id) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
for (let idx = 0; idx < this.currentFlows.length; idx++) { |
|
|
|
if (this.currentFlows[idx] && this.currentFlows[idx].id === id) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
takePreviousFlow(column) { |
|
|
|
if (column < this.previousFlows.length && this.previousFlows[column]) { |
|
|
|
const flow = this.previousFlows[column]; |
|
|
|
this.previousFlows[column] = null; |
|
|
|
return flow; |
|
|
|
} |
|
|
|
return this.generateNewFlow(column); |
|
|
|
} |
|
|
|
|
|
|
|
draw() { |
|
|
|
if (this.rows.length === 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
this.currentFlows = new Array(this.rows[0].length); |
|
|
|
|
|
|
|
// Generate flows for the first row - I do not believe that this can contain '_', '-', '.'
|
|
|
|
for (let column = 0; column < this.rows[0].length; column++) { |
|
|
|
if (this.rows[0][column] === ' ') { |
|
|
|
continue; |
|
|
|
} |
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw the first row
|
|
|
|
for (let column = 0; column < this.rows[0].length; column++) { |
|
|
|
const symbol = this.rows[0][column]; |
|
|
|
const color = this.currentFlows[column] ? this.currentFlows[column].color : ''; |
|
|
|
this.gitGraphCanvas.drawSymbol(symbol, column, 0, color); |
|
|
|
} |
|
|
|
|
|
|
|
for (let row = 1; row < this.rows.length; row++) { |
|
|
|
// Done previous row - step up the row
|
|
|
|
const currentRow = this.rows[row]; |
|
|
|
const previousRow = this.rows[row - 1]; |
|
|
|
|
|
|
|
this.previousFlows = this.currentFlows; |
|
|
|
this.currentFlows = new Array(currentRow.length); |
|
|
|
|
|
|
|
// Set flows for this row
|
|
|
|
for (let column = 0; column < currentRow.length; column++) { |
|
|
|
column = this.setFlowFor(column, currentRow, previousRow); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw this row
|
|
|
|
for (let column = 0; column < currentRow.length; column++) { |
|
|
|
const symbol = currentRow[column]; |
|
|
|
const color = this.currentFlows[column] ? this.currentFlows[column].color : ''; |
|
|
|
this.gitGraphCanvas.drawSymbol(symbol, column, row, color); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
setFlowFor(column, currentRow, previousRow) { |
|
|
|
const symbol = currentRow[column]; |
|
|
|
switch (symbol) { |
|
|
|
case '|': |
|
|
|
case '*': |
|
|
|
return this.setUpFlow(column, currentRow, previousRow); |
|
|
|
case '/': |
|
|
|
return this.setOutFlow(column, currentRow, previousRow); |
|
|
|
case '\\': |
|
|
|
return this.setInFlow(column, currentRow, previousRow); |
|
|
|
case '_': |
|
|
|
return this.setRightFlow(column, currentRow, previousRow); |
|
|
|
case '-': |
|
|
|
return this.setLeftFlow(column, currentRow, previousRow); |
|
|
|
case ' ': |
|
|
|
// In space no one can hear you flow ... (?)
|
|
|
|
return column; |
|
|
|
default: |
|
|
|
// Unexpected so let's generate a new flow and wait for bug-reports
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// setUpFlow handles '|' or '*' - returns the last column that was set
|
|
|
|
// generally we prefer to take the left most flow from the previous row
|
|
|
|
setUpFlow(column, currentRow, previousRow) { |
|
|
|
// If ' |/' or ' |_'
|
|
|
|
// '/|' '/|' -> Take the '|' flow directly beneath us
|
|
|
|
if ( |
|
|
|
column + 1 < currentRow.length && |
|
|
|
(currentRow[column + 1] === '/' || currentRow[column + 1] === '_') && |
|
|
|
column < previousRow.length && |
|
|
|
(previousRow[column] === '|' || previousRow[column] === '*') && |
|
|
|
previousRow[column - 1] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If ' |/' or ' |_'
|
|
|
|
// '/ ' '/ ' -> Take the '/' flow from the preceding column
|
|
|
|
if ( |
|
|
|
column + 1 < currentRow.length && |
|
|
|
(currentRow[column + 1] === '/' || currentRow[column + 1] === '_') && |
|
|
|
column - 1 < previousRow.length && |
|
|
|
previousRow[column - 1] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If ' |'
|
|
|
|
// '/' -> Take the '/' flow - (we always prefer the left-most flow)
|
|
|
|
if ( |
|
|
|
column > 0 && |
|
|
|
column - 1 < previousRow.length && |
|
|
|
previousRow[column - 1] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '|' OR '|' take the '|' flow
|
|
|
|
// '|' '*'
|
|
|
|
if ( |
|
|
|
column < previousRow.length && |
|
|
|
(previousRow[column] === '|' || previousRow[column] === '*') |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '| ' keep the '\' flow
|
|
|
|
// ' \'
|
|
|
|
if (column + 1 < previousRow.length && previousRow[column + 1] === '\\') { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column + 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// Otherwise just create a new flow - probably this is an error...
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// setOutFlow handles '/' - returns the last column that was set
|
|
|
|
// generally we prefer to take the left most flow from the previous row
|
|
|
|
setOutFlow(column, currentRow, previousRow) { |
|
|
|
// If '_/' -> keep the '_' flow
|
|
|
|
if (column > 0 && currentRow[column - 1] === '_') { |
|
|
|
this.currentFlows[column] = this.currentFlows[column - 1]; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '_|/' -> keep the '_' flow
|
|
|
|
if ( |
|
|
|
column > 1 && |
|
|
|
(currentRow[column - 1] === '|' || currentRow[column - 1] === '*') && |
|
|
|
currentRow[column - 2] === '_' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.currentFlows[column - 2]; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '|/'
|
|
|
|
// '/' -> take the '/' flow (if it is still available)
|
|
|
|
if ( |
|
|
|
column > 1 && |
|
|
|
currentRow[column - 1] === '|' && |
|
|
|
column - 2 < previousRow.length && |
|
|
|
previousRow[column - 2] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 2); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If ' /'
|
|
|
|
// '/' -> take the '/' flow, but transform the symbol to '|' due to our spacing
|
|
|
|
// This should only happen if there are 3 '/' - in a row so we don't need to be cleverer here
|
|
|
|
if ( |
|
|
|
column > 0 && |
|
|
|
currentRow[column - 1] === ' ' && |
|
|
|
column - 1 < previousRow.length && |
|
|
|
previousRow[column - 1] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 1); |
|
|
|
currentRow[column] = '|'; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If ' /'
|
|
|
|
// '|' -> take the '|' flow
|
|
|
|
if ( |
|
|
|
column > 0 && |
|
|
|
currentRow[column - 1] === ' ' && |
|
|
|
column - 1 < previousRow.length && |
|
|
|
(previousRow[column - 1] === '|' || previousRow[column - 1] === '*') |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '/' <- Not sure this ever happens... but take the '\' flow
|
|
|
|
// '\'
|
|
|
|
if (column < previousRow.length && previousRow[column] === '\\') { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// Otherwise just generate a new flow and wait for bug-reports...
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// setInFlow handles '\' - returns the last column that was set
|
|
|
|
// generally we prefer to take the left most flow from the previous row
|
|
|
|
setInFlow(column, currentRow, previousRow) { |
|
|
|
// If '\?'
|
|
|
|
// '/?' -> take the '/' flow
|
|
|
|
if (column < previousRow.length && previousRow[column] === '/') { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '\?'
|
|
|
|
// ' \' -> take the '\' flow and reassign to '|'
|
|
|
|
// This should only happen if there are 3 '\' - in a row so we don't need to be cleverer here
|
|
|
|
if (column + 1 < previousRow.length && previousRow[column + 1] === '\\') { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column + 1); |
|
|
|
currentRow[column] = '|'; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If '\?'
|
|
|
|
// ' |' -> take the '|' flow
|
|
|
|
if ( |
|
|
|
column + 1 < previousRow.length && |
|
|
|
(previousRow[column + 1] === '|' || previousRow[column + 1] === '*') |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column + 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// Otherwise just generate a new flow and wait for bug-reports if we're wrong...
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// setRightFlow handles '_' - returns the last column that was set
|
|
|
|
// generally we prefer to take the left most flow from the previous row
|
|
|
|
setRightFlow(column, currentRow, previousRow) { |
|
|
|
// if '__' keep the '_' flow
|
|
|
|
if (column > 0 && currentRow[column - 1] === '_') { |
|
|
|
this.currentFlows[column] = this.currentFlows[column - 1]; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// if '_|_' -> keep the '_' flow
|
|
|
|
if ( |
|
|
|
column > 1 && |
|
|
|
currentRow[column - 1] === '|' && |
|
|
|
currentRow[column - 2] === '_' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.currentFlows[column - 2]; |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// if ' _' -> take the '/' flow
|
|
|
|
// '/ '
|
|
|
|
if ( |
|
|
|
column > 0 && |
|
|
|
column - 1 < previousRow.length && |
|
|
|
previousRow[column - 1] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 1); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// if ' |_'
|
|
|
|
// '/? ' -> take the '/' flow (this may cause generation...)
|
|
|
|
// we can do this because we know that git graph
|
|
|
|
// doesn't create compact graphs like: ' |_'
|
|
|
|
// '//'
|
|
|
|
if ( |
|
|
|
column > 1 && |
|
|
|
column - 2 < previousRow.length && |
|
|
|
previousRow[column - 2] === '/' |
|
|
|
) { |
|
|
|
this.currentFlows[column] = this.takePreviousFlow(column - 2); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// There really shouldn't be another way of doing this - generate and wait for bug-reports...
|
|
|
|
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// setLeftFlow handles '----.' - returns the last column that was set
|
|
|
|
// generally we prefer to take the left most flow from the previous row that terminates this left recursion
|
|
|
|
setLeftFlow(column, currentRow, previousRow) { |
|
|
|
// This is: '----------.' or the like
|
|
|
|
// ' \ \ /|\'
|
|
|
|
|
|
|
|
// Find the end of the '-' or nearest '/|\' in the previousRow :
|
|
|
|
let originalColumn = column; |
|
|
|
let flow; |
|
|
|
for (; column < currentRow.length && currentRow[column] === '-'; column++) { |
|
|
|
if (column > 0 && column - 1 < previousRow.length && previousRow[column - 1] === '/') { |
|
|
|
flow = this.takePreviousFlow(column - 1); |
|
|
|
break; |
|
|
|
} else if (column < previousRow.length && previousRow[column] === '|') { |
|
|
|
flow = this.takePreviousFlow(column); |
|
|
|
break; |
|
|
|
} else if ( |
|
|
|
column + 1 < previousRow.length && |
|
|
|
previousRow[column + 1] === '\\' |
|
|
|
) { |
|
|
|
flow = this.takePreviousFlow(column + 1); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// if we have a flow then we found a '/|\' in the previousRow
|
|
|
|
if (flow) { |
|
|
|
for (; originalColumn < column + 1; originalColumn++) { |
|
|
|
this.currentFlows[originalColumn] = flow; |
|
|
|
} |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// If the symbol in the column is not a '.' then there's likely an error
|
|
|
|
if (currentRow[column] !== '.') { |
|
|
|
// It really should end in a '.' but this one doesn't...
|
|
|
|
// 1. Step back - we don't want to eat this column
|
|
|
|
column--; |
|
|
|
// 2. Generate a new flow and await bug-reports...
|
|
|
|
this.currentFlows[column] = this.generateNewFlow(column); |
|
|
|
|
|
|
|
// 3. Assign all of the '-' to the same flow.
|
|
|
|
for (; originalColumn < column; originalColumn++) { |
|
|
|
this.currentFlows[originalColumn] = this.currentFlows[column]; |
|
|
|
} |
|
|
|
return column; |
|
|
|
} |
|
|
|
|
|
|
|
// We have a terminal '.' eg. the current row looks like '----.'
|
|
|
|
// the previous row should look like one of '/|\' eg. ' \'
|
|
|
|
if (column > 0 && column - 1 < previousRow.length && previousRow[column - 1] === '/') { |
|
|
|
flow = this.takePreviousFlow(column - 1); |
|
|
|
} else if (column < previousRow.length && previousRow[column] === '|') { |
|
|
|
flow = this.takePreviousFlow(column); |
|
|
|
} else if ( |
|
|
|
column + 1 < previousRow.length && |
|
|
|
previousRow[column + 1] === '\\' |
|
|
|
) { |
|
|
|
flow = this.takePreviousFlow(column + 1); |
|
|
|
} else { |
|
|
|
// Again unexpected so let's generate and wait the bug-report
|
|
|
|
flow = this.generateNewFlow(column); |
|
|
|
} |
|
|
|
|
|
|
|
// Assign all of the rest of the ----. to this flow.
|
|
|
|
for (; originalColumn < column + 1; originalColumn++) { |
|
|
|
this.currentFlows[originalColumn] = flow; |
|
|
|
} |
|
|
|
|
|
|
|
return column; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function generateRandomColorString() { |
|
|
|
const chars = '0123456789ABCDEF'; |
|
|
|
const stringLength = 6; |
|
|
|
let randomString = '', |
|
|
|
rnum, |
|
|
|
i; |
|
|
|
for (i = 0; i < stringLength; i++) { |
|
|
|
rnum = Math.floor(Math.random() * chars.length); |
|
|
|
randomString += chars.substring(rnum, rnum + 1); |
|
|
|
} |
|
|
|
|
|
|
|
return randomString; |
|
|
|
} |
|
|
|
|
|
|
|
export default async function initGitGraph() { |
|
|
|
const graphCanvas = document.getElementById('graph-canvas'); |
|
|
|
if (!graphCanvas) return; |
|
|
|
|
|
|
|
const {default: gitGraph} = await import(/* webpackChunkName: "gitgraph" */'../vendor/gitgraph.js'); |
|
|
|
if (!graphCanvas || !graphCanvas.getContext) return; |
|
|
|
|
|
|
|
// Grab the raw graphList
|
|
|
|
const graphList = []; |
|
|
|
$('#graph-raw-list li span.node-relation').each(function () { |
|
|
|
graphList.push($(this).text()); |
|
|
|
}); |
|
|
|
|
|
|
|
gitGraph(graphCanvas, graphList); |
|
|
|
// Define some drawing parameters
|
|
|
|
const config = { |
|
|
|
unitSize: 20, |
|
|
|
lineWidth: 3, |
|
|
|
nodeRadius: 4 |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const gitGraph = new GitGraph(graphCanvas, graphList, config); |
|
|
|
gitGraph.draw(); |
|
|
|
graphCanvas.closest('#git-graph-container').classList.add('in'); |
|
|
|
} |