md-to-adf
Version:
Translate Markdown (Github) into Atlassian Document Format (ADF)
1,687 lines (1,477 loc) • 70.6 kB
JavaScript
module.exports =
/******/ (function(modules, runtime) { // webpackBootstrap
/******/ "use strict";
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ __webpack_require__.ab = __dirname + "/";
/******/
/******/ // the startup function
/******/ function startup() {
/******/ // Load entry module and return exports
/******/ return __webpack_require__(503);
/******/ };
/******/
/******/ // run startup
/******/ return startup();
/******/ })
/************************************************************************/
/******/ ({
/***/ 103:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class Strike extends mark_1.Mark {
constructor() {
super('strike');
}
}
exports.Strike = Strike;
//# sourceMappingURL=strike.js.map
/***/ }),
/***/ 135:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const emoji_1 = __webpack_require__(526);
const hard_break_1 = __webpack_require__(570);
const index_1 = __webpack_require__(492);
const mention_1 = __webpack_require__(962);
const text_1 = __webpack_require__(171);
class Decision {
constructor(localId, state) {
this.localId = localId;
this.state = state;
this.content = new index_1.ContentNode('decisionItem');
}
text(text, marks) {
return this.add(new text_1.Text(text, marks));
}
code(text) {
return this.add(text_1.code(text));
}
em(text) {
return this.add(text_1.em(text));
}
link(text, href, title) {
return this.add(text_1.link(text, href, title));
}
strike(text) {
return this.add(text_1.strike(text));
}
strong(text) {
return this.add(text_1.strong(text));
}
mention(id, text) {
return this.add(new mention_1.Mention(id, text));
}
emoji(shortName, id, text) {
return this.add(new emoji_1.Emoji({ shortName, id, text }));
}
hardBreak() {
return this.add(new hard_break_1.HardBreak());
}
add(node) {
this.content.add(node);
return this;
}
toJSON() {
return Object.assign({}, this.content.toJSON(), { attrs: {
localId: this.localId,
state: this.state
} });
}
}
exports.Decision = Decision;
//# sourceMappingURL=decision.js.map
/***/ }),
/***/ 147:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const emoji_1 = __webpack_require__(526);
const hard_break_1 = __webpack_require__(570);
const index_1 = __webpack_require__(492);
const mention_1 = __webpack_require__(962);
const text_1 = __webpack_require__(171);
class Paragraph extends index_1.TopLevelNode {
constructor() {
super(...arguments);
this.content = new index_1.ContentNode('paragraph');
}
text(text, marks) {
return this.add(new text_1.Text(text, marks));
}
code(text) {
return this.add(text_1.code(text));
}
em(text) {
return this.add(text_1.em(text));
}
link(text, href, title) {
return this.add(text_1.link(text, href, title));
}
strong(text) {
return this.add(text_1.strong(text));
}
mention(id, text) {
return this.add(new mention_1.Mention(id, text));
}
emoji(shortName, id, text) {
return this.add(new emoji_1.Emoji({ shortName, id, text }));
}
hardBreak() {
return this.add(new hard_break_1.HardBreak());
}
add(node) {
this.content.add(node);
return this;
}
toJSON() {
return this.content.toJSON();
}
}
exports.Paragraph = Paragraph;
//# sourceMappingURL=paragraph.js.map
/***/ }),
/***/ 171:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(812);
const index_2 = __webpack_require__(492);
function plain(text) {
return new Text(text);
}
exports.plain = plain;
function strike(text) {
return new Text(text, index_1.marks().strike());
}
exports.strike = strike;
function strong(text) {
return new Text(text, index_1.marks().strong());
}
exports.strong = strong;
function em(text) {
return new Text(text, index_1.marks().em());
}
exports.em = em;
function link(text, href, title) {
return new Text(text, index_1.marks().link(href, title));
}
exports.link = link;
function code(text) {
return new Text(text, index_1.marks().code());
}
exports.code = code;
class Text extends index_2.InlineNode {
constructor(text, marks) {
super();
this.text = text;
this.marks = marks;
if (!text || text.length === 0) {
throw new Error('Text must be at least one character long');
}
}
toJSON() {
const textNode = {
type: 'text',
text: this.text,
};
if (this.marks) {
textNode.marks = this.marks.toJSON();
}
return textNode;
}
}
exports.Text = Text;
//# sourceMappingURL=text.js.map
/***/ }),
/***/ 192:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class Strong extends mark_1.Mark {
constructor() {
super('strong');
}
}
exports.Strong = Strong;
//# sourceMappingURL=strong.js.map
/***/ }),
/***/ 197:
/***/ (function(module, __unusedexports, __webpack_require__) {
/**********************************************************************************************************************
*
* Markdown handling
*
* @author bruno.morel@b-yond.com
*---------------------------------------------------------------------------------------------------------------------
*
* This build an intermediate representation tree and manage the hierarchy and priorities of the markdown expressions
* each branch will contain an object with the follow properties:
*
**********************************************************************************************************************/
const translateMarkdownLineToIR = __webpack_require__( 572 )
/**
* @typedef {Object} IRTreeNode
* @property {IRElement} node - intermediate representation of the markdown element
* @property {IRElement[]} children - the list of children attach to that node
* @property {Number} indexOfList - the index in the list of expression
*/
/**
* Implement markdown greediness and collapsing of subnode, generate the final node tree representing
* the IRElement topology
*
* @param rawTextMarkdown {String[]} array of expression to parse and handle
*
* @returns {IRElement[]} an array of IRElement
*/
function buildTreeFromMarkdown( rawTextMarkdown ){
//code block are the most greedy expression in markdown
const cleanedCodeBlock = collapseCodeBloc( rawTextMarkdown )
//block quote collapse paragraphs, so we have to to them first
const blockquotedNodes = collapseBlockquote( cleanedCodeBlock )
//paragraph themselves collapse when they are not separated by
// two consecutive empty lines
const breakedLineNodes = collapseParagraph( blockquotedNodes )
//lists accumulate elements of the same level unless separated by
// two consecutive empty lines
const accumulatedNodes = accumulateLevelFromList( breakedLineNodes )
//we build the array of textPosition for each level
const levelsPosition = createLevelList( accumulatedNodes )
//map each element to a level, in order
const elementMap = mapIRToLevels( accumulatedNodes, levelsPosition )
return buildTreeFromLevelMap( elementMap )
}
/**
* CodeBlock swallow all text until they are closed, so we collapsed all paragraph into them
* When a code block is open, it should be closed by a triple caret, everything in between is code
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into collapsing
*
* @returns {IRElement[]} an array of IRElement
*/
function collapseCodeBloc( rawIROfMarkdown ){
///MARDKOWN logic - closing code blocks
//
const { codeBlockHandled } = rawIROfMarkdown.split( /\r\n|\r|\n/ ).reduce( ( { codeBlockHandled, indexCurrentCodeBloc }, currentLine ) => {
const lineTranslation = translateMarkdownLineToIR( currentLine )
if( typeof indexCurrentCodeBloc === "undefined"
&& ( lineTranslation.adfType === 'codeBlock'
|| lineTranslation.nodeAttached ) ){
codeBlockHandled.push( lineTranslation )
if( lineTranslation.nodeAttached ){
codeBlockHandled.push( lineTranslation.nodeAttached )
}
return { codeBlockHandled, indexCurrentCodeBloc: codeBlockHandled.length - 1 }
}
if( typeof indexCurrentCodeBloc !== "undefined"
&& ( lineTranslation.adfType !== 'codeBlock'
|| typeof lineTranslation.typeParam === "undefined"
|| lineTranslation.typeParam !== '' ) ) {
const textToAdd = lineTranslation.textPosition >= codeBlockHandled[ indexCurrentCodeBloc ].textPosition
? currentLine.slice( codeBlockHandled[ indexCurrentCodeBloc ].textPosition )
: currentLine
codeBlockHandled[ indexCurrentCodeBloc ].textToEmphasis = codeBlockHandled[ indexCurrentCodeBloc ].textToEmphasis
+ ( codeBlockHandled[ indexCurrentCodeBloc ].textToEmphasis === ''
? textToAdd
: '\n' + textToAdd )
return { codeBlockHandled, indexCurrentCodeBloc }
}
if( typeof indexCurrentCodeBloc !== "undefined"
&& lineTranslation.adfType === 'codeBlock'
&& typeof lineTranslation.typeParam !== "undefined"
&& lineTranslation.typeParam === '' ){
return { codeBlockHandled }
}
codeBlockHandled.push( lineTranslation )
return { codeBlockHandled }
}, { codeBlockHandled: [] } )
//handling of unfinished empty codeBlock
const cleanedCodeBlock = codeBlockHandled.filter( ( currentNode ) => {
if( currentNode.adfType !== 'codeBlock' )
return currentNode
if( currentNode.textToEmphasis !== '' )
return currentNode
} )
return cleanedCodeBlock
}
/**
* Blockquote start with each line identify with a caret. Any interruption (line break) create a new blockquote
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into collapsing
*
* @returns {IRElement[]} an array of IRElement
*/
function collapseBlockquote( rawIROfMarkdown ){
const { blockquotedNodes } = rawIROfMarkdown.reduce( ( { blockquotedNodes, currentLastThatWasBlockQuote }, currentLineNode ) => {
if( !currentLastThatWasBlockQuote
&& currentLineNode.adfType === 'blockQuote' ){
blockquotedNodes.push( currentLineNode )
return { blockquotedNodes, currentLastThatWasBlockQuote: currentLineNode }
}
//this is a non-empty paragraph, if we are already filling up a paragraph, let's add the text inside
if( currentLastThatWasBlockQuote
&& currentLineNode.adfType === 'blockQuote' ){
currentLastThatWasBlockQuote.textToEmphasis = currentLastThatWasBlockQuote.textToEmphasis +
' ' + currentLineNode.textToEmphasis
return { blockquotedNodes, currentLastThatWasBlockQuote }
}
//this is non-blockquote node, we add it to the list
blockquotedNodes.push( currentLineNode )
return { blockquotedNodes }
}, { blockquotedNodes: [ ] } )
return blockquotedNodes
}
/**
* Heading is an exception, otherwise non-empty line aggregate in the parent element
* For all other type, following a markdown with any paragraph of text is considered a continuation, so we aggregate
* all subsequent text into the same parent element (paragraph, list item, ...)
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into collapsing
*
* @returns {IRElement[]} an array of IRElement
*/
function collapseParagraph( rawIROfMarkdown ){
const { breakedLineNodes } = rawIROfMarkdown.reduce( ( { breakedLineNodes, currentParent, lastWasAlsoAParagraph }, currentLineNode ) => {
if( currentLineNode.adfType === 'heading'
|| currentLineNode.adfType === 'divider'
|| currentLineNode.adfType === 'codeBlock' ){
breakedLineNodes.push( currentLineNode )
return { breakedLineNodes }
}
if( currentLineNode.adfType !== 'paragraph' ){
breakedLineNodes.push( currentLineNode )
return { breakedLineNodes, currentParent: currentLineNode }
}
if( !lastWasAlsoAParagraph
&& /^(?:[\s]*)$/.test( currentLineNode.textToEmphasis ) ) {
//we're breaking into a new paragraph
return { breakedLineNodes, lastWasAlsoAParagraph: true }
}
if( lastWasAlsoAParagraph
&& /^(?:[\s]*)$/.test( currentLineNode.textToEmphasis ) ) {
//we've double break, we add a paragraph
breakedLineNodes.push( currentLineNode )
return { breakedLineNodes }
}
//this is a non-empty paragraph, if we are already filling up a paragraph, let's add the text inside
if( currentParent ){
const textToAdd = currentLineNode.textPosition >= currentParent.textPosition
? currentLineNode.textToEmphasis.slice( currentParent.textPosition )
: currentLineNode.textToEmphasis
currentParent.textToEmphasis = currentParent.textToEmphasis + ( currentLineNode.textToEmphasis.charAt( 0 ) !== ' '
? ' ' + textToAdd
: textToAdd )
return { breakedLineNodes, currentParent }
}
//this is a lone new paragraph, we add it to the list
breakedLineNodes.push( currentLineNode )
return { breakedLineNodes, currentParent: currentLineNode }
}, { breakedLineNodes: [ ] } )
return breakedLineNodes
}
/**
* Realign children nodes to orderedList and bulletList
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into collapsing
*
* @returns {IRElement[]} an array of IRElement
*/
function accumulateLevelFromList( rawIROfMarkdown ){
const { accumulatedNodes } = rawIROfMarkdown.reduce( ( { accumulatedNodes, indexCurrentList }, currentLineNode ) => {
if( currentLineNode.adfType !== 'heading'
&& currentLineNode.adfType !== 'divider'
&& currentLineNode.adfType !== 'orderedList'
&& currentLineNode.adfType !== 'bulletList'
&& indexCurrentList
&& currentLineNode.textPosition < accumulatedNodes[ indexCurrentList ].textPosition + 2 ){
currentLineNode.textPosition = accumulatedNodes[ indexCurrentList ].textPosition + 2
}
accumulatedNodes.push( currentLineNode )
if( currentLineNode.adfType === 'heading'
|| currentLineNode.adfType === 'divider' )
return { accumulatedNodes }
if( currentLineNode.adfType === 'bulletList' || currentLineNode.adfType === 'orderedList' ){
return { accumulatedNodes, indexCurrentList: accumulatedNodes.length - 1 }
}
return { accumulatedNodes, indexCurrentList }
}, { accumulatedNodes: [ ] } )
return accumulatedNodes
}
/**
* Build an array of all the different level (defined by the lists) we have to manage
* and their corresponding textPosition
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into collapsing
*
* @returns {Number[]} an array of the textPosition for each level
*/
function createLevelList( rawIROfMarkdown ){
return rawIROfMarkdown.reduce( ( currentLevelList, currentNode ) => {
if( currentNode.adfType !== 'orderedList'
&& currentNode.adfType !== 'bulletList' )
return currentLevelList
return ( currentLevelList.includes( currentNode.textPosition + 2 ) || currentLevelList.includes( currentNode.textPosition + 3 ) )
? currentLevelList
: currentNode.textPosition + 2 > ( currentLevelList[ currentLevelList.length - 1 ] + 1 )
? [ ...currentLevelList, currentNode.textPosition + 2 ]
: currentLevelList
}, [ 0 ] )
}
/**
* Map all element to their level in an array of level
*
* @param rawIROfMarkdown {Array} the array of IRElement to look into mapping
* @param levelsPosition {Array} the list of level's textPosition to use
*
* @returns {IRTreeNode[]} an array of IRTreeNode
*/
function mapIRToLevels( rawIROfMarkdown, levelsPosition ){
return levelsPosition.map( ( currentLevelPosition, currentIndex ) => {
return rawIROfMarkdown.filter( currentList => ( currentList.textPosition >= currentLevelPosition
&& ( currentIndex === levelsPosition.length - 1 //this is the last level
|| currentList.textPosition < levelsPosition[ currentIndex + 1 ] ) ) )
.map( currentList => ( {
indexOfList: rawIROfMarkdown.indexOf( currentList ),
children: [],
node: currentList } ) )
} )
}
/**
* Map all element to their level in an array of level
*
* @param levelsMap {Array} the level array of array of IRElement
*
* @returns {IRTreeNode[]} tree of IRElements and their children
*/
function buildTreeFromLevelMap( levelsMap ){
const treeOfNode = levelsMap.reduce( ( currentTree, currentArrayOfListIndexes, currentIndexInTheArrayOfListIndexes ) => {
const stepAtTree = currentArrayOfListIndexes.reduce( ( currentTreeValues, currentListValues ) => {
if( currentIndexInTheArrayOfListIndexes <= 0 )
return [ ...currentTreeValues, currentListValues ]
const parentList = levelsMap[ currentIndexInTheArrayOfListIndexes - 1 ]
const lastParentWithIndexBelow = parentList.findIndex( currentParentListIndex => {
return currentParentListIndex.indexOfList > currentListValues.indexOfList
} )
const parentIndexToUse = lastParentWithIndexBelow === -1
? parentList.length - 1
: lastParentWithIndexBelow === 0
? 0
: lastParentWithIndexBelow - 1
if( parentIndexToUse < 0 )
throw 'Parent list of node is empty!'
parentList[ parentIndexToUse ].children.push( currentListValues )
return currentTreeValues
}, currentTree )
return stepAtTree
}, [] )
return treeOfNode
}
module.exports = buildTreeFromMarkdown
/***/ }),
/***/ 198:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const decision_1 = __webpack_require__(135);
const index_1 = __webpack_require__(492);
class DecisionList extends index_1.TopLevelNode {
constructor(localId) {
super();
this.localId = localId;
this.content = new index_1.ContentNode('decisionList');
}
decision(localId, state) {
return this.content.add(new decision_1.Decision(localId, state));
}
toJSON() {
return Object.assign({}, this.content.toJSON(), { attrs: {
localId: this.localId
} });
}
}
exports.DecisionList = DecisionList;
//# sourceMappingURL=decision-list.js.map
/***/ }),
/***/ 206:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class Link extends mark_1.Mark {
constructor(href, title) {
super('link');
this.href = href;
this.title = title;
}
toJSON() {
const linkMark = {
type: this.type,
attrs: {
href: this.href
}
};
if (this.title) {
linkMark.attrs.title = this.title;
}
return linkMark;
}
}
exports.Link = Link;
//# sourceMappingURL=link.js.map
/***/ }),
/***/ 223:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
class Rule extends index_1.TopLevelNode {
toJSON() {
return {
type: 'rule'
};
}
}
exports.Rule = Rule;
//# sourceMappingURL=rule.js.map
/***/ }),
/***/ 270:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bullet_list_1 = __webpack_require__(849);
const heading_1 = __webpack_require__(366);
const index_1 = __webpack_require__(492);
const ordered_list_1 = __webpack_require__(982);
const paragraph_1 = __webpack_require__(147);
class Panel extends index_1.TopLevelNode {
constructor(panelType) {
super();
this.panelType = panelType;
this.content = new index_1.ContentNode('panel');
}
heading(level) {
return this.content.add(new heading_1.Heading(level));
}
paragraph() {
return this.content.add(new paragraph_1.Paragraph());
}
orderedList() {
return this.content.add(new ordered_list_1.OrderedList());
}
bulletList() {
return this.content.add(new bullet_list_1.BulletList());
}
toJSON() {
return Object.assign({}, this.content.toJSON(), { attrs: {
panelType: this.panelType
} });
}
}
exports.Panel = Panel;
//# sourceMappingURL=panel.js.map
/***/ }),
/***/ 284:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const emoji_1 = __webpack_require__(526);
const hard_break_1 = __webpack_require__(570);
const index_1 = __webpack_require__(492);
const mention_1 = __webpack_require__(962);
const text_1 = __webpack_require__(171);
class Task {
constructor(localId, state) {
this.localId = localId;
this.state = state;
this.content = new index_1.ContentNode('taskItem');
}
text(text, marks) {
return this.add(new text_1.Text(text, marks));
}
code(text) {
return this.add(text_1.code(text));
}
em(text) {
return this.add(text_1.em(text));
}
link(text, href, title) {
return this.add(text_1.link(text, href, title));
}
strike(text) {
return this.add(text_1.strike(text));
}
strong(text) {
return this.add(text_1.strong(text));
}
mention(id, text) {
return this.add(new mention_1.Mention(id, text));
}
emoji(shortName, id, text) {
return this.add(new emoji_1.Emoji({ shortName, id, text }));
}
hardBreak() {
return this.add(new hard_break_1.HardBreak());
}
add(node) {
this.content.add(node);
return this;
}
toJSON() {
return Object.assign({}, this.content.toJSON(), { attrs: {
localId: this.localId,
state: this.state
} });
}
}
exports.Task = Task;
var TaskState;
(function (TaskState) {
TaskState["TODO"] = "TODO";
TaskState["DONE"] = "DONE";
})(TaskState = exports.TaskState || (exports.TaskState = {}));
//# sourceMappingURL=task.js.map
/***/ }),
/***/ 286:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
var document_1 = __webpack_require__(802);
exports.Document = document_1.Document;
var tag_1 = __webpack_require__(322);
exports.document = tag_1.document;
__export(__webpack_require__(451));
__export(__webpack_require__(893));
__export(__webpack_require__(849));
__export(__webpack_require__(561));
__export(__webpack_require__(198));
__export(__webpack_require__(135));
__export(__webpack_require__(526));
__export(__webpack_require__(570));
__export(__webpack_require__(366));
__export(__webpack_require__(566));
__export(__webpack_require__(823));
__export(__webpack_require__(371));
__export(__webpack_require__(962));
__export(__webpack_require__(982));
__export(__webpack_require__(270));
__export(__webpack_require__(147));
__export(__webpack_require__(223));
__export(__webpack_require__(976));
__export(__webpack_require__(284));
__export(__webpack_require__(171));
__export(__webpack_require__(812));
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 294:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class Underline extends mark_1.Mark {
constructor() {
super('underline');
}
}
exports.Underline = Underline;
//# sourceMappingURL=underline.js.map
/***/ }),
/***/ 322:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const document_1 = __webpack_require__(802);
const index_1 = __webpack_require__(492);
function document(strings, ...args) {
const doc = new document_1.Document();
const paragraph = doc.paragraph();
for (let i = 0; i < args.length; i++) {
if (strings[i].length) {
paragraph.text(strings[i]);
}
if (args[i] instanceof index_1.TopLevelNode) {
throw new Error('Top level nodes cannot be used in tagged templates');
}
if (args[i] instanceof index_1.InlineNode) {
paragraph.add(args[i]);
}
else {
const stringified = String(args[i]);
if (stringified.length > 0) {
paragraph.text(stringified);
}
}
}
if (strings[args.length].length > 0) {
paragraph.text(strings[args.length]);
}
return doc;
}
exports.document = document;
//# sourceMappingURL=tag.js.map
/***/ }),
/***/ 326:
/***/ (function(module, __unusedexports, __webpack_require__) {
/***********************************************************************************************************************
*
* Atlassian Document Format Handling
*
* @author bruno.morel@b-yond.com
* ---------------------------------------------------------------------------------------------------------------------
*
* This transform a Intermediate Representation Tree (see markdownHandling) into the equivalent ADF nodes.
* It also remove non-compatible hierarchy that ADF doesn't support
*
**********************************************************************************************************************/
const { marks, Heading, Text, Emoji, BulletList, OrderedList, ListItem, CodeBlock, BlockQuote, Paragraph, Rule } = __webpack_require__( 286 )
const attachTextToNodeSliceEmphasis = __webpack_require__( 804 )
// /**
// * @typedef { import("./markdownParsing").IRElement } IRElement
// * @typedef { import("./markdownHandling").IRTreeNode } IRTreeNode
// */
/**
* Browse the tree recursively to add each node to the ADF Document
* It also treat special cases between top-level node and generic ones
*
* @param currentParentNode {Document} ADF document to add to
* @param currentArrayOfNodesOfSameIndent {IRTreeNode}
*/
function fillADFNodesWithMarkdown( currentParentNode, currentArrayOfNodesOfSameIndent ){
currentArrayOfNodesOfSameIndent.reduce( ( lastListNode, currentNode ) => {
const nodeOrListNode = lastListNode !== null
&& ( currentNode.node.adfType === 'orderedList' || currentNode.node.adfType === 'bulletList' )
&& lastListNode.content.type === currentNode.node.adfType
? lastListNode
: addTypeToNode( currentParentNode, currentNode.node.adfType, currentNode.node.typeParam )
const nodeOrListItem = currentNode.node.adfType === 'orderedList' || currentNode.node.adfType === 'bulletList'
? nodeOrListNode.content.add( new ListItem() )
: nodeOrListNode
const nodeToAttachTextTo = currentNode.node.adfType === 'orderedList' || currentNode.node.adfType === 'bulletList' || currentNode.node.adfType === 'blockQuote'
? typeof currentNode.node.textToEmphasis !== 'undefined' || currentNode.children.length === 0
? nodeOrListItem.content.add( new Paragraph() )
: nodeOrListItem
: nodeOrListItem
if( currentNode.node.adfType === 'divider' )
return lastListNode
else if( currentNode.node.adfType !== 'codeBlock'
&& currentNode.node.textToEmphasis )
attachItemNode( nodeToAttachTextTo, currentNode.node.textToEmphasis )
else if( currentNode.node.adfType !== 'codeBlock'
&& currentNode.node.textToEmphasis === '' )
attachItemNode( nodeToAttachTextTo, ' ' )
else if( currentNode.node.adfType === 'codeBlock' )
attachTextToNodeRaw( nodeToAttachTextTo, currentNode.node.textToEmphasis )
if( currentNode.children )
fillADFNodesWithMarkdown( nodeOrListItem, currentNode.children )
return ( currentNode.node.adfType !== 'orderedList' && currentNode.node.adfType !== 'bulletList' )
|| ( !lastListNode || currentNode.node.adfType === lastListNode.content.type )
? nodeOrListNode
: lastListNode
}, null )
}
/**
* Adding a Top-Level ADF element
*
* @param adfNodeToAttachTo {Node} ADF node to attach this element to
* @param adfType {String} ADF Type of the element we want to attach
* @param typeParams {String} extra params for special top-level nodes
*
* @returns {Node} the node added
*/
function addTypeToNode( adfNodeToAttachTo, adfType, typeParams ){
switch( adfType ) {
case "heading":
return adfNodeToAttachTo.content.add( new Heading( typeParams ) )
case "divider":
return adfNodeToAttachTo.content.add( new Rule() )
case "bulletList":
return adfNodeToAttachTo.content.add( new BulletList() )
case "orderedList": {
const orderedListNode = new OrderedList( )
if( typeParams ) orderedListNode.attrs = { order: typeParams }
return adfNodeToAttachTo.content.add( orderedListNode )
}
case "codeBlock":
return adfNodeToAttachTo.content.add( new CodeBlock( typeParams ) )
case "blockQuote":
return adfNodeToAttachTo.content.add( new BlockQuote() )
case "paragraph":
return adfNodeToAttachTo.content.add( new Paragraph() )
default:
throw 'incompatible type'
}
}
/**
* Adding a non-top-level ADF node
*
* @param nodeToAttachTo {Node} ADF Node to attach to
* @param rawText {String} text content of the node to add
*/
function attachItemNode( nodeToAttachTo, rawText ) {
const slicedInline = sliceInLineCode( rawText )
const { slicedInlineAndEmoji } = slicedInline.reduce( ( { slicedInlineAndEmoji }, currentSlice ) => {
if( !currentSlice.isMatching ){
const slicedEmoji = sliceEmoji( currentSlice.text )
return { slicedInlineAndEmoji: slicedInlineAndEmoji.concat( slicedEmoji ) }
}
slicedInlineAndEmoji.push( currentSlice )
return { slicedInlineAndEmoji }
}, { slicedInlineAndEmoji: [] } )
const { slicedInlineAndEmojiAndLink } = slicedInlineAndEmoji.reduce( ( { slicedInlineAndEmojiAndLink }, currentSlice ) => {
if( !currentSlice.isMatching ){
const slicedLink = sliceLink( currentSlice.text )
return { slicedInlineAndEmojiAndLink: slicedInlineAndEmojiAndLink.concat( slicedLink ) }
}
slicedInlineAndEmojiAndLink.push( currentSlice )
return { slicedInlineAndEmojiAndLink }
}, { slicedInlineAndEmojiAndLink: [] } )
for( const currentSlice of slicedInlineAndEmojiAndLink ) {
switch( currentSlice.type ){
case 'inline':
const inlineCodeNode = new Text( currentSlice.text, marks().code() )
nodeToAttachTo.content.add( inlineCodeNode )
break
case 'emoji':
const emojiNode = new Emoji( {shortName: currentSlice.text } )
nodeToAttachTo.content.add( emojiNode )
break
case 'link':
const linkNode = new Text( currentSlice.text,
marks().link( currentSlice.optionalText1,
currentSlice.optionalText2 ) )
nodeToAttachTo.content.add( linkNode )
break
case 'image':
const imageNode = new Text( currentSlice.text,
marks().link( currentSlice.optionalText1,
currentSlice.optionalText2 ) )
nodeToAttachTo.content.add( imageNode )
break
default:
attachTextToNodeSliceEmphasis( nodeToAttachTo, currentSlice.text )
// const textNode = new Text( currentSlice.text, marksToUse )
// nodeToAttachTo.content.add( textNode )
}
}
}
/**
* Match text content with and ADF inline type
*
* @param rawText {String} the text content to try to match
*
* @returns {String[]} the different slice matching an inline style
*/
function sliceInLineCode( rawText ){
return sliceOneMatchFromRegexp( rawText, 'inline', /(?<nonMatchBefore>[^`]*)(?:`(?<match>[^`]+)`)(?<nonMatchAfter>[^`]*)/g )
}
/**
* Match text content with and ADF emoji type
*
* @param rawText {String} the text content to try to match
*
* @returns {String[]} the different slice matching an emoji style
*/
function sliceEmoji( rawText ){
return sliceOneMatchFromRegexp( rawText, 'emoji',/(?<nonMatchBefore>[^`]*)(?::(?<match>[^`\s]+):)(?<nonMatchAfter>[^`]*)/g )
}
/**
* Match text content with and ADF link type
*
* @param rawText {String} the text content to try to match
*
* @returns {String[]} the different slice matching a link style
*/
function sliceLink( rawText ){
return sliceOneMatchFromRegexp( rawText, 'link',/(?<nonMatchBefore>[^`]*)(?:\[(?<match>[^\[\]]+)\]\((?<matchOptional>[^\(\)"]+)(?: "(?<matchOptional2>[^"]*)")?\))(?<nonMatchAfter>[^`]*)/g )
}
/**
* Match text content with and regular expression with one match
*
* @param rawText {String} the text content to try to match
* @param typeTag {String} the ADF Type to return if it matches
* @param regexpToSliceWith {RegExp} the regexp with a match group and a non-match group to use
*
* @returns {String[]} the different slice matching the specified regexp
*/
function sliceOneMatchFromRegexp( rawText, typeTag, regexpToSliceWith ){
let slicesResult = [ ]
let snippet = null
let hasAtLeastOneExpression = false
while( ( snippet = regexpToSliceWith.exec( rawText ) ) ) {
hasAtLeastOneExpression = true
if( snippet.groups.nonMatchBefore ){
slicesResult.push( { isMatching: false, text: snippet.groups.nonMatchBefore } )
}
if( snippet.groups.match ){
slicesResult.push( {
isMatching: true,
type: typeTag,
text: snippet.groups.match,
optionalText1: snippet.groups.matchOptional,
optionalText2: snippet.groups.matchOptional2
} )
}
if( snippet.groups.nonMatchAfter ){
slicesResult.push( { isMatching: false, text: snippet.groups.nonMatchAfter } )
}
}
if( !hasAtLeastOneExpression )
slicesResult.push( { isMatching: false, text: rawText } )
return slicesResult
}
/**
* Attach a raw simple text node to the parent
*
* @param nodeToAttachTo {Node} ADF node to attach to
* @param textToAttach {String} text to use for the Text node
*/
function attachTextToNodeRaw( nodeToAttachTo, textToAttach ){
const textNode = new Text( textToAttach )
nodeToAttachTo.content.add( textNode )
}
module.exports = fillADFNodesWithMarkdown
/***/ }),
/***/ 366:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
const text_1 = __webpack_require__(171);
class Heading extends index_1.TopLevelNode {
constructor(level) {
super();
this.level = level;
this.content = new index_1.ContentNode('heading');
if (level < 1 || level > 6) {
throw new Error('Level must be in the range of 1-6');
}
}
link(text, href, title) {
this.content.add(text_1.link(text, href, title));
return this;
}
text(text) {
this.content.add(text_1.plain(text));
return this;
}
toJSON() {
return Object.assign({}, this.content.toJSON(), { attrs: {
level: this.level
} });
}
}
exports.Heading = Heading;
//# sourceMappingURL=heading.js.map
/***/ }),
/***/ 371:
/***/ (function(__unusedmodule, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Media {
constructor(attrs) {
this.attrs = attrs;
}
toJSON() {
const media = {
type: 'media',
attrs: {
id: this.attrs.id,
type: this.attrs.type,
collection: this.attrs.collection
}
};
if (this.attrs.occurrenceKey) {
media.attrs.occurrenceKey = this.attrs.occurrenceKey;
}
return media;
}
}
exports.Media = Media;
//# sourceMappingURL=media.js.map
/***/ }),
/***/ 396:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class SubSup extends mark_1.Mark {
constructor(variant) {
super('subsup');
this.variant = variant;
}
toJSON() {
return {
type: this.type,
attrs: {
type: this.variant
}
};
}
}
exports.SubSup = SubSup;
//# sourceMappingURL=subsup.js.map
/***/ }),
/***/ 400:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mark_1 = __webpack_require__(711);
class Em extends mark_1.Mark {
constructor() {
super('em');
}
}
exports.Em = Em;
//# sourceMappingURL=em.js.map
/***/ }),
/***/ 451:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
class Action {
title(title) {
this.actionTitle = title;
return this;
}
target(target) {
if (!target.key) {
throw new Error('Action target key is required');
}
this.actionTarget = target;
return this;
}
parameters(parameters) {
this.actionParameters = parameters;
return this;
}
toJSON() {
const action = {};
if (this.actionTitle) {
action.title = this.actionTitle;
}
if (this.actionTarget) {
action.target = this.actionTarget;
}
if (this.actionParameters) {
action.parameters = this.actionParameters;
}
if (Object.keys(action).length < 2) {
throw new Error('Must set title and target attributes for action');
}
return action;
}
}
exports.Action = Action;
class Detail {
constructor() {
this.detailUsers = [];
}
title(text) {
this.detailTitle = text;
return this;
}
text(text) {
this.detailText = text;
return this;
}
lozenge(lozenge) {
this.detailLozenge = lozenge;
return this;
}
icon(icon) {
this.detailIcon = icon;
return this;
}
badge(badge) {
this.detailBadge = badge;
return this;
}
user(user) {
this.detailUsers.push(user);
return this;
}
toJSON() {
const detail = {};
if (this.detailTitle) {
detail.title = this.detailTitle;
}
if (this.detailText) {
detail.text = this.detailText;
}
if (this.detailIcon) {
detail.icon = this.detailIcon;
}
if (this.detailBadge) {
detail.badge = this.detailBadge;
}
if (this.detailLozenge) {
detail.lozenge = this.detailLozenge;
}
if (this.detailUsers.length > 0) {
detail.users = this.detailUsers;
}
if (Object.keys(detail).length === 0) {
throw new Error('Must at least set one attribute');
}
return detail;
}
}
exports.Detail = Detail;
class Context {
constructor(text) {
this.text = text;
}
icon(icon) {
this.contextIcon = icon;
return this;
}
toJSON() {
const context = {
text: this.text
};
if (this.contextIcon) {
context.icon = this.contextIcon;
}
return context;
}
}
exports.Context = Context;
class TitleUser {
constructor(titleUserIcon) {
this.titleUserIcon = titleUserIcon;
}
id(id) {
this.titleUserId = id;
return this;
}
toJSON() {
const titleUser = {
icon: this.titleUserIcon
};
if (this.titleUserId) {
titleUser.id = this.titleUserId;
}
return titleUser;
}
}
exports.TitleUser = TitleUser;
class ApplicationCard extends index_1.TopLevelNode {
constructor(title, text) {
super();
this.title = title;
this.text = text;
this.isCollapsible = false;
this.details = [];
this.actions = [];
}
link(url) {
this.linkUrl = url;
return this;
}
background(url) {
this.backgroundUrl = url;
return this;
}
preview(url) {
this.previewUrl = url;
return this;
}
collapsible(collapsible) {
this.isCollapsible = collapsible;
return this;
}
description(text) {
this.descriptionText = text;
return this;
}
titleUser(icon) {
const titleUser = new TitleUser(icon);
this.userInTitle = titleUser;
return titleUser;
}
detail() {
const detail = new Detail();
this.details.push(detail);
return detail;
}
action() {
const action = new Action();
this.actions.push(action);
return action;
}
context(text) {
this.cardContext = new Context(text);
return this.cardContext;
}
toJSON() {
const card = {
type: 'applicationCard',
attrs: {
text: this.text || this.title,
title: {
text: this.title
},
collapsible: this.isCollapsible
}
};
if (this.linkUrl) {
card.attrs.textUrl = this.linkUrl;
card.attrs.link = {
url: this.linkUrl
};
}
if (this.backgroundUrl) {
card.attrs.background = {
url: this.backgroundUrl
};
}
if (this.previewUrl) {
card.attrs.preview = {
url: this.previewUrl
};
}
if (this.descriptionText) {
card.attrs.description = {
text: this.descriptionText
};
}
if (this.userInTitle) {
card.attrs.title.user = this.userInTitle.toJSON();
}
if (this.details.length > 0) {
card.attrs.details = this.details.map(detail => detail.toJSON());
}
if (this.actions.length > 0) {
card.attrs.actions = this.actions.map(action => action.toJSON());
}
if (this.cardContext) {
card.attrs.context = this.cardContext.toJSON();
}
return card;
}
}
exports.ApplicationCard = ApplicationCard;
//# sourceMappingURL=application-card.js.map
/***/ }),
/***/ 492:
/***/ (function(__unusedmodule, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class ContentNode {
constructor(type, minLength = 1) {
this.type = type;
this.minLength = minLength;
this.content = [];
}
toJSON() {
if (this.content.length < this.minLength) {
throw new Error(`There must be at least ${this.minLength} content elements`);
}
return {
type: this.type,
content: this.content.map(node => node.toJSON())
};
}
add(node) {
if (!node) {
throw new Error('Illegal value');
}
this.content.push(node);
return node;
}
}
exports.ContentNode = ContentNode;
class TopLevelNode {
}
exports.TopLevelNode = TopLevelNode;
class InlineNode {
}
exports.InlineNode = InlineNode;
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 503:
/***/ (function(module, __unusedexports, __webpack_require__) {
/***********************************************************************************************************************
*
* Take any markdown (Github focussed for now) and translate it into a JIRA/Confluence compatible ADF document
*
* @author bruno.morel@b-yond.com
*
**********************************************************************************************************************/
const { Document } = __webpack_require__( 286 )
const buildIRTreeFromMarkdown = __webpack_require__( 197 )
const fillADFNodesWithMarkdown = __webpack_require__( 326 )
function translateGITHUBMarkdownToADF( markdownText ){
const textTree = buildIRTreeFromMarkdown( markdownText )
const adfRoot = new Document()
if( textTree.length > 0 )
fillADFNodesWithMarkdown( adfRoot, textTree )
return adfRoot
}
module.exports = translateGITHUBMarkdownToADF
/***/ }),
/***/ 526:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
function emoji(shortName, id, text) {
return new Emoji({ shortName, id, text });
}
exports.emoji = emoji;
class Emoji extends index_1.InlineNode {
constructor(attrs) {
super();
this.attrs = attrs;
}
toJSON() {
const emojiNode = {
type: 'emoji',
attrs: {
shortName: this.attrs.shortName
}
};
if (this.attrs.id) {
emojiNode.attrs.id = this.attrs.id;
}
if (this.attrs.text) {
emojiNode.attrs.text = this.attrs.text;
}
return emojiNode;
}
}
exports.Emoji = Emoji;
//# sourceMappingURL=emoji.js.map
/***/ }),
/***/ 561:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
const text_1 = __webpack_require__(171);
class CodeBlock extends index_1.TopLevelNode {
constructor(language) {
super();
this.language = language;
this.content = new index_1.ContentNode('codeBlock');
}
text(code) {
this.content.add(text_1.plain(code));
return this;
}
toJSON() {
const codeBlock = this.content.toJSON();
if (this.language) {
codeBlock.attrs = {
language: this.language
};
}
return codeBlock;
}
}
exports.CodeBlock = CodeBlock;
//# sourceMappingURL=code-block.js.map
/***/ }),
/***/ 566:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bullet_list_1 = __webpack_require__(849);
const index_1 = __webpack_require__(492);
const ordered_list_1 = __webpack_require__(982);
const paragraph_1 = __webpack_require__(147);
class ListItem {
constructor() {
this.content = new index_1.ContentNode('listItem');
}
paragraph() {
return this.content.add(new paragraph_1.Paragraph());
}
bulletList() {
return this.content.add(new bullet_list_1.BulletList());
}
orderedList() {
return this.content.add(new ordered_list_1.OrderedList());
}
toJSON() {
return this.content.toJSON();
}
}
exports.ListItem = ListItem;
//# sourceMappingURL=list-item.js.map
/***/ }),
/***/ 570:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = __webpack_require__(492);
function hardBreak() {
return new HardBreak();
}
exports.hardBreak = hardBreak;
class HardBreak extends index_1.InlineNode {
toJSON() {
return {
type: 'hardBreak',
attrs: {
text: '\n'
}
};
}
}
exports.HardBreak = HardBreak;
//# sourceMappingURL=hard-break.js.map
/***/ }),
/***/ 572:
/***/ (function(module) {
/**********************************************************************************************************************
*
* Markdown Parser
*
* @author bruno.morel@b-yond.com
*---------------------------------------------------------------------------------------------------------------------
*
* This translate all markdown to an intermediate representation composed as an array with
* each item containing and object with the follow properties:
* adfType : the ADF type of the line (heading, paragraph, orderedList, ...
* textToEmphasis: the actuel text (if any) attached to the element
* typeParam: any extra parameter for special types (language for codeBlock)
* nodeAttached: element to manage the special case of a codeBlock attached to a list
* textPosition: the actual start position of the text (used later for level identication)
*
**********************************************************************************************************************/
/**
* @typedef {Ob