diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8f23559d586..17488c256db 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -96,42 +96,42 @@ Example: Workflow -------- -### Stable branch: `master` +### Stable branches: `yarp-3.x` -The `master` branch is stable and **should not receive new features**. +The `yarp-3.x` branch is stable and **should not receive new features**. Only **bug fixes** are accepted. -This is the typical workflow to fix a bug in the master branch. +This is the typical workflow to fix a bug in the yarp-3.x branches. * Identify a bug that does not require breaking changes of the API/ABI. * Open an issue on github. -* Add some label (FIXME which label?). +* Add some labels. * Assign the issue to yourself. -* Create a new branch starting from the `master` branch: +* Create a new branch starting from the `yarp-3.x` branch: ``` git fetch origin -git checkout -b origin/master +git checkout -b origin/yarp-3.x ``` * Fix the bug and make one or more commits. * [Push the branch on your fork and create a pull request](https://help.github.com/categories/collaborating-on-projects-using-pull-requests/). * Wait for someone else to review your fix and merge your pull request. -* Your fix is now in the `master` branch, now you need to port it to the `devel` - branch. +* Your fix is now in the `yarp-3.x` branch, now you need to port it to the newer + `yarp-3.x+1` branches (if any), and to the `master` branch. * Ensure that your branches are in sync with `origin`: ``` +git checkout yarp-3.x +git pull --rebase origin yarp-3.x git checkout master git pull --rebase origin master -git checkout devel -git pull --rebase origin devel ``` - * Merge master into devel and eventually fix the conflicts. + * Merge yarp-3.x into master and eventually fix the conflicts. ``` -git merge master +git merge yarp-3.x ``` ##### Work in progress PR @@ -144,47 +144,44 @@ Once you're happy about your work, just remove the `[WIP]` tag as well as the la and drop a message within the PR to notify the community that reviews are welcome and merging is now possible. -### Development branch: `devel` +### Development branch: `master` -We use the branch `devel` to collect the ongoing work, which is given in terms +We use the branch `master` to collect the ongoing work, which is given in terms of **new features** and **bug fixes**. +When we start the development of a new feature release, the tweak number is +bumped to 100. This number can be checked from CMake in downstream projects to +ensure that the user has all the required features. When we introduce a new feature that will cause downstream projects to be aware -of such update, we do increase the tweak number (always sticking to -_odd numbers_). - -When we decide to publish these new features in a new software release (roughly -each _3 months_), we merge the new modifications into `master`, doing: - -```sh -git checkout master -git merge --no-ff devel -git push origin master -``` - +of such update, we do increase the tweak number. ### Example This is an example of workflow involving: -* A bug fixed in the `bugfix_xxx` branch (gray) and later merged on the `master` - branch (blue). -* A few stable tags in the `master` branch: - * **v3.0.1** is latest stable tag for the YARP 3.0 release series. - * **v3.1.0** is the first stable tag for the YARP 3.1 release series. - * **v3.1.1** is a stable tag (bug fixes only) for the YARP 3.1 release - series. **v3.1.0** and **v3.1.1** are compatible (both API and ABI). -* The development of a new feature developed in the `feature_foo` branch (orange) - and later merged in the `devel` branch (purple). -* Two fake development tag in the `devel` branch: - * **v3.1.100** that represents the beginning of the development of the next - stable release. - * **v3.1.101** that includes one new feature. +* A security fix (turquoise branch) fixed in the `yarp-3.3` branch (gray) and + later merged on the `yarp-3.4` (blue) and `master` branches (green). +* A bug fix (purple branch) (fixed in the `yarp-3.4` branch (gray) and later + merged on the `master` branch. +* A new feature (orange branch) merged in the `devel` branch (purple). +* A few tags: + * **v3.3.0** is the first tag (introducing new features) for the YARP 3.3 release series. + * **v3.3.1** is a stable tag (bug fixes only) for the YARP 3.3 release series. + * **v3.3.2** is the latest stable (bug fixes only) tag for the YARP 3.3 release series. + * **v3.4.0** is the first tag (introducing new features) for the YARP 3.4 release series. + * **v3.4.1** is the latest stable tag for the YARP 3.1 release series. + * **v3.1.1** is a stable tag for the YARP 3.1 release series. +* A few fake development tags in the `master` branch: + * **v3.3.100** that represents the beginning of the development of the next + YARP 3.4 release. + * **v3.4.100** that represents the beginning of the development of the next + YARP 3.5 release. + * **v3.4.101** that includes one new feature. These are not tagged for real in the repository, but represents the actual version number that other projects can check in order to require a specific feature and print an error that is easy to understand when that feature is not - available (i.e. in CMake `find_package(YARP 3.1.101 REQUIRED)`) + available (i.e. in CMake `find_package(YARP 3.4.101 REQUIRED)`) ![YARP Workflow](git-workflow.png) @@ -196,8 +193,8 @@ This is an example of workflow involving: - **Versioning format**: the versioning system we adopt complies with the format <**major**>.<**minor**>.<**patch**>. Starting with YARP 3.0.0, the _patch_ version number is a number lower than - 100 for stable releases (tagged in `master`), and a number greater or equal - than 100 for unstable releases (tagged in `devel`). + 100 for stable releases, and a number greater or equal than 100 for unstable + releases. diff --git a/.github/git-workflow.png b/.github/git-workflow.png index 60277e0f125..508dd879716 100644 Binary files a/.github/git-workflow.png and b/.github/git-workflow.png differ diff --git a/.github/git-workflow/gitgraph.js b/.github/git-workflow/gitgraph.js index 6d08448f268..a85da5fd0f5 100644 --- a/.github/git-workflow/gitgraph.js +++ b/.github/git-workflow/gitgraph.js @@ -1,1287 +1 @@ -(function () { - "use strict"; - - /** - * Emit an event on the given element. - * - * @param {HTMLElement} element - DOM element to trigger the event on. - * @param {String} eventName - Name of the triggered event. - * @param {Object} [data={}] - Custom data to attach to the event. - * @private - */ - function _emitEvent ( element, eventName, data ) { - var event; - - if ( document.createEvent ) { - event = document.createEvent( "HTMLEvents" ); - event.initEvent( eventName, true, true ); - } else { - event = document.createEventObject(); - event.eventType = eventName; - } - - event.eventName = eventName; - event.data = data || {}; - - if ( document.createEvent ) { - element.dispatchEvent( event ); - } else { - element.fireEvent( "on" + event.eventType, event ); - } - } - - /** - * Returns the scaling factor of given canvas `context`. - * Handles high-resolution displays. - * - * @param {Object} context - * @returns {Number} - * @private - */ - function _getScale ( context ) { - var backingStorePixelRatio; - var scalingFactor; - - // Account for high-resolution displays - scalingFactor = 1; - - if ( window.devicePixelRatio ) { - backingStorePixelRatio = context.webkitBackingStorePixelRatio || - context.mozBackingStorePixelRatio || - context.msBackingStorePixelRatio || - context.oBackingStorePixelRatio || - context.backingStorePixelRatio || 1; - - scalingFactor *= window.devicePixelRatio / backingStorePixelRatio; - } - - return scalingFactor; - } - - /** - * Returns `true` if `graph` has a vertical orientation. - * - * @param {GitGraph} graph - * @returns {boolean} - * @private - */ - function _isVertical ( graph ) { - return (graph.orientation === "vertical" || graph.orientation === "vertical-reverse"); - } - - /** - * Returns `true` if `graph` has an horizontal orientation. - * - * @param {GitGraph} graph - * @returns {boolean} - * @private - */ - function _isHorizontal ( graph ) { - return (graph.orientation === "horizontal" || graph.orientation === "horizontal-reverse"); - } - - /** - * GitGraph - * - * @constructor - * - * @param {Object} options - GitGraph options - * @param {String} [options.elementId = "gitGraph"] - Id of the canvas container - * @param {Template|String|Object} [options.template] - Template of the graph - * @param {String} [options.author = "Sergio Flores "] - Default author for commits - * @param {String} [options.mode = (null|"compact")] - Display mode - * @param {HTMLElement} [options.canvas] - DOM canvas (ex: document.getElementById("id")) - * @param {String} [options.orientation = ("vertical-reverse"|"horizontal"|"horizontal-reverse")] - Graph orientation - * @param {Boolean} [options.reverseArrow = false] - Make arrows point to ancestors if true - * - * @this GitGraph - **/ - function GitGraph ( options ) { - // Options - options = (typeof options === "object") ? options : {}; - this.elementId = (typeof options.elementId === "string") ? options.elementId : "gitGraph"; - this.author = (typeof options.author === "string") ? options.author : "Sergio Flores "; - this.reverseArrow = booleanOptionOr( options.reverseArrow, false ); - - // Template management - if ( (typeof options.template === "string") - || (typeof options.template === "object") ) { - this.template = this.newTemplate( options.template ); - } else if ( options.template instanceof Template ) { - this.template = options.template; - } else { - this.template = this.newTemplate( "metro" ); - } - - this.mode = options.mode || null; - if ( this.mode === "compact" ) { - this.template.commit.message.display = false; - } - - // Orientation - switch ( options.orientation ) { - case "vertical-reverse" : - this.template.commit.spacingY *= -1; - this.orientation = "vertical-reverse"; - this.template.branch.labelRotation = 0; - this.template.commit.tag.spacingY *= -1; - break; - case "horizontal" : - this.template.commit.message.display = false; - this.template.commit.spacingX = this.template.commit.spacingY; - this.template.branch.spacingY = this.template.branch.spacingX; - this.template.commit.spacingY = 0; - this.template.branch.spacingX = 0; - this.orientation = "horizontal"; - this.template.branch.labelRotation = -90; - this.template.commit.tag.spacingX = -this.template.commit.spacingX; - this.template.commit.tag.spacingY = this.template.branch.spacingY; - break; - case "horizontal-reverse" : - this.template.commit.message.display = false; - this.template.commit.spacingX = -this.template.commit.spacingY; - this.template.branch.spacingY = this.template.branch.spacingX; - this.template.commit.spacingY = 0; - this.template.branch.spacingX = 0; - this.orientation = "horizontal-reverse"; - this.template.branch.labelRotation = 90; - this.template.commit.tag.spacingX = -this.template.commit.spacingY; - this.template.commit.tag.spacingY = this.template.branch.spacingY; - break; - default: - this.orientation = "vertical"; - this.template.branch.labelRotation = 0; - break; - } - - this.marginX = this.template.branch.spacingX + this.template.commit.dot.size * 2; - this.marginY = this.template.branch.spacingY + this.template.commit.dot.size * 2; - this.offsetX = 0; - this.offsetY = 0; - - // Canvas init - this.canvas = document.getElementById( this.elementId ) || options.canvas; - this.context = this.canvas.getContext( "2d" ); - this.context.textBaseline = "center"; - - // Tooltip layer - this.tooltip = document.createElement( "div" ); - this.tooltip.className = "gitgraph-tooltip"; - this.tooltip.style.position = "fixed"; - this.tooltip.style.display = "none"; - - // Add tooltip div into body - document.body.appendChild( this.tooltip ); - - // Navigation vars - this.HEAD = null; - this.branches = []; - this.commits = []; - - // Utilities - this.columnMax = 0; // nb of column for message position - this.commitOffsetX = 0; - this.commitOffsetY = 0; - - // Bindings - var mouseMoveOptions = { - handleEvent: this.hover, - gitgraph: this - }; - this.canvas.addEventListener( "mousemove", mouseMoveOptions, false ); - - var mouseDownOptions = { - handleEvent: this.click, - gitgraph: this - }; - this.canvas.addEventListener( "mousedown", mouseDownOptions, false ); - - // Render on window resize - window.onresize = this.render.bind( this ); - } - - /** - * Create new branch - * - * @param {(String | Object)} options - Branch name | Options of Branch - * - * @see Branch - * @this GitGraph - * - * @return {Branch} New branch - **/ - GitGraph.prototype.branch = function ( options ) { - // Options - if ( typeof options === "string" ) { - var name = options; - options = {}; - options.name = name; - } - - options = (typeof options === "object") ? options : {}; - options.parent = this; - options.parentBranch = options.parentBranch || this.HEAD; - - // Add branch - var branch = new Branch( options ); - this.branches.push( branch ); - - // Return - return branch; - }; - - /** - * Create new orphan branch - * - * @param {(String | Object)} options - Branch name | Options of Branch - * - * @see Branch - * @this GitGraph - * - * @return {Branch} New branch - **/ - GitGraph.prototype.orphanBranch = function ( options ) { - // Options - if ( typeof options === "string" ) { - var name = options; - options = {}; - options.name = name; - } - - options = (typeof options === "object") ? options : {}; - options.parent = this; - - // Add branch - var branch = new Branch( options ); - this.branches.push( branch ); - - // Return - return branch; - }; - - /** - * Commit on HEAD - * - * @param {Object} options - Options of commit - * - * @see Commit - * @this GitGraph - * - * @return {GitGraph} this - Return the main object so we can chain - **/ - GitGraph.prototype.commit = function ( options ) { - this.HEAD.commit( options ); - - // Return the main object so we can chain - return this; - }; - - /** - * Create a new template - * - * @param {(String|Object)} options - The template name, or the template options - * - * @return {Template} - **/ - GitGraph.prototype.newTemplate = function ( options ) { - if ( typeof options === "string" ) { - return new Template().get( options ); - } - return new Template( options ); - }; - - /** - * Render the canvas - * - * @this GitGraph - **/ - GitGraph.prototype.render = function () { - this.scalingFactor = _getScale( this.context ); - - // Resize canvas - var unscaledResolution = { - x: Math.abs( (this.columnMax + 1 ) * this.template.branch.spacingX ) - + Math.abs( this.commitOffsetX ) - + this.marginX * 2, - y: Math.abs( (this.columnMax + 1 ) * this.template.branch.spacingY ) - + Math.abs( this.commitOffsetY ) - + this.marginY * 2 - }; - - if ( this.template.commit.message.display ) { - unscaledResolution.x += 800; - } - - unscaledResolution.x += this.template.commit.widthExtension; - - this.canvas.style.width = unscaledResolution.x + "px"; - this.canvas.style.height = unscaledResolution.y + "px"; - - this.canvas.width = unscaledResolution.x * this.scalingFactor; - this.canvas.height = unscaledResolution.y * this.scalingFactor; - - // Clear All - this.context.clearRect( 0, 0, this.canvas.width, this.canvas.height ); - - // Add some margin - this.context.translate( this.marginX, this.marginY ); - - // Translate for inverse orientation - if ( this.template.commit.spacingY > 0 ) { - this.context.translate( 0, this.canvas.height - this.marginY * 2 ); - this.offsetY = this.canvas.height - this.marginY * 2; - } - if ( this.template.commit.spacingX > 0 ) { - this.context.translate( this.canvas.width - this.marginX * 2, 0 ); - this.offsetX = this.canvas.width - this.marginX * 2; - } - - // Scale the context when every transformations have been made. - this.context.scale( this.scalingFactor, this.scalingFactor ); - - // Render branches - for ( var i = this.branches.length - 1, branch; !!(branch = this.branches[ i ]); i-- ) { - branch.render(); - } - - this.tagNum = 0; - - // Render commits after to put them on the foreground - for ( var j = 0, commit; !!(commit = this.commits[ j ]); j++ ) { - commit.render(); - } - - _emitEvent( this.canvas, "graph:render", { id: this.elementId } ); - }; - - /** - * A callback for each commit - * - * @callback commitCallback - * @param {Commit} commit - A commit - * @param {boolean} mouseOver - True, if the mouse is currently hovering over the commit - */ - - /** - * Hover event on commit dot - * - * @param {MouseEvent} event - Mouse event - * @param {commitCallback} callbackFn - A callback function that will be called for each commit - * - * @this GitGraph - **/ - GitGraph.prototype.applyCommits = function ( event, callbackFn ) { - for ( var i = 0, commit; !!(commit = this.commits[ i ]); i++ ) { - var distanceX = (commit.x + (this.offsetX + this.marginX) / this.scalingFactor - event.offsetX); - var distanceY = (commit.y + (this.offsetY + this.marginY) / this.scalingFactor - event.offsetY); - var distanceBetweenCommitCenterAndMouse = Math.sqrt( Math.pow( distanceX, 2 ) + Math.pow( distanceY, 2 ) ); - var isOverCommit = distanceBetweenCommitCenterAndMouse < this.template.commit.dot.size; - - callbackFn( commit, isOverCommit ); - } - }; - - /** - * Hover event on commit dot - * - * @param {MouseEvent} event - Mouse event - * - * @this GitGraph - **/ - GitGraph.prototype.hover = function ( event ) { - var self = this.gitgraph; - var isOut = true; - - function showCommitTooltip ( commit ) { - // Fix firefox MouseEvent - if ( typeof InstallTrigger !== "undefined" )/* == (is Firefox) */ { - event.x = event.x ? event.x : event.clientX; - event.y = event.y ? event.y : event.clientY; - } - - self.tooltip.style.left = event.x + "px"; // TODO Scroll bug - self.tooltip.style.top = event.y + "px"; // TODO Scroll bug - if ( self.template.commit.tooltipHTMLFormatter !== null ) { - self.tooltip.innerHTML = self.template.commit.tooltipHTMLFormatter( commit ); - } else { - self.tooltip.textContent = commit.sha1 + " - " + commit.message; - } - self.tooltip.style.display = "block"; - } - - function emitCommitEvent ( commit, event ) { - var mouseEventOptions = { - author: commit.author, - message: commit.message, - date: commit.date, - sha1: commit.sha1 - }; - - _emitEvent( self.canvas, "commit:" + event, mouseEventOptions ); - } - - self.applyCommits( event, function ( commit, isOverCommit ) { - if ( isOverCommit ) { - if ( !self.template.commit.message.display ) { - showCommitTooltip( commit ); - } - - // Don't emit event if we already were over a commit. - if ( !commit.isMouseOver ) { - emitCommitEvent( commit, "mouseover" ); - } - - isOut = false; - commit.isMouseOver = true; - } else { - // Don't emit event if we already were out of a commit. - if ( commit.isMouseOver ) { - emitCommitEvent( commit, "mouseout" ); - } - commit.isMouseOver = false; - } - } ); - - if ( isOut ) { - self.tooltip.style.display = "none"; - } - }; - - /** - * Click event on commit dot - * - * @param {MouseEvent} event - Mouse event - * - * @this GitGraph - **/ - GitGraph.prototype.click = function ( event ) { - this.gitgraph.applyCommits( event, function ( commit, isOverCommit ) { - if ( !isOverCommit ) { - return; - } - - if ( commit.onClick !== null ) { - commit.onClick( commit, true ); - } - } ); - }; - - // -------------------------------------------------------------------- - // ----------------------- Branch ------------------------ - // -------------------------------------------------------------------- - - /** - * Branch - * - * @constructor - * - * @param {Object} options - Options of branch - * @param {GitGraph} options.parent - GitGraph constructor - * @param {Branch} [options.parentBranch] - Parent branch - * @param {String} [options.name = "no-name"] - Branch name - * - * @this Branch - **/ - function Branch ( options ) { - // Check integrity - if ( options.parent instanceof GitGraph === false ) { - return; - } - - // Options - options = (typeof options === "object") ? options : {}; - this.parent = options.parent; - this.parentBranch = options.parentBranch; - this.name = (typeof options.name === "string") ? options.name : "no-name"; - this.context = this.parent.context; - this.template = this.parent.template; - this.lineWidth = options.lineWidth || this.template.branch.lineWidth; - this.lineDash = options.lineDash || this.template.branch.lineDash; - this.showLabel = booleanOptionOr( options.showLabel, this.template.branch.showLabel ); - this.spacingX = this.template.branch.spacingX; - this.spacingY = this.template.branch.spacingY; - this.size = 0; - this.height = 0; - this.width = 0; - this.commits = []; - this.path = []; // Path to draw, this is an array of points {x, y, type("start"|"join"|"end")} - - // Column number calculation for auto-color & auto-offset - if ( typeof options.column === "number" ) { - this.column = options.column; - } else { - this.column = 0; - this.calculColumn(); - } - - this.parent.columnMax = (this.column > this.parent.columnMax) ? this.column : this.parent.columnMax; - - // Options with auto value - this.offsetX = this.column * this.spacingX; - this.offsetY = this.column * this.spacingY; - - var columnIndex = (this.column % this.template.colors.length); - this.color = options.color || this.template.branch.color || this.template.colors[ columnIndex ]; - - // Checkout on this new branch - this.checkout(); - } - - /** - * Create new branch - * - * @param {(String | Object)} options - Branch name | Options of Branch - * - * @see Branch - * @this Branch - * - * @return {Branch} New Branch - **/ - Branch.prototype.branch = function ( options ) { - // Options - if ( typeof options === "string" ) { - var name = options; - options = {}; - options.name = name; - } - - options = (typeof options === "object") ? options : {}; - options.parent = this.parent; - options.parentBranch = options.parentBranch || this; - - // Add branch - var branch = new Branch( options ); - this.parent.branches.push( branch ); - - // Return - return branch; - }; - - /** - * Render the branch - * - * @this Branch - **/ - Branch.prototype.render = function () { - this.context.beginPath(); - - for ( var i = 0, point; !!(point = this.path[ i ]); i++ ) { - if ( point.type === "start" ) { - this.context.moveTo( point.x, point.y ); - } else { - if ( this.template.branch.mergeStyle === "bezier" ) { - var path = this.path[ i - 1 ]; - - this.context.bezierCurveTo( - path.x - this.template.commit.spacingX / 2, path.y - this.template.commit.spacingY / 2, - point.x + this.template.commit.spacingX / 2, point.y + this.template.commit.spacingY / 2, - point.x, point.y - ); - } else { - this.context.lineTo( point.x, point.y ); - } - } - } - - this.context.lineWidth = this.lineWidth; - this.context.strokeStyle = this.color; - if ( this.context.setLineDash !== undefined ) { - this.context.setLineDash( this.lineDash ); - } - this.context.stroke(); - this.context.closePath(); - }; - - /** - * Add a commit - * - * @param {(String | Object)} [options] - Message | Options of commit - * @param {String} [options.detailId] - Id of detail DOM Element - * - * @see Commit - * - * @this Branch - **/ - Branch.prototype.commit = function ( options ) { - if ( typeof (options) === "string" ) { - options = { message: options }; - } else if ( typeof (options) !== "object" ) { - options = {}; - } - - options.arrowDisplay = this.template.arrow.active; - options.branch = this; - var columnIndex = (this.column % this.template.colors.length); - options.color = options.color || this.template.commit.color || this.template.colors[ columnIndex ]; - options.parent = this.parent; - options.parentCommit = options.parentCommit || this.commits.slice( -1 )[ 0 ]; - - // Special compact mode - if ( this.parent.mode === "compact" - && this.parent.commits.slice( -1 )[ 0 ] - && this.parent.commits.slice( -1 )[ 0 ].branch !== options.branch - && options.branch.commits.length - && options.type !== "mergeCommit" ) { - this.parent.commitOffsetX -= this.template.commit.spacingX; - this.parent.commitOffsetY -= this.template.commit.spacingY; - } - - options.messageColor = options.messageColor || this.template.commit.message.color || options.color || null; - options.labelColor = options.labelColor || this.template.branch.labelColor || options.color || null; - options.tagColor = options.tagColor || this.template.commit.tag.color || options.color || null; - options.dotColor = options.dotColor || this.template.commit.dot.color || options.color || null; - options.x = this.offsetX - this.parent.commitOffsetX; - options.y = this.offsetY - this.parent.commitOffsetY; - - // Detail - var isVertical = this.parent.orientation === "vertical"; - var isNotCompact = this.parent.mode !== "compact"; - if ( typeof options.detailId === "string" && isVertical && isNotCompact ) { - options.detail = document.getElementById( options.detailId ); - } else { - options.detail = null; - } - - // Check collision (Cause of special compact mode) - var previousCommit = options.branch.commits.slice( -1 )[ 0 ] || {}; - var commitPosition = options.x + options.y; - var previousCommitPosition = previousCommit.x + previousCommit.y; - var isCommitAtSamePlaceThanPreviousOne = (commitPosition === previousCommitPosition); - - if ( isCommitAtSamePlaceThanPreviousOne ) { - this.parent.commitOffsetX += this.template.commit.spacingX; - this.parent.commitOffsetY += this.template.commit.spacingY; - options.x = this.offsetX - this.parent.commitOffsetX; - options.y = this.offsetY - this.parent.commitOffsetY; - } - - // Fork case: Parent commit from parent branch - if ( options.parentCommit instanceof Commit === false && this.parentBranch instanceof Branch ) { - options.parentCommit = this.parentBranch.commits.slice( -1 )[ 0 ]; - } - - // First commit - var isFirstBranch = options.parentCommit instanceof Commit; - var isPathBeginning = this.path.length === 0; - - options.showLabel = (isPathBeginning && this.showLabel) ? true : false; - - if ( options.showLabel ) { - options.x -= this.template.commit.spacingX; - options.y -= this.template.commit.spacingY; - } - - var commit = new Commit( options ); - this.commits.push( commit ); - - // Add point(s) to path - var point = { - x: commit.x, - y: commit.y, - type: "join" - }; - - if ( isFirstBranch && isPathBeginning ) { - var parent = { - x: commit.parentCommit.branch.offsetX - this.parent.commitOffsetX + this.template.commit.spacingX, - y: commit.parentCommit.branch.offsetY - this.parent.commitOffsetY + this.template.commit.spacingY, - type: "start" - }; - this.path.push( JSON.parse( JSON.stringify( parent ) ) ); // Elegant way for cloning an object - parent.type = "join"; - this.parentBranch.path.push( parent ); - } else if ( isPathBeginning ) { - point.type = "start"; - } - - // Increment commitOffset for next commit position - this.path.push( point ); - - this.parent.commitOffsetX += this.template.commit.spacingX * (options.showLabel ? 2 : 1); - this.parent.commitOffsetY += this.template.commit.spacingY * (options.showLabel ? 2 : 1); - - // Add height of detail div (normal vertical mode only) - if ( commit.detail !== null ) { - commit.detail.style.display = "block"; - this.parent.commitOffsetY -= commit.detail.clientHeight - 40; - } - - // Auto-render - this.parent.render(); - - // Return the main object so we can chain - return this; - }; - - /** - * Checkout onto this branch - * - * @this Branch - **/ - Branch.prototype.checkout = function () { - this.parent.HEAD = this; - }; - - /** - * Delete this branch - * - * @this Branch - **/ - Branch.prototype.delete = function () { - this.isfinish = true; - }; - - /** - * Merge branch - * - * @param {Branch} [target = this.parent.HEAD] - * @param {(String | Object)} [commitOptions] - Message | Options of commit - * - * @this Branch - * - * @return {Branch} this - **/ - Branch.prototype.merge = function ( target, commitOptions ) { - // Merge target - var targetBranch = target || this.parent.HEAD; - - // Check integrity of target - if ( targetBranch instanceof Branch === false || targetBranch === this ) { - return this; - } - - // Merge commit - var defaultMessage = "Merge branch `" + this.name + "` into `" + targetBranch.name + "`"; - if ( typeof commitOptions !== "object" ) { - var message = commitOptions; - commitOptions = {}; - commitOptions.message = (typeof message === "string") ? message : defaultMessage; - } else { - commitOptions.message = commitOptions.message || defaultMessage; - } - commitOptions.type = "mergeCommit"; - commitOptions.parentCommit = this.commits.slice( -1 )[ 0 ]; - - targetBranch.commit( commitOptions ); - - // Add points to path - var targetCommit = targetBranch.commits.slice( -1 )[ 0 ]; - var endOfBranch = { - x: this.offsetX + this.template.commit.spacingX * (targetCommit.showLabel ? 3 : 2) - this.parent.commitOffsetX, - y: this.offsetY + this.template.commit.spacingY * (targetCommit.showLabel ? 3 : 2) - this.parent.commitOffsetY, - type: "join" - }; - this.path.push( JSON.parse( JSON.stringify( endOfBranch ) ) ); // Elegant way for cloning an object - - var mergeCommit = { - x: targetCommit.x, - y: targetCommit.y, - type: "end" - }; - this.path.push( mergeCommit ); - - endOfBranch.type = "start"; - this.path.push( endOfBranch ); // End of branch for future commits - - // Auto-render - this.parent.render(); - - // Checkout on target - this.parent.HEAD = targetBranch; - - // Return the main object so we can chain - return this; - }; - - /** - * Calcul column - * - * @this Branch - **/ - Branch.prototype.calculColumn = function () { - var candidates = []; - for ( var i = 0, branch; !!(branch = this.parent.branches[ i ]); i++ ) { - if ( !branch.isfinish ) { - if ( !( branch.column in candidates ) ) { - candidates[ branch.column ] = 0; - } - candidates[ branch.column ]++; - } - } - - this.column = 0; - for ( ; ; this.column++ ) { - if ( !( this.column in candidates ) || candidates[ this.column ] === 0 ) { - break; - } - } - }; - - // -------------------------------------------------------------------- - // ----------------------- Commit ------------------------ - // -------------------------------------------------------------------- - - /** - * Commit - * - * @constructor - * - * @param {Object} options - Commit options - * @param {GitGraph} options.parent - GitGraph constructor - * @param {Number} options.x - Position X (dot) - * @param {Number} options.y - Position Y (dot) - * @param {String} options.color - Master color (dot & message) - * @param {Boolean} options.arrowDisplay - Add a arrow under commit dot - * @param {String} [options.author = this.parent.author] - Author name & email - * @param {String} [options.date] - Date of commit, default is now - * @param {String} [options.detail] - DOM Element of detail part - * @param {String} [options.sha1] - Sha1, default is a random short sha1 - * @param {Commit} [options.parentCommit] - Parent commit - * @param {String} [options.type = ("mergeCommit"|null)] - Type of commit - * - * @param {String} [options.tag] - Tag of the commit - * @param {String} [options.tagColor = options.color] - Specific tag color - * @param {String} [options.tagFont = this.template.commit.tag.font] - Font of the tag - * - * @param {String} [options.dotColor = options.color] - Specific dot color - * @param {Number} [options.dotSize = this.template.commit.dot.size] - Dot size - * @param {Number} [options.dotStrokeWidth = this.template.commit.dot.strokeWidth] - Dot stroke width - * @param {Number} [options.dotStrokeColor = this.template.commit.dot.strokeColor] - * - * @param {String} [options.message = "He doesn't like George Michael! Boooo!"] - Commit message - * @param {String} [options.messageColor = options.color] - Specific message color - * @param {String} [options.messageFont = this.template.commit.message.font] - Font of the message - * @param {Boolean} [options.messageDisplay = this.template.commit.message.display] - Commit message policy - * @param {Boolean} [options.messageAuthorDisplay = this.template.commit.message.displayAuthor] - Commit message author policy - * @param {Boolean} [options.messageBranchDisplay = this.template.commit.message.displayBranch] - Commit message author policy - * @param {Boolean} [options.messageHashDisplay = this.template.commit.message.displayHash] - Commit message hash policy - * - * @param {String} [options.labelColor = options.color] - Specific label color - * @param {String} [options.labelFont = this.template.branch.labelFont] - Font used for labels - * - * @param {commitCallback} [options.onClick] - OnClick event for the commit dot - * @param {Object} [options.representedObject] - Any object which is related to this commit. Can be used in onClick or the formatter. Useful to bind the commit to external objects such as database id etc. - * - * @this Commit - **/ - function Commit ( options ) { - // Check integrity - if ( options.parent instanceof GitGraph === false ) { - return; - } - - // Options - options = (typeof options === "object") ? options : {}; - this.parent = options.parent; - this.template = this.parent.template; - this.context = this.parent.context; - this.branch = options.branch; - this.author = options.author || this.parent.author; - this.date = options.date || new Date().toUTCString(); - this.detail = options.detail || null; - this.tag = options.tag || null; - this.tagColor = options.tagColor || options.color; - this.tagFont = options.tagFont || this.template.commit.tag.font; - this.sha1 = options.sha1 || (Math.random( 100 )).toString( 16 ).substring( 3, 10 ); - this.message = options.message || "He doesn't like George Michael! Boooo!"; - this.arrowDisplay = options.arrowDisplay; - this.messageDisplay = booleanOptionOr( options.messageDisplay, this.template.commit.message.display ); - this.messageAuthorDisplay = booleanOptionOr( options.messageAuthorDisplay, this.template.commit.message.displayAuthor ); - this.messageBranchDisplay = booleanOptionOr( options.messageBranchDisplay, this.template.commit.message.displayBranch ); - this.messageHashDisplay = booleanOptionOr( options.messageHashDisplay, this.template.commit.message.displayHash ); - this.messageColor = options.messageColor || options.color; - this.messageFont = options.messageFont || this.template.commit.message.font; - this.dotColor = options.dotColor || options.color; - this.dotSize = options.dotSize || this.template.commit.dot.size; - this.dotStrokeWidth = options.dotStrokeWidth || this.template.commit.dot.strokeWidth; - this.dotStrokeColor = options.dotStrokeColor || this.template.commit.dot.strokeColor || options.color; - this.type = options.type || null; - this.onClick = options.onClick || null; - this.representedObject = options.representedObject || null; - this.parentCommit = options.parentCommit; - this.x = options.x; - this.y = options.y; - this.showLabel = options.showLabel; - this.labelColor = options.labelColor || options.color; - this.labelFont = options.labelFont || this.template.branch.labelFont; - - this.parent.commits.push( this ); - } - - /** - * Render the commit - * - * @this Commit - **/ - Commit.prototype.render = function () { - - // Label - if ( this.showLabel ) { - drawTextBG( this.context, this.x + this.template.commit.spacingX, this.y + this.template.commit.spacingY, this.branch.name, "black", this.labelColor, this.labelFont, this.template.branch.labelRotation ); - } - - // Dot - this.context.beginPath(); - this.context.arc( this.x, this.y, this.dotSize, 0, 2 * Math.PI, false ); - this.context.fillStyle = this.dotColor; - this.context.strokeStyle = this.dotStrokeColor; - this.context.lineWidth = this.dotStrokeWidth; - - if ( typeof (this.dotStrokeWidth) === "number" ) { - this.context.stroke(); - } - - this.context.fill(); - this.context.closePath(); - - // Arrow - if ( this.arrowDisplay && this.parentCommit instanceof Commit ) { - this.arrow(); - } - - this.context.font = this.messageFont; - - // Tag - var tagWidth = this.template.commit.tag.spacingX; - if ( this.tag !== null ) { - this.parent.tagNum++; - var textWidth = this.context.measureText( this.tag ).width; - if ( this.template.branch.labelRotation !== 0 ) { - var textHeight = getFontHeight( this.tagFont ); - drawTextBG( this.context, - this.x - this.dotSize / 2, - ((this.parent.columnMax + 1) * this.template.commit.tag.spacingY) - this.template.commit.tag.spacingY / 2 + (this.parent.tagNum % 2) * textHeight * 1.5, - this.tag, "black", this.tagColor, this.tagFont, 0 ); - } else { - drawTextBG( this.context, - ((this.parent.columnMax + 1) * this.template.commit.tag.spacingX) - this.template.commit.tag.spacingX / 2 + textWidth / 2, - this.y - this.dotSize / 2, - this.tag, "black", this.tagColor, this.tagFont, 0 ); - } - tagWidth = (tagWidth < textWidth) ? textWidth : tagWidth; - } - - var commitOffsetLeft = (this.parent.columnMax + 1) * this.template.branch.spacingX + tagWidth; - - // Detail - if ( this.detail !== null ) { - this.detail.style.left = this.parent.canvas.offsetLeft + commitOffsetLeft + this.x + 30 + "px"; - this.detail.style.top = this.parent.canvas.offsetTop + this.y + 40 + "px"; - this.detail.width = 30; - } - - // Message - if ( this.messageDisplay ) { - var message = this.message; - if ( this.messageHashDisplay ) { - message = this.sha1 + " " + message; - } - if ( this.messageAuthorDisplay ) { - message = message + (this.author ? " - " + this.author : ""); - } - if ( this.messageBranchDisplay ) { - message = (this.branch.name ? "[" + this.branch.name + "] " : "") + message; - } - - this.context.fillStyle = this.messageColor; - this.context.fillText( message, commitOffsetLeft, this.y + this.dotSize / 2 ); - } - }; - - /** - * Render a arrow before commit - * - * @this Commit - **/ - Commit.prototype.arrow = function Arrow () { - // Options - var size = this.template.arrow.size; - var color = this.template.arrow.color || this.branch.color; - var isReversed = this.parent.reverseArrow; - - function rotate ( y, x ) { - var direction = (isReversed) ? -1 : 1; - return Math.atan2( direction * y, direction * x ); - } - - // Angles calculation - var alpha = rotate( this.parentCommit.y - this.y, this.parentCommit.x - this.x ); - - // Merge & Fork case - if ( this.type === "mergeCommit" || this === this.branch.commits[ 0 ] /* First commit */ ) { - var deltaColumn = (this.parentCommit.branch.column - this.branch.column); - var commitSpaceDelta = (this.showLabel ? 2 : 1); - - var isArrowVertical = ( - isReversed - && _isVertical( this.parent ) - && Math.abs( this.y - this.parentCommit.y ) > Math.abs( this.template.commit.spacingY ) - ); - var alphaX = (isArrowVertical) - ? 0 - : this.template.branch.spacingX * deltaColumn + this.template.commit.spacingX * commitSpaceDelta; - - var isArrowHorizontal = ( - isReversed - && _isHorizontal( this.parent ) - && Math.abs( this.x - this.parentCommit.x ) > Math.abs( this.template.commit.spacingX ) - ); - var alphaY = (isArrowHorizontal) - ? 0 - : this.template.branch.spacingY * deltaColumn + this.template.commit.spacingY * commitSpaceDelta; - - alpha = rotate( alphaY, alphaX ); - color = this.parentCommit.branch.color; - } - - var delta = Math.PI / 7; // Delta between left & right (radian) - - var arrowX = (isReversed) ? this.parentCommit.x : this.x; - var arrowY = (isReversed) ? this.parentCommit.y : this.y; - - // Top - var h = this.template.commit.dot.size + this.template.arrow.offset; - var x1 = h * Math.cos( alpha ) + arrowX; - var y1 = h * Math.sin( alpha ) + arrowY; - - // Bottom left - var x2 = (h + size) * Math.cos( alpha - delta ) + arrowX; - var y2 = (h + size) * Math.sin( alpha - delta ) + arrowY; - - // Bottom center - var x3 = (h + size / 2) * Math.cos( alpha ) + arrowX; - var y3 = (h + size / 2) * Math.sin( alpha ) + arrowY; - - // Bottom right - var x4 = (h + size) * Math.cos( alpha + delta ) + arrowX; - var y4 = (h + size) * Math.sin( alpha + delta ) + arrowY; - - this.context.beginPath(); - this.context.fillStyle = color; - this.context.moveTo( x1, y1 ); // Top - this.context.lineTo( x2, y2 ); // Bottom left - this.context.quadraticCurveTo( x3, y3, x4, y4 ); // Bottom center - this.context.lineTo( x4, y4 ); // Bottom right - this.context.fill(); - }; - - // -------------------------------------------------------------------- - // ----------------------- Template ------------------------ - // -------------------------------------------------------------------- - - /** - * Template - * - * @constructor - * - * @param {Object} options - Template options - * @param {Array} [options.colors] - Colors scheme: One color for each column - * @param {String} [options.arrow.color] - Arrow color - * @param {Number} [options.arrow.size] - Arrow size - * @param {Number} [options.arrow.offser] - Arrow offset - * @param {String} [options.branch.color] - Branch color - * @param {Number} [options.branch.linewidth] - Branch line width - * @param {String} [options.branch.mergeStyle = ("bezier"|"straight")] - Branch merge style - * @param {Number} [options.branch.spacingX] - Space between branches - * @param {Number} [options.branch.spacingY] - Space between branches - * @param {Number} [options.commit.spacingX] - Space between commits - * @param {Number} [options.commit.spacingY] - Space between commits - * @param {Number} [options.commit.widthExtension = 0] - Additional width to be added to the calculated width - * @param {String} [options.commit.color] - Master commit color (dot & message) - * @param {String} [options.commit.dot.color] - Commit dot color - * @param {Number} [options.commit.dot.size] - Commit dot size - * @param {Number} [options.commit.dot.strokewidth] - Commit dot stroke width - * @param {Number} [options.commit.dot.strokeColor] - Commit dot stroke color - * @param {String} [options.commit.message.color] - Commit message color - * @param {Boolean} [options.commit.message.display] - Commit display policy - * @param {Boolean} [options.commit.message.displayAuthor] - Commit message author policy - * @param {Boolean} [options.commit.message.displayBranch] - Commit message branch policy - * @param {Boolean} [options.commit.message.displayHash] - Commit message hash policy - * @param {String} [options.commit.message.font = "normal 12pt Calibri"] - Commit message font - * @param {commitCallback} [options.commit.tooltipHTMLFormatter] - Formatter for the tooltip contents. - * - * @this Template - **/ - function Template ( options ) { - // Options - options = (typeof options === "object") ? options : {}; - options.branch = options.branch || {}; - options.arrow = options.arrow || {}; - options.commit = options.commit || {}; - options.commit.dot = options.commit.dot || {}; - options.commit.tag = options.commit.tag || {}; - options.commit.message = options.commit.message || {}; - - // One color per column - this.colors = options.colors || [ "#6963FF", "#47E8D4", "#6BDB52", "#E84BA5", "#FFA657" ]; - - // Branch style - this.branch = {}; - this.branch.color = options.branch.color || null; // Only one color - this.branch.lineWidth = options.branch.lineWidth || 2; - this.branch.lineDash = options.branch.lineDash || []; - this.branch.showLabel = options.branch.showLabel || false; - this.branch.labelColor = options.branch.labelColor || null; - this.branch.labelFont = options.branch.labelFont || "normal 8pt Calibri"; - this.branch.labelRotation = options.branch.labelRotation || 0; - - // Merge style = "bezier" | "straight" - this.branch.mergeStyle = options.branch.mergeStyle || "bezier"; - - // Space between branches - this.branch.spacingX = (typeof options.branch.spacingX === "number") ? options.branch.spacingX : 20; - this.branch.spacingY = options.branch.spacingY || 0; - - // Arrow style - this.arrow = {}; - this.arrow.size = options.arrow.size || null; - this.arrow.color = options.arrow.color || null; - this.arrow.active = typeof (this.arrow.size) === "number"; - this.arrow.offset = options.arrow.offset || 2; - - // Commit style - this.commit = {}; - this.commit.spacingX = options.commit.spacingX || 0; - this.commit.spacingY = (typeof options.commit.spacingY === "number") ? options.commit.spacingY : 25; - this.commit.widthExtension = (typeof options.commit.widthExtension === "number") ? options.commit.widthExtension : 0; - this.commit.tooltipHTMLFormatter = options.commit.tooltipHTMLFormatter || null; - - // Only one color, if null message takes branch color (full commit) - this.commit.color = options.commit.color || null; - - this.commit.dot = {}; - - // Only one color, if null message takes branch color (only dot) - this.commit.dot.color = options.commit.dot.color || null; - this.commit.dot.size = options.commit.dot.size || 3; - this.commit.dot.strokeWidth = options.commit.dot.strokeWidth || null; - this.commit.dot.strokeColor = options.commit.dot.strokeColor || null; - - this.commit.tag = {}; - this.commit.tag.color = options.commit.tag.color || this.commit.dot.color; - this.commit.tag.font = options.commit.tag.font || options.commit.message.font || "normal 10pt Calibri"; - this.commit.tag.spacingX = this.branch.spacingX; - this.commit.tag.spacingY = this.commit.spacingY; - - this.commit.message = {}; - this.commit.message.display = booleanOptionOr( options.commit.message.display, true ); - this.commit.message.displayAuthor = booleanOptionOr( options.commit.message.displayAuthor, true ); - this.commit.message.displayBranch = booleanOptionOr( options.commit.message.displayBranch, true ); - this.commit.message.displayHash = booleanOptionOr( options.commit.message.displayHash, true ); - - // Only one color, if null message takes commit color (only message) - this.commit.message.color = options.commit.message.color || null; - this.commit.message.font = options.commit.message.font || "normal 12pt Calibri"; - } - - /** - * Get a default template from library - * - * @param {String} name - Template name - * - * @return {Template} [template] - Template if exist - **/ - Template.prototype.get = function ( name ) { - var template = {}; - - switch ( name ) { - case "blackarrow": - template = { - branch: { - color: "#000000", - lineWidth: 4, - spacingX: 50, - mergeStyle: "straight" - }, - commit: { - spacingY: -60, - dot: { - size: 12, - strokeColor: "#000000", - strokeWidth: 7 - }, - message: { - color: "black" - } - }, - arrow: { - size: 16, - offset: 2.5 - } - }; - break; - - case "metro": - /* falls through */ - default: - template = { - colors: [ "#979797", "#008fb5", "#f1c109" ], - branch: { - lineWidth: 10, - spacingX: 50 - }, - commit: { - spacingY: -80, - dot: { - size: 14 - }, - message: { - font: "normal 14pt Arial" - } - } - }; - break; - } - - return new Template( template ); - }; - - // -------------------------------------------------------------------- - // ----------------------- Utilities ----------------------- - // -------------------------------------------------------------------- - - var getFontHeight = function ( font ) { - var body = document.getElementsByTagName( "body" )[ 0 ]; - var dummy = document.createElement( "div" ); - var dummyText = document.createTextNode( "Mg" ); - dummy.appendChild( dummyText ); - dummy.setAttribute( "style", "font: " + font + ";" ); - body.appendChild( dummy ); - var result = dummy.offsetHeight; - body.removeChild( dummy ); - return result; - }; - - function booleanOptionOr ( booleanOption, defaultOption ) { - return (typeof booleanOption === "boolean") ? booleanOption : defaultOption; - } - - function drawTextBG ( context, x, y, text, fgcolor, bgcolor, font, angle ) { - context.save(); - context.translate( x, y ); - context.rotate( angle * (Math.PI / 180) ); - context.textAlign = "center"; - - context.font = font; - var width = context.measureText( text ).width; - var height = getFontHeight( font ); - - context.beginPath(); - context.rect( -(width / 2) - 4, -(height / 2) + 2, width + 8, height + 2 ); - context.fillStyle = bgcolor; - context.fill(); - context.lineWidth = 2; - context.strokeStyle = "black"; - context.stroke(); - - context.fillStyle = fgcolor; - context.fillText( text, 0, height / 2 ); - context.restore(); - } - - // Expose GitGraph object - window.GitGraph = GitGraph; - window.GitGraph.Branch = Branch; - window.GitGraph.Commit = Commit; - window.GitGraph.Template = Template; -})(); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).GitgraphJS={})}(this,function(t){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function s(t,e){return t(e={exports:{}},e.exports),e.exports}var i=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.VerticalReverse="vertical-reverse",t.Horizontal="horizontal",t.HorizontalReverse="horizontal-reverse"}(e.Orientation||(e.Orientation={}))});r(i);i.Orientation;var n=s(function(t,e){function r(t,e){return Object.assign({},e.reduce((e,r)=>Object.assign({},e,{[r]:t[r]}),{}))}function s(t){return void 0===t}Object.defineProperty(e,"__esModule",{value:!0}),e.booleanOptionOr=function(t,e){return"boolean"==typeof t?t:e},e.numberOptionOr=function(t,e){return"number"==typeof t?t:e},e.pick=r,e.debug=function(t,e){console.log(JSON.stringify(t.map(t=>r(t,e)),null,2))},e.isUndefined=s,e.withoutUndefinedKeys=function(t={}){return Object.keys(t).reduce((e,r)=>s(t[r])?e:Object.assign({},e,{[r]:t[r]}),{})},e.arrowSvgPath=function(t,e,r){const s=r.style.dot.size,n=t.template.arrow.size,o=s+t.template.arrow.offset,a=Math.PI/7,h=function(t,e,r){const s=e.x-r.x,n=e.y-r.y,o=t.template.commit.spacing;let a,h;switch(t.orientation){case i.Orientation.Horizontal:a=n,h=-o;break;case i.Orientation.HorizontalReverse:a=n,h=o;break;case i.Orientation.VerticalReverse:a=-o,h=s;break;default:a=o,h=s}return t.isVertical?Math.abs(n)>o&&(h=0):Math.abs(s)>o&&(a=0),t.reverseArrow&&(a*=-1,h*=-1),Math.atan2(a,h)}(t,e,r),c=o*Math.cos(h),l=o*Math.sin(h),m=(o+n)*Math.cos(h-a),u=(o+n)*Math.sin(h-a),p=(o+n/2)*Math.cos(h),d=(o+n/2)*Math.sin(h),g=(o+n)*Math.cos(h+a),f=(o+n)*Math.sin(h+a);return`M${c},${l} L${m},${u} Q${p},${d} ${g},${f} L${g},${f}`}});r(n);n.booleanOptionOr,n.numberOptionOr,n.pick,n.debug,n.isUndefined,n.withoutUndefinedKeys,n.arrowSvgPath;var o=s(function(t,e){var r;Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.Bezier="bezier",t.Straight="straight"}(r||(r={})),e.MergeStyle=r,e.DEFAULT_FONT="normal 12pt Calibri";class s{constructor(t){t.branch=t.branch||{},t.branch.label=t.branch.label||{},t.arrow=t.arrow||{},t.commit=t.commit||{},t.commit.dot=t.commit.dot||{},t.commit.message=t.commit.message||{},this.colors=t.colors||["#000000"],this.branch={color:t.branch.color,lineWidth:t.branch.lineWidth||2,mergeStyle:t.branch.mergeStyle||r.Bezier,spacing:n.numberOptionOr(t.branch.spacing,20),label:{display:n.booleanOptionOr(t.branch.label.display,!0),color:t.branch.label.color||t.commit.color,strokeColor:t.branch.label.strokeColor||t.commit.color,bgColor:t.branch.label.bgColor||"white",font:t.branch.label.font||t.commit.message.font||e.DEFAULT_FONT,borderRadius:n.numberOptionOr(t.branch.label.borderRadius,10)}},this.arrow={size:t.arrow.size||null,color:t.arrow.color||null,offset:t.arrow.offset||2},this.commit={color:t.commit.color,spacing:n.numberOptionOr(t.commit.spacing,25),hasTooltipInCompactMode:n.booleanOptionOr(t.commit.hasTooltipInCompactMode,!0),dot:{color:t.commit.dot.color||t.commit.color,size:t.commit.dot.size||3,strokeWidth:n.numberOptionOr(t.commit.dot.strokeWidth,0),strokeColor:t.commit.dot.strokeColor,font:t.commit.dot.font||t.commit.message.font||"normal 10pt Calibri"},message:{display:n.booleanOptionOr(t.commit.message.display,!0),displayAuthor:n.booleanOptionOr(t.commit.message.displayAuthor,!0),displayHash:n.booleanOptionOr(t.commit.message.displayHash,!0),color:t.commit.message.color||t.commit.color,font:t.commit.message.font||e.DEFAULT_FONT}},this.tag=t.tag||{}}}e.Template=s;const i=new s({colors:["#6963FF","#47E8D4","#6BDB52","#E84BA5","#FFA657"],branch:{color:"#000000",lineWidth:4,spacing:50,mergeStyle:r.Straight},commit:{spacing:60,dot:{size:16,strokeColor:"#000000",strokeWidth:4},message:{color:"black"}},arrow:{size:16,offset:-1.5}});e.blackArrowTemplate=i;const o=new s({colors:["#979797","#008fb5","#f1c109"],branch:{lineWidth:10,spacing:50},commit:{spacing:80,dot:{size:14},message:{font:"normal 14pt Arial"}}});var a;function h(t){return t?"string"==typeof t?{[a.BlackArrow]:i,[a.Metro]:o}[t]:t:o}e.metroTemplate=o,function(t){t.Metro="metro",t.BlackArrow="blackarrow"}(a||(a={})),e.TemplateName=a,e.templateExtend=function(t,e){const r=h(t);return e.branch||(e.branch={}),e.commit||(e.commit={}),{colors:e.colors||r.colors,arrow:Object.assign({},r.arrow,e.arrow),branch:Object.assign({},r.branch,e.branch,{label:Object.assign({},r.branch.label,e.branch.label)}),commit:Object.assign({},r.commit,e.commit,{dot:Object.assign({},r.commit.dot,e.commit.dot),message:Object.assign({},r.commit.message,e.commit.message)}),tag:Object.assign({},r.tag,e.tag)}},e.getTemplate=h});r(o);o.MergeStyle,o.DEFAULT_FONT,o.Template,o.blackArrowTemplate,o.metroTemplate,o.TemplateName,o.templateExtend,o.getTemplate;var a=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.Tag=class{constructor(t,e,r,s){this.name=t,this.tagStyle=e,this.commitStyle=s,this.render=r}get style(){return{strokeColor:this.tagStyle.strokeColor||this.commitStyle.color,bgColor:this.tagStyle.bgColor||this.commitStyle.color,color:this.tagStyle.color||"white",font:this.tagStyle.font||this.commitStyle.message.font||o.DEFAULT_FONT,borderRadius:n.numberOptionOr(this.tagStyle.borderRadius,10),pointerWidth:n.numberOptionOr(this.tagStyle.pointerWidth,12)}}}});r(a);a.Tag;var h=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});const r=()=>(Math.random().toString(16).substring(3)+Math.random().toString(16).substring(3)+Math.random().toString(16).substring(3)+Math.random().toString(16).substring(3)).substring(0,40);class s{constructor(t){let e,s;this.refs=[],this.x=0,this.y=0;try{[,e,s]=t.author.match(/(.*) <(.*)>/)}catch(r){[e,s]=[t.author,""]}this.author={name:e,email:s,timestamp:Date.now()},this.committer={name:e,email:s,timestamp:Date.now()},this.subject=t.subject,this.body=t.body||"",this.hash=t.hash||r(),this.hashAbbrev=this.hash.substring(0,7),this.parents=t.parents?t.parents:[],this.parentsAbbrev=this.parents.map(t=>t.substring(0,7)),this.style=Object.assign({},t.style,{message:Object.assign({},t.style.message),dot:Object.assign({},t.style.dot)}),this.dotText=t.dotText,this.onClick=(()=>t.onClick?t.onClick(this):void 0),this.onMessageClick=(()=>t.onMessageClick?t.onMessageClick(this):void 0),this.onMouseOver=(()=>t.onMouseOver?t.onMouseOver(this):void 0),this.onMouseOut=(()=>t.onMouseOut?t.onMouseOut(this):void 0),this.renderDot=t.renderDot,this.renderMessage=t.renderMessage,this.renderTooltip=t.renderTooltip}get message(){let t="";return this.style.message.displayHash&&(t+=`${this.hashAbbrev} `),t+=this.subject,this.style.message.displayAuthor&&(t+=` - ${this.author.name} <${this.author.email}>`),t}get branchToDisplay(){return this.branches?this.branches[0]:""}setRefs(t){return this.refs=t.getNames(this.hash),this}setTags(t,e,r){return this.tags=t.getNames(this.hash).map(t=>new a.Tag(t,e(t),r(t),this.style)),this}setBranches(t){return this.branches=t,this}setPosition({x:t,y:e}){return this.x=t,this.y=e,this}withDefaultColor(t){const e=Object.assign({},this.style,{dot:Object.assign({},this.style.dot),message:Object.assign({},this.style.message)});e.color||(e.color=t),e.dot.color||(e.dot.color=t),e.message.color||(e.message.color=t);const r=this.cloneCommit();return r.style=e,r}cloneCommit(){const t=new s({author:`${this.author.name} <${this.author.email}>`,subject:this.subject,style:this.style,body:this.body,hash:this.hash,parents:this.parents,dotText:this.dotText,onClick:this.onClick,onMessageClick:this.onMessageClick,onMouseOver:this.onMouseOver,onMouseOut:this.onMouseOut,renderDot:this.renderDot,renderMessage:this.renderMessage,renderTooltip:this.renderTooltip});return t.refs=this.refs,t.branches=this.branches,t.tags=this.tags,t.x=this.x,t.y=this.y,t}}e.Commit=s});r(h);h.Commit;var c=s(function(t,r){var s=e&&e.__rest||function(t,e){var r={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&e.indexOf(s)<0&&(r[s]=t[s]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(s=Object.getOwnPropertySymbols(t);ithis._graph.refs.set(t,o.hash))}else this._graph.refs.set(this._branch.name,o.hash);this._graph.commits.push(o),this.checkout(),this._graph.refs.set("HEAD",o.hash),i&&this.tag(i)}_areCommitsConnected(t,e){const r=this._graph.commits.find(({hash:t})=>e===t);return!!r&&(!(0===r.parents.length)&&(!!r.parents.includes(t)||r.parents.some(e=>this._areCommitsConnected(t,e))))}_fastForwardTo(t){this._graph.refs.set(this._branch.name,t)}_getCommitStyle(t={}){return Object.assign({},n.withoutUndefinedKeys(this._graph.template.commit),n.withoutUndefinedKeys(this._branch.commitDefaultOptions.style),t,{message:Object.assign({},n.withoutUndefinedKeys(this._graph.template.commit.message),n.withoutUndefinedKeys(this._branch.commitDefaultOptions.style.message),t.message,n.withoutUndefinedKeys({display:this._graph.shouldDisplayCommitMessage&&void 0})),dot:Object.assign({},n.withoutUndefinedKeys(this._graph.template.commit.dot),n.withoutUndefinedKeys(this._branch.commitDefaultOptions.style.dot),t.dot)})}}r.BranchUserApi=i});r(c);c.BranchUserApi;var l=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});const r="";e.DELETED_BRANCH_NAME=r;class s{constructor(t){this.gitgraph=t.gitgraph,this.name=t.name,this.style=t.style,this.parentCommitHash=t.parentCommitHash,this.commitDefaultOptions=t.commitDefaultOptions||{style:{}},this.onGraphUpdate=t.onGraphUpdate,this.renderLabel=t.renderLabel}getUserApi(){return new c.BranchUserApi(this,this.gitgraph,this.onGraphUpdate)}isDeleted(){return this.name===r}}e.Branch=s,e.createDeletedBranch=function(t,e,i){return new s({name:r,gitgraph:t,style:e,onGraphUpdate:i})}});r(l);l.DELETED_BRANCH_NAME,l.Branch,l.createDeletedBranch;var m=s(function(t,e){var r;Object.defineProperty(e,"__esModule",{value:!0}),function(t){t.Compact="compact"}(r||(r={})),e.Mode=r});r(m);m.Mode;var u=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.RegularGraphRows=class{constructor(t){this.rows=new Map,this.maxRowCache=void 0,this.computeRowsFromCommits(t)}getRowOf(t){return this.rows.get(t)||0}getMaxRow(){return void 0===this.maxRowCache&&(this.maxRowCache=function(t){const e=new Set;return t.forEach(t=>e.add(t)),Array.from(e)}(Array.from(this.rows.values())).length-1),this.maxRowCache}computeRowsFromCommits(t){t.forEach((t,e)=>{this.rows.set(t.hash,e)}),this.maxRowCache=void 0}}});r(u);u.RegularGraphRows;var p=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.CompactGraphRows=class extends u.RegularGraphRows{computeRowsFromCommits(t){t.forEach((e,r)=>{let s=r;if(0!==r){const i=this.getRowOf(e.parents[0]),n=t[r-1];s=Math.max(i+1,this.getRowOf(n.hash)),e.parents.length>1&&ithis.branches.add(t.branchToDisplay)),r&&(this.branches=new Set(Array.from(this.branches).sort(r)))}get(t){return Array.from(this.branches).findIndex(e=>e===t)}getColorOf(t){return this.colors[this.get(t)%this.colors.length]}}});r(g);g.BranchesOrder;var f=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.Refs=class{constructor(){this.commitPerName=new Map,this.namesPerCommit=new Map}set(t,e){const r=this.commitPerName.get(t);return r&&this.removeNameFrom(r,t),this.addNameTo(e,t),this.addCommitTo(t,e),this}getCommit(t){return this.commitPerName.get(t)}getNames(t){return this.namesPerCommit.get(t)||[]}getAllNames(){return Array.from(this.commitPerName.keys())}hasCommit(t){return this.namesPerCommit.has(t)}hasName(t){return this.commitPerName.has(t)}removeNameFrom(t,e){const r=this.namesPerCommit.get(t)||[];this.namesPerCommit.set(t,r.filter(t=>t!==e))}addNameTo(t,e){const r=this.namesPerCommit.get(t)||[];this.namesPerCommit.set(t,[...r,e])}addCommitTo(t,e){this.commitPerName.set(t,e)}}});r(f);f.Refs;var b=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.BranchesPathsCalculator=class{constructor(t,e,r,s,i,n){this.branchesPaths=new Map,this.commits=t,this.branches=e,this.commitSpacing=r,this.isGraphVertical=s,this.isGraphReverse=i,this.createDeletedBranch=n}execute(){return this.fromCommits(),this.withMergeCommits(),this.smoothBranchesPaths()}fromCommits(){this.commits.forEach(t=>{let e=this.branches.get(t.branchToDisplay);e||(e=this.getDeletedBranchInPath()||this.createDeletedBranch());const r=[],s=this.branchesPaths.get(e),i=this.commits.find(({hash:e})=>e===t.parents[0]);s?r.push(...s):i&&r.push({x:i.x,y:i.y}),r.push({x:t.x,y:t.y}),this.branchesPaths.set(e,r)})}withMergeCommits(){this.commits.filter(({parents:t})=>t.length>1).forEach(t=>{const e=this.commits.find(({hash:e})=>e===t.parents[1]);if(!e)return;const r=e.branches?e.branches[0]:"";let s=this.branches.get(r);if(!s&&!(s=this.getDeletedBranchInPath()))return;const i=[...this.branchesPaths.get(s)||[]];this.branchesPaths.set(s,[...i,{x:t.x,y:t.y,mergeCommit:!0}])})}getDeletedBranchInPath(){return Array.from(this.branchesPaths.keys()).find(t=>t.isDeleted())}smoothBranchesPaths(){const t=new Map;return this.branchesPaths.forEach((e,r)=>{if(e.length<=1)return void t.set(r,[e]);e=this.isGraphVertical?e.sort((t,e)=>t.y>e.y?-1:1):e.sort((t,e)=>t.x>e.x?1:-1),this.isGraphReverse&&(e=e.reverse());const s=e.reduce((t,r,s)=>{if(r.mergeCommit){t[t.length-1].push(n.pick(r,["x","y"]));let i=s-1,o=e[i];for(;i>=0&&o.mergeCommit;)o=e[--i];i>=0&&t.push([o])}else t[t.length-1].push(r);return t},[[]]);this.isGraphReverse&&s.forEach(t=>t.reverse()),this.isGraphVertical?s.forEach(e=>{if(e.length<=1)return;const s=e[0],i=e[e.length-1],n=e[1].x,o=Math.round(Math.abs(s.y-i.y)/this.commitSpacing)-1,a=o>0?new Array(o).fill(0).map((t,r)=>({x:n,y:e[0].y-this.commitSpacing*(r+1)})):[],h=t.get(r)||[];t.set(r,[...h,[s,...a,i]])}):s.forEach(e=>{if(e.length<=1)return;const s=e[0],i=e[e.length-1],n=e[1].y,o=Math.round(Math.abs(s.x-i.x)/this.commitSpacing)-1,a=o>0?new Array(o).fill(0).map((t,r)=>({y:n,x:e[0].x+this.commitSpacing*(r+1)})):[],h=t.get(r)||[];t.set(r,[...h,[s,...a,i]])})}),t}},e.toSvgPath=function(t,e,r){return t.map(t=>"M"+t.map(({x:t,y:s},i,n)=>{if(e&&n.length>1&&(1===i||i===n.length-1)){const e=n[i-1];if(r){const r=(e.y+s)/2;return`C ${e.x} ${r} ${t} ${r} ${t} ${s}`}{const r=(e.x+t)/2;return`C ${r} ${e.y} ${r} ${s} ${t} ${s}`}}return`L ${t} ${s}`}).join(" ").slice(1)).join(" ")}});r(b);b.BranchesPathsCalculator,b.toSvgPath;var y=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.GitgraphUserApi=class{constructor(t,e){this._graph=t,this._onGraphUpdate=e}clear(){return this._graph.refs=new f.Refs,this._graph.tags=new f.Refs,this._graph.commits=[],this._graph.branches=new Map,this._graph.currentBranch=this._graph.createBranch("master"),this._onGraphUpdate(),this}commit(t){return this._graph.currentBranch.getUserApi().commit(t),this}branch(t){return this._graph.createBranch(t).getUserApi()}tag(...t){let e,r,s,i,n;if("string"==typeof t[0]?(e=t[0],r=t[1]):(e=t[0].name,r=t[0].ref,s=t[0].style,i=t[0].render),!r){const t=this._graph.refs.getCommit("HEAD");if(!t)return this;r=t}if(this._graph.refs.hasCommit(r)&&(n=r),this._graph.refs.hasName(r)&&(n=this._graph.refs.getCommit(r)),!n)throw new Error(`The ref "${r}" does not exist`);return this._graph.tags.set(e,n),this._graph.tagStyles[e]=s,this._graph.tagRenders[e]=i,this._onGraphUpdate(),this}import(t){const e=new Error("Only `git2json` format is supported for imported data.");if(!Array.isArray(t))throw e;if(!t.every(t=>"object"==typeof t&&"object"==typeof t.author&&Array.isArray(t.refs)))throw e;const r=t.map(t=>Object.assign({},t,{style:Object.assign({},this._graph.template.commit,{message:Object.assign({},this._graph.template.commit.message,{display:this._graph.shouldDisplayCommitMessage})}),author:`${t.author.name} <${t.author.email}>`})).reverse();this.clear(),this._graph.commits=r.map(t=>new h.Commit(t)),r.forEach(({refs:t,hash:e})=>{t&&e&&(t.map(t=>t.split("tag: ")).map(([t,e])=>e).filter(t=>"string"==typeof t).forEach(t=>this._graph.tags.set(t,e)),t.filter(t=>!t.startsWith("tag: ")).forEach(t=>this._graph.refs.set(t,e)))});const s=this._getBranches();return this._graph.commits.map(t=>this._withBranches(s,t)).reduce((t,e)=>e.branches?(e.branches.forEach(e=>t.add(e)),t):t,new Set).forEach(t=>this.branch(t)),this._onGraphUpdate(),this}_withBranches(t,e){let r=Array.from((t.get(e.hash)||new Set).values());return 0===r.length&&(r=[l.DELETED_BRANCH_NAME]),e.setBranches(r)}_getBranches(){const t=new Map,e=[];return this._graph.refs.getAllNames().filter(t=>"HEAD"!==t).forEach(r=>{const s=this._graph.refs.getCommit(r);for(s&&e.push(s);e.length>0;){const s=e.pop(),i=this._graph.commits.find(({hash:t})=>t===s),n=t.get(s)||new Set;n.add(r),t.set(s,n),i.parents.length>0&&e.push(i.parents[0])}}),t}}});r(y);y.GitgraphUserApi;var v=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0});e.GitgraphCore=class{constructor(t={}){this.refs=new f.Refs,this.tags=new f.Refs,this.tagStyles={},this.tagRenders={},this.commits=[],this.branches=new Map,this.listeners=[],this.nextTimeoutId=null,this.template=o.getTemplate(t.template),this.currentBranch=this.createBranch("master"),this.orientation=t.orientation,this.reverseArrow=n.booleanOptionOr(t.reverseArrow,!1),this.initCommitOffsetX=n.numberOptionOr(t.initCommitOffsetX,0),this.initCommitOffsetY=n.numberOptionOr(t.initCommitOffsetY,0),this.mode=t.mode,this.author=t.author||"Sergio Flores ",this.commitMessage=t.commitMessage||"He doesn't like George Michael! Boooo!",this.generateCommitHash="function"==typeof t.generateCommitHash?t.generateCommitHash:()=>void 0,this.branchesOrderFunction="function"==typeof t.compareBranchesOrder?t.compareBranchesOrder:void 0,this.branchLabelOnEveryCommit=n.booleanOptionOr(t.branchLabelOnEveryCommit,!1)}get isHorizontal(){return this.orientation===i.Orientation.Horizontal||this.orientation===i.Orientation.HorizontalReverse}get isVertical(){return!this.isHorizontal}get isReverse(){return this.orientation===i.Orientation.HorizontalReverse||this.orientation===i.Orientation.VerticalReverse}get shouldDisplayCommitMessage(){return!this.isHorizontal&&this.mode!==m.Mode.Compact}getUserApi(){return new y.GitgraphUserApi(this,()=>this.next())}subscribe(t){this.listeners.push(t);let e=!0;return()=>{if(!e)return;e=!1;const r=this.listeners.indexOf(t);this.listeners.splice(r,1)}}getRenderedData(){const t=this.computeRenderedCommits(),e=this.computeRenderedBranchesPaths(t),r=this.computeCommitMessagesX(e);return this.computeBranchesColor(t,e),{commits:t,branchesPaths:e,commitMessagesX:r}}createBranch(t){let e={gitgraph:this,name:"",parentCommitHash:this.refs.getCommit("HEAD"),style:this.template.branch,onGraphUpdate:()=>this.next()};if("string"==typeof t)e.name=t,e.parentCommitHash=this.refs.getCommit("HEAD");else{const r=t.from?t.from.name:"HEAD",s=this.refs.getCommit(r)||(this.refs.hasCommit(t.from)?t.from:void 0);t.style=t.style||{},e=Object.assign({},e,t,{parentCommitHash:s,style:Object.assign({},e.style,t.style,{label:Object.assign({},e.style.label,t.style.label)})})}const r=new l.Branch(e);return this.branches.set(r.name,r),r}computeRenderedCommits(){const t=this.getBranches(),e=this.commits.map(e=>this.withBranches(t,e)),r=d.createGraphRows(this.mode,this.commits),s=new g.BranchesOrder(e,this.template.colors,this.branchesOrderFunction);return e.map(t=>t.setRefs(this.refs)).map(t=>this.withPosition(r,s,t)).map(t=>t.withDefaultColor(this.getBranchDefaultColor(s,t.branchToDisplay))).map(t=>t.setTags(this.tags,t=>Object.assign({},this.tagStyles[t],this.template.tag),t=>this.tagRenders[t]))}computeRenderedBranchesPaths(t){return new b.BranchesPathsCalculator(t,this.branches,this.template.commit.spacing,this.isVertical,this.isReverse,()=>l.createDeletedBranch(this,this.template.branch,()=>this.next())).execute()}computeBranchesColor(t,e){const r=new g.BranchesOrder(t,this.template.colors,this.branchesOrderFunction);Array.from(e).forEach(([t])=>{t.computedColor=t.style.color||this.getBranchDefaultColor(r,t.name)})}computeCommitMessagesX(t){return Array.from(t).length*this.template.branch.spacing}withBranches(t,e){let r=Array.from((t.get(e.hash)||new Set).values());return 0===r.length&&(r=[l.DELETED_BRANCH_NAME]),e.setBranches(r)}getBranches(){const t=new Map,e=[];return this.refs.getAllNames().filter(t=>"HEAD"!==t).forEach(r=>{const s=this.refs.getCommit(r);for(s&&e.push(s);e.length>0;){const s=e.pop(),i=this.commits.find(({hash:t})=>t===s),n=t.get(s)||new Set;n.add(r),t.set(s,n),i.parents.length>0&&e.push(i.parents[0])}}),t}withPosition(t,e,r){const s=t.getRowOf(r.hash),n=t.getMaxRow(),o=e.get(r.branchToDisplay);switch(this.orientation){default:return r.setPosition({x:this.initCommitOffsetX+this.template.branch.spacing*o,y:this.initCommitOffsetY+this.template.commit.spacing*(n-s)});case i.Orientation.VerticalReverse:return r.setPosition({x:this.initCommitOffsetX+this.template.branch.spacing*o,y:this.initCommitOffsetY+this.template.commit.spacing*s});case i.Orientation.Horizontal:return r.setPosition({x:this.initCommitOffsetX+this.template.commit.spacing*s,y:this.initCommitOffsetY+this.template.branch.spacing*o});case i.Orientation.HorizontalReverse:return r.setPosition({x:this.initCommitOffsetX+this.template.commit.spacing*(n-s),y:this.initCommitOffsetY+this.template.branch.spacing*o})}}getBranchDefaultColor(t,e){return t.getColorOf(e)}next(){this.nextTimeoutId&&window.clearTimeout(this.nextTimeoutId),this.nextTimeoutId=window.setTimeout(()=>{this.listeners.forEach(t=>t(this.getRenderedData()))},0)}}});r(v);v.GitgraphCore;var O=s(function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.GitgraphCore=v.GitgraphCore,e.Mode=m.Mode,e.GitgraphUserApi=y.GitgraphUserApi,e.BranchUserApi=c.BranchUserApi,e.Branch=l.Branch,e.Commit=h.Commit,e.Tag=a.Tag,e.Refs=f.Refs,e.MergeStyle=o.MergeStyle,e.TemplateName=o.TemplateName,e.templateExtend=o.templateExtend,e.Orientation=i.Orientation,e.toSvgPath=b.toSvgPath,e.arrowSvgPath=n.arrowSvgPath});r(O);var w=O.GitgraphCore,C=O.Mode,A=(O.GitgraphUserApi,O.BranchUserApi,O.Branch,O.Commit,O.Tag,O.Refs,O.MergeStyle),_=O.TemplateName,M=O.templateExtend,x=O.Orientation,S=O.toSvgPath,E=O.arrowSvgPath,B="http://www.w3.org/2000/svg";function R(t){var e=document.createElementNS(B,"g");return t.children.forEach(function(t){return t&&e.appendChild(t)}),t.translate&&e.setAttribute("transform","translate("+t.translate.x+", "+t.translate.y+")"),t.fill&&e.setAttribute("fill",t.fill),t.stroke&&e.setAttribute("stroke",t.stroke),t.strokeWidth&&e.setAttribute("stroke-width",t.strokeWidth.toString()),t.onClick&&e.addEventListener("click",t.onClick),t.onMouseOver&&e.addEventListener("mouseover",t.onMouseOver),t.onMouseOut&&e.addEventListener("mouseout",t.onMouseOut),e}function k(t){var e=document.createElementNS(B,"text");return e.setAttribute("alignment-baseline","central"),e.setAttribute("dominant-baseline","central"),e.textContent=t.content,t.fill&&e.setAttribute("fill",t.fill),t.font&&e.setAttribute("style","font: "+t.font),t.anchor&&e.setAttribute("text-anchor",t.anchor),t.translate&&(e.setAttribute("x",t.translate.x.toString()),e.setAttribute("y",t.translate.y.toString())),t.onClick&&e.addEventListener("click",t.onClick),e}function j(t){var e=document.createElementNS(B,"path");return e.setAttribute("d",t.d),t.fill&&e.setAttribute("fill",t.fill),t.stroke&&e.setAttribute("stroke",t.stroke),t.strokeWidth&&e.setAttribute("stroke-width",t.strokeWidth.toString()),t.translate&&e.setAttribute("transform","translate("+t.translate.x+", "+t.translate.y+")"),e}function T(t){var e=document.createElementNS(B,"use");return e.setAttribute("href","#"+t),e.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href","#"+t),e}var P=10,D=5;function N(t,e){var r=function(t){var e=document.createElementNS(B,"rect");return e.setAttribute("width",t.width.toString()),e.setAttribute("height",t.height.toString()),t.borderRadius&&e.setAttribute("rx",t.borderRadius.toString()),t.fill&&e.setAttribute("fill",t.fill||"transparent"),t.stroke&&e.setAttribute("stroke",t.stroke),e}({width:0,height:0,borderRadius:t.style.label.borderRadius,stroke:t.style.label.strokeColor||e.style.color,fill:t.style.label.bgColor}),s=k({content:t.name,translate:{x:P,y:0},font:t.style.label.font,fill:t.style.label.color||e.style.color}),i=R({children:[r]});return new MutationObserver(function(){var t=s.getBBox(),e=t.height,i=t.width+2*P,n=e+2*D;r.setAttribute("width",i.toString()),r.setAttribute("height",n.toString()),s.setAttribute("y",(n/2).toString())}).observe(i,{attributes:!1,subtree:!1,childList:!0}),i.appendChild(s),i}var U=10,H=5;var G=10,z=10;function L(t){var e=0;if(t){var r=t.getBoundingClientRect().height,s=window.getComputedStyle(t).marginTop||"0px";e=r+parseInt(s.replace("px",""),10)}return e}t.MergeStyle=A,t.Mode=C,t.Orientation=x,t.TemplateName=_,t.createGitgraph=function(t,e){var r,s,i={},n={},o=!1,a=0,h=null,c=function(t){var e=document.createElementNS(B,"svg");return t?(t.children&&t.children.forEach(function(t){return e.appendChild(t)}),t.viewBox&&e.setAttribute("viewBox",t.viewBox),t.height&&e.setAttribute("height",t.height.toString()),t.width&&e.setAttribute("width",t.width.toString()),e):e}();new MutationObserver(function(){var t,e,h,p,d,g,f,b;o?(o=!1,g=Array.from(s.children),f=0,b=l.orientation===x.VerticalReverse?g:g.reverse(),n=b.reduce(function(t,e){var r=parseInt(e.getAttribute("transform").split(",")[1].slice(0,-1),10),s=e.getElementsByTagName("foreignObject")[0],i=s&&s.firstElementChild;return t[r]=r+f,f+=L(i),t},{}),m(r)):(l.isHorizontal||Object.keys(i).forEach(function(t){var e=i[t],r=e.branchLabel,s=e.tags,n=e.message,o=a;if(r){u(r,o);var h=r.getBBox().width+2*P;o+=h+10}s.forEach(function(t){u(t,o);var e=parseFloat(t.getAttribute("data-offset")||"0"),r=t.getBBox().width+2*U+e;o+=r+10}),n&&u(n,o)}),t=c.getBBox(),e=t.height,h=t.width,p=l.isHorizontal?50:P+G,d=l.isHorizontal?50:D+G,c.setAttribute("width",(h+p).toString()),c.setAttribute("height",(e+d).toString()))}).observe(c,{attributes:!1,subtree:!0,childList:!0}),t.appendChild(c);var l=new w(e);return l.subscribe(function(t){o=!0,m(t)}),l.getUserApi();function m(t){i={};var e=t.commits,n=t.branchesPaths;a=t.commitMessagesX,r=t,s=function(t){return R({children:t.map(function(e){var r=d(e),s=r.x,n=r.y;return R({translate:{x:s,y:n},children:[function(t){if(t.renderDot)return t.renderDot(t);var e=t.hash,r=function(t){var e=document.createElementNS(B,"circle");return e.setAttribute("cx",t.radius.toString()),e.setAttribute("cy",t.radius.toString()),e.setAttribute("r",t.radius.toString()),t.id&&e.setAttribute("id",t.id),t.fill&&e.setAttribute("fill",t.fill),e}({id:e,radius:t.style.dot.size,fill:t.style.dot.color||""}),s="clip-"+t.hash,i=document.createElementNS(B,"clipPath");i.setAttribute("id",s),i.appendChild(T(e));var n=T(e);n.setAttribute("clip-path","url(#"+s+")"),n.setAttribute("stroke",t.style.dot.strokeColor||"");var o=t.style.dot.strokeWidth?2*t.style.dot.strokeWidth:0;n.setAttribute("stroke-width",o.toString());var a,m,u=t.dotText?k({content:t.dotText,font:t.style.dot.font,anchor:"middle",translate:{x:t.style.dot.size,y:t.style.dot.size}}):null;return R({onClick:t.onClick,onMouseOver:function(){!function(t){if(c.firstChild&&(!l.isVertical||l.mode===C.Compact)&&(!l.isVertical||t.style.hasTooltipInCompactMode)){var e=t.renderTooltip?t.renderTooltip(t):function(t){var e=j({d:"",fill:"#EEE"}),r=k({translate:{x:z+G,y:0},content:t.hashAbbrev+" - "+t.subject,fill:"#333"}),s=2*t.style.dot.size,i=R({translate:{x:s,y:s/2},children:[e]});return new MutationObserver(function(){var t=r.getBBox().width,s=z+t+2*G,i=["M 0,0","L "+z+","+z,"V 20","Q "+z+",25 "+(z+5)+",25","H "+(s-5),"Q "+s+",25 "+s+",20","V -20","Q "+s+",-25 "+(s-5)+",-25","H "+(z+5),"Q "+z+",-25 "+z+",-20","V -"+z,"z"].join(" ");e.setAttribute("d",i.toString())}).observe(i,{attributes:!1,subtree:!1,childList:!0}),i.appendChild(r),i}(t);h=R({translate:d(t),children:[e]}),c.firstChild.appendChild(h)}}(t),t.onMouseOver()},onMouseOut:function(){h&&h.remove(),t.onMouseOut()},children:[(a=[r,i],m=document.createElementNS(B,"defs"),a.forEach(function(t){return m.appendChild(t)}),m),n,u]})}(e)].concat(function(e){if(!l.template.arrow.size)return[null];var r=e.style.dot.size;return e.parents.map(function(s){var i=t.find(function(t){var e=t.hash;return e===s});if(!i)return null;var n=l.reverseArrow?{x:r+(i.x-e.x),y:r+(i.y-e.y)}:{x:r,y:r},o=j({d:E(l,i,e),fill:l.template.arrow.color||""});return R({translate:n,children:[o]})})}(e),[R({translate:{x:-s,y:0},children:[function(t){if(!t.style.message.display)return null;var e;if(t.renderMessage)return p(e=R({children:[]})),e.appendChild(t.renderMessage(t)),g(t,e),e;var r=k({content:t.message,fill:t.style.message.color||"",font:t.style.message.font,onClick:t.onMessageClick});if(e=R({translate:{x:0,y:t.style.dot.size},children:[r]}),t.body){var s=function(t){var e=document.createElementNS(B,"foreignObject");e.setAttribute("width",t.width.toString()),t.translate&&(e.setAttribute("x",t.translate.x.toString()),e.setAttribute("y",t.translate.y.toString()));var r=document.createElement("p");return r.textContent=t.content,e.appendChild(r),e}({width:600,translate:{x:10,y:0},content:t.body});p(e),e.appendChild(s)}return g(t,e),e}(e)].concat(function(t){return Array.from(l.branches.values()).map(function(e){if(!e.style.label.display)return null;if(!l.branchLabelOnEveryCommit){var r=l.refs.getCommit(e.name);if(t.hash!==r)return null}if(t.branchToDisplay!==e.name)return null;var s,n=e.renderLabel?e.renderLabel(e):N(e,t);if(l.isVertical)s=R({children:[n]});else{var o=2*t.style.dot.size;s=R({translate:{x:t.x,y:o+10},children:[n]})}return function(t,e){i[t.hashAbbrev]||f(t),i[t.hashAbbrev].branchLabel=e}(t,s),s})}(e),function(t){return t.tags?l.isHorizontal?[]:t.tags.map(function(e){var r=e.render?e.render(e.name,e.style):function(t){var e=j({d:"",fill:t.style.bgColor,stroke:t.style.strokeColor}),r=k({content:t.name,fill:t.style.color,font:t.style.font,translate:{x:0,y:0}}),s=R({children:[e]}),i=t.style.pointerWidth;return new MutationObserver(function(){var s=r.getBBox(),n=s.height,o=s.width;if(0!==n&&0!==o){var a=t.style.borderRadius,h=i+o+2*U,c=n+2*H,l=["M 0,0","L "+i+","+c/2,"V "+c/2,"Q "+i+","+c/2+" "+(i+a)+","+c/2,"H "+(h-a),"Q "+h+","+c/2+" "+h+","+(c/2-a),"V -"+(c/2-a),"Q "+h+",-"+c/2+" "+(h-a)+",-"+c/2,"H "+(i+a),"Q "+i+",-"+c/2+" "+i+",-"+c/2,"V -"+c/2,"z"].join(" ");e.setAttribute("d",l.toString()),r.setAttribute("x",(i+U).toString())}}).observe(s,{attributes:!1,subtree:!1,childList:!0}),s.appendChild(r),s}(e),s=R({translate:{x:0,y:t.style.dot.size},children:[r]});return s.setAttribute("data-offset",e.style.pointerWidth.toString()),function(t,e){i[t.hashAbbrev]||f(t),i[t.hashAbbrev].tags.push(e)}(t,s),s}):[]}(e))})])})})})}(e),c.innerHTML="",c.appendChild(R({translate:{x:P,y:G},children:[function(t){var e=l.template.commit.dot.size,r=l.template.branch.mergeStyle===A.Bezier;return R({children:Array.from(t).map(function(t){var s=t[0],i=t[1];return j({d:S(i.map(function(t){return t.map(d)}),r,l.isVertical),fill:"transparent",stroke:s.computedColor||"",strokeWidth:s.style.lineWidth,translate:{x:e,y:e}})})})}(n),s]}))}function u(t,e){var r=t.getAttribute("transform")||"translate(0, 0)";t.setAttribute("transform",r.replace(/translate\(([\d\.]+),/,"translate("+e+","))}function p(t){function e(t){if("foreignObject"===t.nodeName){var r=t.firstChild&&t.firstChild.parentElement;if(!r)return;r.setAttribute("height",L(r.firstElementChild).toString())}t.childNodes.forEach(e)}new MutationObserver(function(t){t.forEach(function(t){return e(t.target)})}).observe(t,{attributes:!1,subtree:!1,childList:!0})}function d(t){var e=t.x,r=t.y;return{x:e,y:n[r]||r}}function g(t,e){i[t.hashAbbrev]||f(t),i[t.hashAbbrev].message=e}function f(t){i[t.hashAbbrev]={branchLabel:null,tags:[],message:null}}},t.templateExtend=M,Object.defineProperty(t,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/.github/git-workflow/workflow.html b/.github/git-workflow/workflow.html index d93c43c51b4..463947cefa4 100644 --- a/.github/git-workflow/workflow.html +++ b/.github/git-workflow/workflow.html @@ -5,11 +5,11 @@ YARP Workflow + - - +
diff --git a/.github/git-workflow/workflow.js b/.github/git-workflow/workflow.js index 7cbe83ef172..444272d0b80 100644 --- a/.github/git-workflow/workflow.js +++ b/.github/git-workflow/workflow.js @@ -1,56 +1,122 @@ -var config = { - template: "metro", - orientation: "vertical-reverse", +const branchesOrder = ["security_fix_on_oldstable", + "yarp-3.3", + "bugfix_on_stable", + "yarp-3.4", + "new_feature_on_master", + "master"]; + +var compareBranchesOrder = function(a, b) { return branchesOrder.indexOf(a) - branchesOrder.indexOf(b); }; + +const options = { + template: GitgraphJS.templateExtend("metro", { + colors: ["#008fb5", + "#979797", + "#ae00e3", + "#123456", + "#f18f00", + "#00aa00"], + commit: { + message: { + displayAuthor: false, + displayHash: false, + font: '11pt monospace', + }, + spacing: '32', + dot: { + size: '8' + } + }, + branch: { + lineWidth: '7', + label: { + font: 'italic 9pt serif', + }, + }, + tag: { + font: 'bold 11pt monospace', + } + }), author: "Daniele E. Domenichelli ", + compareBranchesOrder: compareBranchesOrder }; -var gitGraph = new GitGraph( config ); -gitGraph.template.commit.message.displayHash = false; -gitGraph.template.commit.message.displayAuthor = false; -gitGraph.template.colors = ["#008fb5", - "#979797", - "#ae00e3", - "#f18f00"]; + +const graphContainer = document.getElementById("gitgraph"); +const gitgraph = GitgraphJS.createGitgraph(graphContainer, options); // Create branch named "master" -var master = gitGraph.orphanBranch({ - name: "master", - column: 0 -}); +var master = gitgraph.branch("master"); +// Add some spacing +master.commit({ subject: "", style: { dot: { size: '0' }} }); +master.commit({ subject: "YARP 3.3.0", tag: "v3.3.0" }); + + +// Create branch named "yarp-3.3" +var oldstable = master.branch("yarp-3.3"); +oldstable.commit("Start YARP 3.3.1 development"); +master.merge(oldstable, "Merge branch yarp-3.3 into master"); +master.commit("Start YARP 3.4 development").tag({ name: "(v3.3.100)", style: { color: "#00aa0060", bgColor: "#fff"} }); + +// Add some spacing +oldstable.commit({ subject: "", style: { dot: { size: '0' }} }); +oldstable.commit({ subject: "", style: { dot: { size: '0' }} }); + + +oldstable.commit({ subject: "YARP 3.3.1", tag: "v3.3.1" }); +master.merge(oldstable, "Merge branch yarp-3.3 into master"); + +master.commit({ subject: "", style: { dot: { size: '0' }} }); +master.commit({ subject: "YARP 3.4.0", tag: "v3.4.0" }); -// Create branch named "devel" -var devel = gitGraph.orphanBranch({ - name: "devel", - column: 2 -}); +// Create branch named "yarp-3.4" and start new development on master branch +var stable = master.branch("yarp-3.4"); +master.commit("Start YARP 3.5 development").tag({ name: "(v3.4.100)", style: { color: "#00aa0060", bgColor: "#fff"} }); +master.commit({ subject: "", style: { dot: { size: '0' }} }); +// Create a security fix on oldstable branch +oldstable.commit("Start YARP 3.3.2 development"); +var security_fix_on_oldstable = oldstable.branch({ name: "security_fix_on_oldstable", style: { lineWidth: '4' }}); +security_fix_on_oldstable.commit("Start working on issue #xxx"); +security_fix_on_oldstable.commit("Fix issue #xxx"); +oldstable.merge(security_fix_on_oldstable, "Merge pull request #xxy from /security_fix_on_oldstable") +stable.merge(oldstable, "Merge branch yarp-3.3 into yarp-3.4"); +master.merge(stable, "Merge branch yarp-3.4 into master"); -devel.commit("Work in progress"); +master.commit({ subject: "", style: { dot: { size: '0' }} }); -master.commit({ message: "YARP 3.0.1", tag: "v3.0.1" }); -master.merge(devel, "Merge branch origin/master into devel"); +oldstable.commit({ subject: "YARP 3.3.2", tag: "v3.3.2" }); +stable.merge(oldstable, "Merge branch yarp-3.3 into yarp-3.4"); +master.merge(stable, "Merge branch yarp-3.4 into master"); -devel.commit("Get ready for the new stable release"); +master.commit({ subject: "", style: { dot: { size: '0' }} }); +// Create a bugfix on stable branch +stable.commit("Start YARP 3.4.1 development"); +var bugfix_on_stable = stable.branch({ name: "bugfix_on_stable", style: { lineWidth: '4' }}); +bugfix_on_stable.commit("Start working on issue #xxx"); +bugfix_on_stable.commit("Fix issue #xxx"); +stable.merge(bugfix_on_stable, "Merge pull request #xxy from /bugfix_on_stable") +master.merge(stable, "Merge branch stable into master") -devel.merge(master, "Merge branch origin/devel into master"); -master.commit({ message: "YARP 3.1.0", tag: "v3.1.0" }); -master.merge(devel, "Merge branch origin/master into devel"); -devel.commit({ message: "Start YARP 3.2 development", tag: "(v3.1.100)" }); +master.commit({ subject: "", style: { dot: { size: '0' }} }); +master.commit("..."); +// Create a feature on master branch +var new_feature_on_master = master.branch({ name: "new_feature_on_master", style: { lineWidth: '4' }}); +new_feature_on_master.commit("Start working on feature 'foo'"); +new_feature_on_master.commit("Continue working on feature 'foo'"); +new_feature_on_master.commit("Finish implementing feature 'foo'"); +master.merge(new_feature_on_master, "Merge pull request #xxy from /new_feature_on_master") +master.commit("Bump tweak number").tag({ name: "(v3.4.101)", style: { color: "#00aa0060", bgColor: "#fff", font: '11pt monospace'} }); -var feature_foo = devel.branch({ name: "feature_foo", column: 3 }); -feature_foo.commit("Start working on feature 'foo'"); -feature_foo.commit("Continue working on feature 'foo'"); -feature_foo.commit("Finish implementing feature 'foo'"); -feature_foo.merge(devel, "Merge branch feature_foo into devel"); -devel.commit({ message: "Bump tweak number", tag: "(v3.1.101)" }); +master.commit({ subject: "", style: { dot: { size: '0' }} }); +stable.commit({ subject: "YARP 3.4.1", tag: "v3.4.1" }); +stable.commit("Start YARP 3.4.2 development"); +master.merge(stable, "Merge branch stable into master") -var bugfix_xxx = master.branch({ name: "bugfix_xxx", column: 1 }); -bugfix_xxx.commit("Start working on issue #xxx"); -bugfix_xxx.commit("Fix issue #xxx"); -bugfix_xxx.merge(master, "Merge pull request #xxy from /bugfix_xxx") -master.commit({ message: "YARP 3.1.1", tag: "v3.1.1" }); -master.merge(devel, "Merge branch origin/master into devel") +master.commit({ subject: "", style: { dot: { size: '0' }} }); +oldstable.commit({ subject: "", style: { dot: { size: '0' }} }); +stable.commit({ subject: "", style: { dot: { size: '0' }} }); +master.commit({ subject: "", style: { dot: { size: '0' }} }); diff --git a/README.md b/README.md index a52978f9bcc..31f3f68d59d 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,7 @@ used on everything from humanoids to embedded devices. Documentation ------------- -[![YARP documentation (master)](https://img.shields.io/badge/[master]_Documentation-yarp.it-19c2d8.svg)](http://www.yarp.it/) -[![YARP documentation (devel)](https://img.shields.io/badge/[devel]_Documentation-yarp.it-19c2d8.svg)](http://www.yarp.it/devel/) +[![YARP documentation](https://img.shields.io/badge/Documentation-yarp.it-19c2d8.svg)](http://www.yarp.it/) Installation @@ -66,7 +65,7 @@ There's a comprehensive list of tutorials here: License ------- -[![License](https://img.shields.io/badge/license-BSD%20%2B%20others-19c2d8.svg)](https://github.com/robotology/yarp/blob/devel/LICENSE) +[![License](https://img.shields.io/badge/license-BSD%20%2B%20others-19c2d8.svg)](https://github.com/robotology/yarp/blob/master/LICENSE) Material included in YARP is Copyright of Istituto Italiano di Tecnologia (IIT), RobotCub Consortium and other contributors. @@ -80,11 +79,8 @@ See the file COPYING and LICENSE files for details. CI Status --------- -[![Build Status (Linux/macOS) (master branch)](https://img.shields.io/travis/robotology/yarp/master.svg?logo=travis&label=[master]%20build%20(Linux/macOS))](https://travis-ci.org/robotology/yarp) -[![Build Status (Linux/macOS) (devel branch)](https://img.shields.io/travis/robotology/yarp/devel.svg?logo=travis&label=[devel]%20build%20(Linux/macOS))](https://travis-ci.org/robotology/yarp) - -[![Build status (Windows) (master branch)](https://img.shields.io/appveyor/ci/robotology/yarp/master.svg?logo=appveyor&label=[master]%20build%20(Windows))](https://ci.appveyor.com/project/robotology/yarp) -[![Build status (Windows) (devel branch)](https://img.shields.io/appveyor/ci/robotology/yarp/devel.svg?logo=appveyor&label=[devel]%20build%20(Windows))](https://ci.appveyor.com/project/robotology/yarp) +[![Build Status (Linux/macOS)](https://img.shields.io/travis/robotology/yarp/master.svg?logo=travis&label=build%20(Linux/macOS))](https://travis-ci.org/robotology/yarp) +[![Build status (Windows)](https://img.shields.io/appveyor/ci/robotology/yarp/master.svg?logo=appveyor&label=build%20(Windows))](https://ci.appveyor.com/project/robotology/yarp) and [more](http://dashboard.icub.org/index.php?project=YARP) @@ -93,8 +89,7 @@ Stats ----- [![Github commits (since latest release)](https://img.shields.io/github/commits-since/robotology/yarp/latest.svg)](https://github.com/robotology/yarp) -[![GitHub last commit (master branch)](https://img.shields.io/github/last-commit/robotology/yarp/master.svg?label=[master]%20last%20commit)](https://github.com/robotology/yarp) -[![GitHub last commit (devel branch)](https://img.shields.io/github/last-commit/robotology/yarp/devel.svg?label=[devel]%20last%20commit)](https://github.com/robotology/yarp) +[![GitHub last commit](https://img.shields.io/github/last-commit/robotology/yarp/master.svg?label=last%20commit)](https://github.com/robotology/yarp) [![GitHub commit activity the past week, 4 weeks, year](https://img.shields.io/github/commit-activity/y/robotology/yarp.svg)](https://github.com/robotology/yarp) [![GitHub contributors](https://img.shields.io/github/contributors/robotology/yarp.svg)](https://github.com/robotology/yarp/graphs/contributors)