/ *
THIS IS A GENERATED / BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
* /
'use strict' ;
var obsidian = require ( 'obsidian' ) ;
let buttonStore ;
const getStore = ( isMobile ) => isMobile ? buttonStore : JSON . parse ( localStorage . getItem ( "buttons" ) ) ;
const initializeButtonStore = ( app , storeEvents ) => {
const files = app . vault . getMarkdownFiles ( ) ;
const blocksArr = files
. map ( ( file ) => {
const cache = app . metadataCache . getFileCache ( file ) ;
return buildButtonArray ( cache , file ) ;
} )
. filter ( ( arr ) => arr !== undefined )
. flat ( ) ;
localStorage . setItem ( "buttons" , JSON . stringify ( blocksArr ) ) ;
buttonStore = blocksArr ;
storeEvents . trigger ( 'index-complete' ) ;
} ;
const addButtonToStore = ( app , file ) => {
const cache = app . metadataCache . getFileCache ( file ) ;
const buttons = buildButtonArray ( cache , file ) ;
const store = getStore ( app . isMobile ) ;
const newStore = buttons && store
? removeDuplicates ( [ ... buttons , ... store ] )
: store
? removeDuplicates ( store )
: buttons
? removeDuplicates ( buttons )
: [ ] ;
localStorage . setItem ( "buttons" , JSON . stringify ( newStore ) ) ;
buttonStore = newStore ;
} ;
const getButtonFromStore = async ( app , args ) => {
const store = getStore ( app . isMobile ) ;
args . id ;
if ( args . id ) {
const storedButton = store &&
store . filter ( ( item ) => ` button- ${ args . id } ` === item . id ) [ 0 ] ;
if ( storedButton ) {
const file = app . vault . getAbstractFileByPath ( storedButton . path ) ;
const content = await app . vault . cachedRead ( file ) ;
const contentArray = content . split ( "\n" ) ;
const button = contentArray
. slice ( storedButton . position . start . line + 1 , storedButton . position . end . line )
. join ( "\n" ) ;
const storedArgs = createArgumentObject ( button ) ;
return {
args : { ... storedArgs , ... args } ,
id : storedButton . id . split ( "button-" ) [ 1 ] ,
} ;
}
}
} ;
const getButtonById = async ( app , id ) => {
const store = getStore ( app . isMobile ) ;
const storedButton = store . filter ( ( item ) => ` button- ${ id } ` === item . id ) [ 0 ] ;
if ( storedButton ) {
const file = app . vault . getAbstractFileByPath ( storedButton . path ) ;
const content = await app . vault . cachedRead ( file ) ;
const contentArray = content . split ( "\n" ) ;
const button = contentArray
. slice ( storedButton . position . start . line + 1 , storedButton . position . end . line )
. join ( "\n" ) ;
return createArgumentObject ( button ) ;
}
} ;
const getButtonSwapById = async ( app , id ) => {
const store = getStore ( app . isMobile ) ;
const storedButton = store . filter ( ( item ) => ` button- ${ id } ` === item . id ) [ 0 ] ;
if ( storedButton ) {
return storedButton . swap ;
}
} ;
const setButtonSwapById = async ( app , id , newSwap ) => {
const store = getStore ( app . isMobile ) ;
const storedButton = store . filter ( ( item ) => ` button- ${ id } ` === item . id ) [ 0 ] ;
if ( storedButton ) {
storedButton . swap = newSwap ;
const newStore = removeDuplicates ( [ ... store , storedButton ] ) ;
localStorage . setItem ( "buttons" , JSON . stringify ( newStore ) ) ;
buttonStore = newStore ;
}
} ;
const buildButtonArray = ( cache , file ) => {
const blocks = cache && cache . blocks ;
if ( blocks ) {
const blockKeys = Array . from ( Object . keys ( blocks ) ) ;
const blockArray = blockKeys
. map ( ( key ) => blocks [ key ] )
. map ( ( obj ) => {
obj [ "path" ] = file . path ;
obj [ "swap" ] = 0 ;
return obj ;
} )
. filter ( ( block ) => block . id . includes ( "button" ) ) ;
return blockArray ;
}
} ;
function removeDuplicates ( arr ) {
return arr && arr [ 0 ]
? arr . filter ( ( v , i , a ) => a . findIndex ( ( t ) => t . id === v . id ||
( t . path === v . path &&
t . position . start . line === v . position . start . line &&
t . position . end . line === v . position . end . line ) ) === i )
: arr ;
}
function nanoid ( num ) {
let result = "" ;
const characters = "abcdefghijklmnopqrstuvwxyz0123456789" ;
const charactersLength = characters . length ;
for ( let i = 0 ; i < num ; i ++ ) {
result += characters . charAt ( Math . floor ( Math . random ( ) * charactersLength ) ) ;
}
return result ;
}
const insertButton = ( app , outputObject ) => {
const buttonArr = [ ] ;
buttonArr . push ( "```button" ) ;
outputObject . name && buttonArr . push ( ` name ${ outputObject . name } ` ) ;
outputObject . type && buttonArr . push ( ` type ${ outputObject . type } ` ) ;
outputObject . action && buttonArr . push ( ` action ${ outputObject . action } ` ) ;
outputObject . id && buttonArr . push ( ` id ${ outputObject . id } ` ) ;
outputObject . swap && buttonArr . push ( ` swap ${ outputObject . swap } ` ) ;
outputObject . remove && buttonArr . push ( ` remove ${ outputObject . remove } ` ) ;
outputObject . replace && buttonArr . push ( ` replace ${ outputObject . replace } ` ) ;
outputObject . templater === true &&
buttonArr . push ( ` templater ${ outputObject . templater } ` ) ;
outputObject . color && buttonArr . push ( ` color ${ outputObject . color } ` ) ;
outputObject . class && buttonArr . push ( ` class ${ outputObject . class } ` ) ;
buttonArr . push ( "```" ) ;
outputObject . blockId
? buttonArr . push ( ` ^button- ${ outputObject . blockId } ` )
: buttonArr . push ( ` ^button- ${ nanoid ( 4 ) } ` ) ;
const page = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
const editor = page . editor ;
editor . replaceSelection ( buttonArr . join ( "\n" ) ) ;
addButtonToStore ( app , page . file ) ;
} ;
const insertInlineButton = ( app , id ) => {
const page = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
const editor = page . editor ;
editor . replaceSelection ( ` \` button- ${ id } \` ` ) ;
} ;
const createArgumentObject = ( source ) => source . split ( "\n" ) . reduce ( ( acc , i ) => {
const split = i . split ( " " ) ;
const key = split [ 0 ] . toLowerCase ( ) ;
acc [ key ] = split . filter ( ( item ) => item !== split [ 0 ] ) . join ( " " ) . trim ( ) ;
return acc ;
} , { } ) ;
const createContentArray = async ( app ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const file = activeView . file ;
const content = await app . vault . read ( file ) ;
return { contentArray : content . split ( "\n" ) , file } ;
}
new obsidian . Notice ( "Could not get Active View" , 1000 ) ;
console . error ( "could not get active view" ) ;
} ;
const handleValueArray = ( value , callback ) => {
if ( value . includes ( "[" ) && value . includes ( "]" ) ) {
const args = value . match ( /\[(.*)\]/ ) ;
if ( args [ 1 ] ) {
const argArray = args [ 1 ] . split ( /,\s?/ ) ;
if ( argArray [ 0 ] ) {
callback ( argArray ) ;
}
}
}
} ;
function getNewArgs ( app , position ) {
const promise = new Promise ( ( resolve ) => {
setTimeout ( async ( ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
const newContent = await app . vault
. cachedRead ( activeView . file )
. then ( ( content ) => content . split ( "\n" ) ) ;
const newButton = newContent
. splice ( position . lineStart , position . lineEnd - position . lineStart )
. join ( "\n" )
. replace ( "```button" , "" )
. replace ( "```" , "" ) ;
resolve ( { args : createArgumentObject ( newButton ) } ) ;
} , 150 ) ;
} ) ;
return promise ;
}
const wrapAround = ( value , size ) => {
return ( ( value % size ) + size ) % size ;
} ;
const buttonEventListener = ( app , callback ) => {
return app . metadataCache . on ( "changed" , ( file ) => {
callback ( app , file ) ;
} ) ;
} ;
const openFileListener = ( app , storeEvents , callback ) => {
return app . workspace . on ( "file-open" , ( ) => {
callback ( app , storeEvents ) ;
} ) ;
} ;
var Mexp = function ( parsed ) {
this . value = parsed ;
} ;
Mexp . math = {
isDegree : true , // mode of calculator
acos : function ( x ) {
return ( Mexp . math . isDegree ? 180 / Math . PI * Math . acos ( x ) : Math . acos ( x ) )
} ,
add : function ( a , b ) {
return a + b
} ,
asin : function ( x ) {
return ( Mexp . math . isDegree ? 180 / Math . PI * Math . asin ( x ) : Math . asin ( x ) )
} ,
atan : function ( x ) {
return ( Mexp . math . isDegree ? 180 / Math . PI * Math . atan ( x ) : Math . atan ( x ) )
} ,
acosh : function ( x ) {
return Math . log ( x + Math . sqrt ( x * x - 1 ) )
} ,
asinh : function ( x ) {
return Math . log ( x + Math . sqrt ( x * x + 1 ) )
} ,
atanh : function ( x ) {
return Math . log ( ( 1 + x ) / ( 1 - x ) )
} ,
C : function ( n , r ) {
var pro = 1 ;
var other = n - r ;
var choice = r ;
if ( choice < other ) {
choice = other ;
other = r ;
}
for ( var i = choice + 1 ; i <= n ; i ++ ) {
pro *= i ;
}
return pro / Mexp . math . fact ( other )
} ,
changeSign : function ( x ) {
return - x
} ,
cos : function ( x ) {
if ( Mexp . math . isDegree ) x = Mexp . math . toRadian ( x ) ;
return Math . cos ( x )
} ,
cosh : function ( x ) {
return ( Math . pow ( Math . E , x ) + Math . pow ( Math . E , - 1 * x ) ) / 2
} ,
div : function ( a , b ) {
return a / b
} ,
fact : function ( n ) {
if ( n % 1 !== 0 ) return 'NaN'
var pro = 1 ;
for ( var i = 2 ; i <= n ; i ++ ) {
pro *= i ;
}
return pro
} ,
inverse : function ( x ) {
return 1 / x
} ,
log : function ( i ) {
return Math . log ( i ) / Math . log ( 10 )
} ,
mod : function ( a , b ) {
return a % b
} ,
mul : function ( a , b ) {
return a * b
} ,
P : function ( n , r ) {
var pro = 1 ;
for ( var i = Math . floor ( n ) - Math . floor ( r ) + 1 ; i <= Math . floor ( n ) ; i ++ ) {
pro *= i ;
}
return pro
} ,
Pi : function ( low , high , ex ) {
var pro = 1 ;
for ( var i = low ; i <= high ; i ++ ) {
pro *= Number ( ex . postfixEval ( {
n : i
} ) ) ;
}
return pro
} ,
pow10x : function ( e ) {
var x = 1 ;
while ( e -- ) {
x *= 10 ;
}
return x
} ,
sigma : function ( low , high , ex ) {
var sum = 0 ;
for ( var i = low ; i <= high ; i ++ ) {
sum += Number ( ex . postfixEval ( {
n : i
} ) ) ;
}
return sum
} ,
sin : function ( x ) {
if ( Mexp . math . isDegree ) x = Mexp . math . toRadian ( x ) ;
return Math . sin ( x )
} ,
sinh : function ( x ) {
return ( Math . pow ( Math . E , x ) - Math . pow ( Math . E , - 1 * x ) ) / 2
} ,
sub : function ( a , b ) {
return a - b
} ,
tan : function ( x ) {
if ( Mexp . math . isDegree ) x = Mexp . math . toRadian ( x ) ;
return Math . tan ( x )
} ,
tanh : function ( x ) {
return Mexp . sinha ( x ) / Mexp . cosha ( x )
} ,
toRadian : function ( x ) {
return x * Math . PI / 180
} ,
and : function ( a , b ) {
return a & b
}
} ;
Mexp . Exception = function ( message ) {
this . message = message ;
} ;
var math _function = Mexp ;
function inc ( arr , val ) {
for ( var i = 0 ; i < arr . length ; i ++ ) {
arr [ i ] += val ;
}
return arr
}
var tokens = [
{ token : 'sin' , show : 'sin' , type : 0 , value : math _function . math . sin } ,
{ token : 'cos' , show : 'cos' , type : 0 , value : math _function . math . cos } ,
{ token : 'tan' , show : 'tan' , type : 0 , value : math _function . math . tan } ,
{ token : 'pi' , show : 'π' , type : 3 , value : 'PI' } ,
{ token : '(' , show : '(' , type : 4 , value : '(' } ,
{ token : ')' , show : ')' , type : 5 , value : ')' } ,
{ token : 'P' , show : 'P' , type : 10 , value : math _function . math . P } ,
{ token : 'C' , show : 'C' , type : 10 , value : math _function . math . C } ,
{ token : ' ' , show : ' ' , type : 14 , value : ' ' . anchor } ,
{ token : 'asin' , show : 'asin' , type : 0 , value : math _function . math . asin } ,
{ token : 'acos' , show : 'acos' , type : 0 , value : math _function . math . acos } ,
{ token : 'atan' , show : 'atan' , type : 0 , value : math _function . math . atan } ,
{ token : '7' , show : '7' , type : 1 , value : '7' } ,
{ token : '8' , show : '8' , type : 1 , value : '8' } ,
{ token : '9' , show : '9' , type : 1 , value : '9' } ,
{ token : 'int' , show : 'Int' , type : 0 , value : Math . floor } ,
{ token : 'cosh' , show : 'cosh' , type : 0 , value : math _function . math . cosh } ,
{ token : 'acosh' , show : 'acosh' , type : 0 , value : math _function . math . acosh } ,
{ token : 'ln' , show : ' ln' , type : 0 , value : Math . log } ,
{ token : '^' , show : '^' , type : 10 , value : Math . pow } ,
{ token : 'root' , show : 'root' , type : 0 , value : Math . sqrt } ,
{ token : '4' , show : '4' , type : 1 , value : '4' } ,
{ token : '5' , show : '5' , type : 1 , value : '5' } ,
{ token : '6' , show : '6' , type : 1 , value : '6' } ,
{ token : '/' , show : '÷' , type : 2 , value : math _function . math . div } ,
{ token : '!' , show : '!' , type : 7 , value : math _function . math . fact } ,
{ token : 'tanh' , show : 'tanh' , type : 0 , value : math _function . math . tanh } ,
{ token : 'atanh' , show : 'atanh' , type : 0 , value : math _function . math . atanh } ,
{ token : 'Mod' , show : ' Mod ' , type : 2 , value : math _function . math . mod } ,
{ token : '1' , show : '1' , type : 1 , value : '1' } ,
{ token : '2' , show : '2' , type : 1 , value : '2' } ,
{ token : '3' , show : '3' , type : 1 , value : '3' } ,
{ token : '*' , show : '×' , type : 2 , value : math _function . math . mul } ,
{ token : 'sinh' , show : 'sinh' , type : 0 , value : math _function . math . sinh } ,
{ token : 'asinh' , show : 'asinh' , type : 0 , value : math _function . math . asinh } ,
{ token : 'e' , show : 'e' , type : 3 , value : 'E' } ,
{ token : 'log' , show : ' log' , type : 0 , value : math _function . math . log } ,
{ token : '0' , show : '0' , type : 1 , value : '0' } ,
{ token : '.' , show : '.' , type : 6 , value : '.' } ,
{ token : '+' , show : '+' , type : 9 , value : math _function . math . add } ,
{ token : '-' , show : '-' , type : 9 , value : math _function . math . sub } ,
{ token : ',' , show : ',' , type : 11 , value : ',' } ,
{ token : 'Sigma' , show : 'Σ' , type : 12 , value : math _function . math . sigma } ,
{ token : 'n' , show : 'n' , type : 13 , value : 'n' } ,
{ token : 'Pi' , show : 'Π' , type : 12 , value : math _function . math . Pi } ,
{ token : 'pow' , show : 'pow' , type : 8 , value : Math . pow , numberOfArguments : 2 } ,
{ token : '&' , show : '&' , type : 9 , value : math _function . math . and } ,
] ;
var preced = {
0 : 11 ,
1 : 0 ,
2 : 3 ,
3 : 0 ,
4 : 0 ,
5 : 0 ,
6 : 0 ,
7 : 11 ,
8 : 11 ,
9 : 1 ,
10 : 10 ,
11 : 0 ,
12 : 11 ,
13 : 0 ,
14 : - 1 ,
15 : 11 , // will be filtered after lexer
} ; // stores precedence by types
for ( var i = 0 ; i < tokens . length ; i ++ ) {
tokens [ i ] . precedence = preced [ tokens [ i ] . type ] ;
}
var type0 = {
0 : true ,
1 : true ,
3 : true ,
4 : true ,
6 : true ,
8 : true ,
9 : true ,
12 : true ,
13 : true ,
14 : true ,
15 : true ,
} ; // type2:true,type4:true,type9:true,type11:true,type21:true,type22
var type1 = {
0 : true ,
1 : true ,
2 : true ,
3 : true ,
4 : true ,
5 : true ,
6 : true ,
7 : true ,
8 : true ,
9 : true ,
10 : true ,
11 : true ,
12 : true ,
13 : true ,
15 : true ,
} ; // type3:true,type5:true,type7:true,type23
var type1Asterick = {
0 : true ,
3 : true ,
4 : true ,
8 : true ,
12 : true ,
13 : true ,
15 : true ,
} ;
var empty = { } ;
var type3Asterick = {
0 : true ,
1 : true ,
3 : true ,
4 : true ,
6 : true ,
8 : true ,
12 : true ,
13 : true ,
15 : true ,
} ; // type_5:true,type_7:true,type_23
var type6 = {
1 : true ,
} ;
var newAr = [
[ ] ,
[
'1' ,
'2' ,
'3' ,
'7' ,
'8' ,
'9' ,
'4' ,
'5' ,
'6' ,
'+' ,
'-' ,
'*' ,
'/' ,
'(' ,
')' ,
'^' ,
'!' ,
'P' ,
'C' ,
'e' ,
'0' ,
'.' ,
',' ,
'n' ,
' ' ,
'&' ,
] ,
[ 'pi' , 'ln' , 'Pi' ] ,
[ 'sin' , 'cos' , 'tan' , 'Del' , 'int' , 'Mod' , 'log' , 'pow' ] ,
[ 'asin' , 'acos' , 'atan' , 'cosh' , 'root' , 'tanh' , 'sinh' ] ,
[ 'acosh' , 'atanh' , 'asinh' , 'Sigma' ] ,
] ;
function match ( str1 , str2 , i , x ) {
for ( var f = 0 ; f < x ; f ++ ) {
if ( str1 [ i + f ] !== str2 [ f ] ) {
return false
}
}
return true
}
math _function . tokenTypes = {
FUNCTION _WITH _ONE _ARG : 0 ,
NUMBER : 1 ,
BINARY _OPERATOR _HIGH _PRECENDENCE : 2 ,
CONSTANT : 3 ,
OPENING _PARENTHESIS : 4 ,
CLOSING _PARENTHESIS : 5 ,
DECIMAL : 6 ,
POSTFIX _FUNCTION _WITH _ONE _ARG : 7 ,
FUNCTION _WITH _N _ARGS : 8 ,
BINARY _OPERATOR _LOW _PRECENDENCE : 9 ,
BINARY _OPERATOR _PERMUTATION : 10 ,
COMMA : 11 ,
EVALUATED _FUNCTION : 12 ,
EVALUATED _FUNCTION _PARAMETER : 13 ,
SPACE : 14 ,
} ;
/ * *
0 : function with syntax function _name ( Maths _exp )
1 : numbers
2 : binary operators like * / M o d l e f t a s s o c i a t e a n d s a m e p r e c e d e n c e
3 : Math constant values like e , pi , Cruncher ans
4 : opening bracket
5 : closing bracket
6 : decimal
7 : function with syntax ( Math _exp ) function _name
8 : function with syntax function _name ( Math _exp1 , Math _exp2 )
9 : binary operator like + , -
10 : binary operator like P C or ^
11 : ,
12 : function with , seperated three parameters and third parameter is a string that will be mexp string
13 : variable of Sigma function
* /
math _function . addToken = function ( newTokens ) {
for ( var i = 0 ; i < newTokens . length ; i ++ ) {
var x = newTokens [ i ] . token . length ;
var temp = - 1 ;
if ( newTokens [ i ] . type === math _function . tokenTypes . FUNCTION _WITH _N _ARGS && newTokens [ i ] . numberOfArguments === undefined ) {
newTokens [ i ] . numberOfArguments = 2 ;
}
// newAr is a specially designed data structure index of 1d array = length of tokens
newAr [ x ] = newAr [ x ] || [ ] ;
for ( var y = 0 ; y < newAr [ x ] . length ; y ++ ) {
if ( newTokens [ i ] . token === newAr [ x ] [ y ] ) {
temp = indexOfToken ( newAr [ x ] [ y ] , tokens ) ;
break
}
}
if ( temp === - 1 ) {
tokens . push ( newTokens [ i ] ) ;
newTokens [ i ] . precedence = preced [ newTokens [ i ] . type ] ;
if ( newAr . length <= newTokens [ i ] . token . length ) {
newAr [ newTokens [ i ] . token . length ] = [ ] ;
}
newAr [ newTokens [ i ] . token . length ] . push ( newTokens [ i ] . token ) ;
} else {
// overwrite
tokens [ temp ] = newTokens [ i ] ;
newTokens [ i ] . precedence = preced [ newTokens [ i ] . type ] ;
}
}
} ;
function indexOfToken ( key , tokens ) {
for ( var search = 0 ; search < tokens . length ; search ++ ) {
if ( tokens [ search ] . token === key ) return search
}
return - 1
}
function tokenize ( string ) {
var nodes = [ ] ;
var length = string . length ;
var key , x , y ;
for ( var i = 0 ; i < length ; i ++ ) {
if ( i < length - 1 && string [ i ] === ' ' && string [ i + 1 ] === ' ' ) {
continue
}
key = '' ;
for ( x = string . length - i > newAr . length - 2 ? newAr . length - 1 : string . length - i ; x > 0 ; x -- ) {
if ( newAr [ x ] === undefined ) continue
for ( y = 0 ; y < newAr [ x ] . length ; y ++ ) {
if ( match ( string , newAr [ x ] [ y ] , i , x ) ) {
key = newAr [ x ] [ y ] ;
y = newAr [ x ] . length ;
x = 0 ;
}
}
}
i += key . length - 1 ;
if ( key === '' ) {
throw new math _function . Exception ( "Can't understand after " + string . slice ( i ) )
}
nodes . push ( tokens [ indexOfToken ( key , tokens ) ] ) ;
}
return nodes
}
var changeSignObj = {
value : math _function . math . changeSign ,
type : 0 ,
pre : 21 ,
show : '-' ,
} ;
var closingParObj = {
value : ')' ,
show : ')' ,
type : 5 ,
pre : 0 ,
} ;
var openingParObj = {
value : '(' ,
type : 4 ,
pre : 0 ,
show : '(' ,
} ;
math _function . lex = function ( inp , tokens ) {
var str = [ openingParObj ] ;
var ptc = [ ] ; // Parenthesis to close at the beginning is after one token
var inpStr = inp ;
var allowed = type0 ;
var bracToClose = 0 ;
var asterick = empty ;
var prevKey = '' ;
var i ;
if ( typeof tokens !== 'undefined' ) {
math _function . addToken ( tokens ) ;
}
var obj = { } ;
var nodes = tokenize ( inpStr ) ;
for ( i = 0 ; i < nodes . length ; i ++ ) {
var node = nodes [ i ] ;
if ( node . type === 14 ) {
if (
i > 0 &&
i < nodes . length - 1 &&
nodes [ i + 1 ] . type === 1 &&
( nodes [ i - 1 ] . type === 1 || nodes [ i - 1 ] . type === 6 )
) {
throw new math _function . Exception ( 'Unexpected Space' )
}
continue
}
var cToken = node . token ;
var cType = node . type ;
var cEv = node . value ;
var cPre = node . precedence ;
var cShow = node . show ;
var pre = str [ str . length - 1 ] ;
var j ;
for ( j = ptc . length ; j -- ; ) {
// loop over ptc
if ( ptc [ j ] === 0 ) {
if ( [ 0 , 2 , 3 , 4 , 5 , 9 , 11 , 12 , 13 ] . indexOf ( cType ) !== - 1 ) {
if ( allowed [ cType ] !== true ) {
throw new math _function . Exception ( cToken + ' is not allowed after ' + prevKey )
}
str . push ( closingParObj ) ;
allowed = type1 ;
asterick = type3Asterick ;
ptc . pop ( ) ;
}
} else break
}
if ( allowed [ cType ] !== true ) {
throw new math _function . Exception ( cToken + ' is not allowed after ' + prevKey )
}
if ( asterick [ cType ] === true ) {
cType = 2 ;
cEv = math _function . math . mul ;
cShow = '×' ;
cPre = 3 ;
i = i - 1 ;
}
obj = {
value : cEv ,
type : cType ,
pre : cPre ,
show : cShow ,
numberOfArguments : node . numberOfArguments ,
} ;
if ( cType === 0 ) {
allowed = type0 ;
asterick = empty ;
inc ( ptc , 2 ) ;
str . push ( obj ) ;
if ( nodes [ i + 1 ] . type !== 4 ) {
str . push ( openingParObj ) ;
ptc . push ( 2 ) ;
}
// bracToClose++
} else if ( cType === 1 ) {
if ( pre . type === 1 ) {
pre . value += cEv ;
inc ( ptc , 1 ) ;
} else {
str . push ( obj ) ;
}
allowed = type1 ;
asterick = type1Asterick ;
} else if ( cType === 2 ) {
allowed = type0 ;
asterick = empty ;
inc ( ptc , 2 ) ;
str . push ( obj ) ;
} else if ( cType === 3 ) {
// constant
str . push ( obj ) ;
allowed = type1 ;
asterick = type3Asterick ;
} else if ( cType === 4 ) {
inc ( ptc , 1 ) ;
bracToClose ++ ;
allowed = type0 ;
asterick = empty ;
str . push ( obj ) ;
} else if ( cType === 5 ) {
if ( ! bracToClose ) {
throw new math _function . Exception ( 'Closing parenthesis are more than opening one, wait What!!!' )
}
bracToClose -- ;
allowed = type1 ;
asterick = type3Asterick ;
str . push ( obj ) ;
inc ( ptc , 1 ) ;
} else if ( cType === 6 ) {
if ( pre . hasDec ) {
throw new math _function . Exception ( 'Two decimals are not allowed in one number' )
}
if ( pre . type !== 1 ) {
pre = {
value : 0 ,
type : 1 ,
pre : 0 ,
} ; // pre needs to be changed as it will the last value now to be safe in later code
str . push ( pre ) ;
// inc(ptc, 1)
}
allowed = type6 ;
inc ( ptc , 1 ) ;
asterick = empty ;
pre . value += cEv ;
pre . hasDec = true ;
} else if ( cType === 7 ) {
allowed = type1 ;
asterick = type3Asterick ;
inc ( ptc , 1 ) ;
str . push ( obj ) ;
}
if ( cType === 8 ) {
allowed = type0 ;
asterick = empty ;
inc ( ptc , node . numberOfArguments + 2 ) ;
str . push ( obj ) ;
// str.push(openingParObj)
if ( nodes [ i + 1 ] . type !== 4 ) {
str . push ( openingParObj ) ;
ptc . push ( node . numberOfArguments + 2 ) ;
}
} else if ( cType === 9 ) {
if ( pre . type === 9 ) {
if ( pre . value === math _function . math . add ) {
pre . value = cEv ;
pre . show = cShow ;
inc ( ptc , 1 ) ;
} else if ( pre . value === math _function . math . sub && cShow === '-' ) {
pre . value = math _function . math . add ;
pre . show = '+' ;
inc ( ptc , 1 ) ;
}
} else if ( pre . type !== 5 && pre . type !== 7 && pre . type !== 1 && pre . type !== 3 && pre . type !== 13 ) {
// changesign only when negative is found
if ( cToken === '-' ) {
// do nothing for + token
// don't add with the above if statement as that will run the else statement of parent if on Ctoken +
allowed = type0 ;
asterick = empty ;
inc ( ptc , 2 ) . push ( 2 ) ;
str . push ( changeSignObj ) ;
str . push ( openingParObj ) ;
}
} else {
str . push ( obj ) ;
inc ( ptc , 2 ) ;
}
allowed = type0 ;
asterick = empty ;
} else if ( cType === 10 ) {
allowed = type0 ;
asterick = empty ;
inc ( ptc , 2 ) ;
str . push ( obj ) ;
} else if ( cType === 11 ) {
allowed = type0 ;
asterick = empty ;
str . push ( obj ) ;
} else if ( cType === 12 ) {
allowed = type0 ;
asterick = empty ;
inc ( ptc , 6 ) ;
str . push ( obj ) ;
if ( nodes [ i + 1 ] . type !== 4 ) {
str . push ( openingParObj ) ;
ptc . push ( 6 ) ;
}
} else if ( cType === 13 ) {
allowed = type1 ;
asterick = type3Asterick ;
str . push ( obj ) ;
}
inc ( ptc , - 1 ) ;
prevKey = cToken ;
}
for ( j = ptc . length ; j -- ; ) {
// loop over ptc
str . push ( closingParObj ) ;
}
if ( allowed [ 5 ] !== true ) {
throw new math _function . Exception ( 'complete the expression' )
}
while ( bracToClose -- ) {
str . push ( closingParObj ) ;
}
str . push ( closingParObj ) ;
// console.log(str);
return new math _function ( str )
} ;
var lexer = math _function ;
lexer . prototype . toPostfix = function ( ) {
var post = [ ] , elem , popped , prep , pre , ele ;
var stack = [ { value : "(" , type : 4 , pre : 0 } ] ;
var arr = this . value ;
for ( var i = 1 ; i < arr . length ; i ++ ) {
if ( arr [ i ] . type === 1 || arr [ i ] . type === 3 || arr [ i ] . type === 13 ) { //if token is number,constant,or n(which is also a special constant in our case)
if ( arr [ i ] . type === 1 )
arr [ i ] . value = Number ( arr [ i ] . value ) ;
post . push ( arr [ i ] ) ;
}
else if ( arr [ i ] . type === 4 ) {
stack . push ( arr [ i ] ) ;
}
else if ( arr [ i ] . type === 5 ) {
while ( ( popped = stack . pop ( ) ) . type !== 4 ) {
post . push ( popped ) ;
}
}
else if ( arr [ i ] . type === 11 ) {
while ( ( popped = stack . pop ( ) ) . type !== 4 ) {
post . push ( popped ) ;
}
stack . push ( popped ) ;
}
else {
elem = arr [ i ] ;
pre = elem . pre ;
ele = stack [ stack . length - 1 ] ;
prep = ele . pre ;
var flag = ele . value == 'Math.pow' && elem . value == 'Math.pow' ;
if ( pre > prep ) stack . push ( elem ) ;
else {
while ( prep >= pre && ! flag || flag && pre < prep ) {
popped = stack . pop ( ) ;
ele = stack [ stack . length - 1 ] ;
post . push ( popped ) ;
prep = ele . pre ;
flag = elem . value == 'Math.pow' && ele . value == 'Math.pow' ;
}
stack . push ( elem ) ;
}
}
}
return new lexer ( post ) ;
} ;
var postfix = lexer ;
postfix . prototype . postfixEval = function ( UserDefined ) {
UserDefined = UserDefined || { } ;
UserDefined . PI = Math . PI ;
UserDefined . E = Math . E ;
var stack = [ ] ,
pop1 ,
pop2 ,
pop3 ;
var arr = this . value ;
var bool = typeof UserDefined . n !== 'undefined' ;
for ( var i = 0 ; i < arr . length ; i ++ ) {
if ( arr [ i ] . type === 1 ) {
stack . push ( { value : arr [ i ] . value , type : 1 } ) ;
} else if ( arr [ i ] . type === 3 ) {
stack . push ( { value : UserDefined [ arr [ i ] . value ] , type : 1 } ) ;
} else if ( arr [ i ] . type === 0 ) {
if ( typeof stack [ stack . length - 1 ] . type === 'undefined' ) {
stack [ stack . length - 1 ] . value . push ( arr [ i ] ) ;
} else stack [ stack . length - 1 ] . value = arr [ i ] . value ( stack [ stack . length - 1 ] . value ) ;
} else if ( arr [ i ] . type === 7 ) {
if ( typeof stack [ stack . length - 1 ] . type === 'undefined' ) {
stack [ stack . length - 1 ] . value . push ( arr [ i ] ) ;
} else stack [ stack . length - 1 ] . value = arr [ i ] . value ( stack [ stack . length - 1 ] . value ) ;
} else if ( arr [ i ] . type === 8 ) {
var popped = [ ] ;
for ( var x = 0 ; x < arr [ i ] . numberOfArguments ; x ++ ) {
popped . push ( stack . pop ( ) . value ) ;
}
stack . push ( { type : 1 , value : arr [ i ] . value . apply ( arr [ i ] , popped . reverse ( ) ) } ) ;
} else if ( arr [ i ] . type === 10 ) {
pop1 = stack . pop ( ) ;
pop2 = stack . pop ( ) ;
if ( typeof pop2 . type === 'undefined' ) {
pop2 . value = pop2 . concat ( pop1 ) ;
pop2 . value . push ( arr [ i ] ) ;
stack . push ( pop2 ) ;
} else if ( typeof pop1 . type === 'undefined' ) {
pop1 . unshift ( pop2 ) ;
pop1 . push ( arr [ i ] ) ;
stack . push ( pop1 ) ;
} else {
stack . push ( { type : 1 , value : arr [ i ] . value ( pop2 . value , pop1 . value ) } ) ;
}
} else if ( arr [ i ] . type === 2 || arr [ i ] . type === 9 ) {
pop1 = stack . pop ( ) ;
pop2 = stack . pop ( ) ;
if ( typeof pop2 . type === 'undefined' ) {
pop2 = pop2 . concat ( pop1 ) ;
pop2 . push ( arr [ i ] ) ;
stack . push ( pop2 ) ;
} else if ( typeof pop1 . type === 'undefined' ) {
pop1 . unshift ( pop2 ) ;
pop1 . push ( arr [ i ] ) ;
stack . push ( pop1 ) ;
} else {
stack . push ( { type : 1 , value : arr [ i ] . value ( pop2 . value , pop1 . value ) } ) ;
}
} else if ( arr [ i ] . type === 12 ) {
pop1 = stack . pop ( ) ;
if ( typeof pop1 . type !== 'undefined' ) {
pop1 = [ pop1 ] ;
}
pop2 = stack . pop ( ) ;
pop3 = stack . pop ( ) ;
stack . push ( { type : 1 , value : arr [ i ] . value ( pop3 . value , pop2 . value , new postfix ( pop1 ) ) } ) ;
} else if ( arr [ i ] . type === 13 ) {
if ( bool ) {
stack . push ( { value : UserDefined [ arr [ i ] . value ] , type : 3 } ) ;
} else stack . push ( [ arr [ i ] ] ) ;
}
}
if ( stack . length > 1 ) {
throw new postfix . Exception ( 'Uncaught Syntax error' )
}
return stack [ 0 ] . value > 1000000000000000 ? 'Infinity' : parseFloat ( stack [ 0 ] . value . toFixed ( 15 ) )
} ;
postfix . eval = function ( str , tokens , obj ) {
if ( typeof tokens === 'undefined' ) {
return this . lex ( str ) . toPostfix ( ) . postfixEval ( )
} else if ( typeof obj === 'undefined' ) {
if ( typeof tokens . length !== 'undefined' ) return this . lex ( str , tokens ) . toPostfix ( ) . postfixEval ( )
else return this . lex ( str ) . toPostfix ( ) . postfixEval ( tokens )
} else return this . lex ( str , tokens ) . toPostfix ( ) . postfixEval ( obj )
} ;
var postfix _evaluator = postfix ;
postfix _evaluator . prototype . formulaEval = function ( ) {
var pop1 , pop2 , pop3 ;
var disp = [ ] ;
var arr = this . value ;
for ( var i = 0 ; i < arr . length ; i ++ ) {
if ( arr [ i ] . type === 1 || arr [ i ] . type === 3 ) {
disp . push ( { value : arr [ i ] . type === 3 ? arr [ i ] . show : arr [ i ] . value , type : 1 } ) ;
}
else if ( arr [ i ] . type === 13 ) {
disp . push ( { value : arr [ i ] . show , type : 1 } ) ;
}
else if ( arr [ i ] . type === 0 ) {
disp [ disp . length - 1 ] = { value : arr [ i ] . show + ( arr [ i ] . show != "-" ? "(" : "" ) + disp [ disp . length - 1 ] . value + ( arr [ i ] . show != "-" ? ")" : "" ) , type : 0 } ;
}
else if ( arr [ i ] . type === 7 ) {
disp [ disp . length - 1 ] = { value : ( disp [ disp . length - 1 ] . type != 1 ? "(" : "" ) + disp [ disp . length - 1 ] . value + ( disp [ disp . length - 1 ] . type != 1 ? ")" : "" ) + arr [ i ] . show , type : 7 } ;
}
else if ( arr [ i ] . type === 10 ) {
pop1 = disp . pop ( ) ;
pop2 = disp . pop ( ) ;
if ( arr [ i ] . show === 'P' || arr [ i ] . show === 'C' ) disp . push ( { value : "<sup>" + pop2 . value + "</sup>" + arr [ i ] . show + "<sub>" + pop1 . value + "</sub>" , type : 10 } ) ;
else disp . push ( { value : ( pop2 . type != 1 ? "(" : "" ) + pop2 . value + ( pop2 . type != 1 ? ")" : "" ) + "<sup>" + pop1 . value + "</sup>" , type : 1 } ) ;
}
else if ( arr [ i ] . type === 2 || arr [ i ] . type === 9 ) {
pop1 = disp . pop ( ) ;
pop2 = disp . pop ( ) ;
disp . push ( { value : ( pop2 . type != 1 ? "(" : "" ) + pop2 . value + ( pop2 . type != 1 ? ")" : "" ) + arr [ i ] . show + ( pop1 . type != 1 ? "(" : "" ) + pop1 . value + ( pop1 . type != 1 ? ")" : "" ) , type : arr [ i ] . type } ) ;
}
else if ( arr [ i ] . type === 12 ) {
pop1 = disp . pop ( ) ;
pop2 = disp . pop ( ) ;
pop3 = disp . pop ( ) ;
disp . push ( { value : arr [ i ] . show + "(" + pop3 . value + "," + pop2 . value + "," + pop1 . value + ")" , type : 12 } ) ;
}
}
return disp [ 0 ] . value ;
} ;
var formula _evaluator = postfix _evaluator ;
const removeButton = async ( app , remove , lineStart , lineEnd ) => {
const { contentArray , file } = await createContentArray ( app ) ;
const store = getStore ( app . isMobile ) ;
if ( remove === "true" ) {
const numberOfItems = lineEnd - lineStart ;
contentArray . splice ( lineStart , numberOfItems + 1 ) ;
if ( contentArray [ lineStart ] &&
contentArray [ lineStart ] . includes ( "^button-" ) ) {
contentArray . splice ( lineStart , 1 ) ;
}
const content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
if ( lineStart === lineEnd ) {
contentArray . splice ( lineStart , 1 ) ;
const content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
else {
handleValueArray ( remove , async ( argArray ) => {
const buttons = store &&
store . filter ( ( item ) => {
let exists ;
argArray . forEach ( ( arg ) => {
if ( item . id === ` button- ${ arg } ` && item . path === file . path ) {
exists = true ;
}
} ) ;
return exists ;
} ) ;
if ( buttons [ 0 ] ) {
let offset = 0 ;
buttons . forEach ( ( button ) => {
const start = button . position . start . line - offset ;
const numLines = button . position . end . line - button . position . start . line ;
contentArray . splice ( start , numLines + 2 ) ;
offset += numLines + 2 ;
} ) ;
const content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
} ) ;
}
} ;
const removeSection = async ( app , section ) => {
const { contentArray , file } = await createContentArray ( app ) ;
if ( section . includes ( "[" ) && section . includes ( "]" ) ) {
const args = section . match ( /\[(.*)\]/ ) ;
if ( args [ 1 ] ) {
const argArray = args [ 1 ] . split ( /,\s?/ ) ;
if ( argArray [ 0 ] ) {
const start = parseInt ( argArray [ 0 ] ) - 1 ;
const end = parseInt ( argArray [ 1 ] ) ;
const numLines = end - start ;
contentArray . splice ( start , numLines ) ;
const content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
}
}
} ;
const prependContent = async ( app , insert , lineStart ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const file = activeView . file ;
let content = await app . vault . read ( file ) ;
const contentArray = content . split ( "\n" ) ;
contentArray . splice ( lineStart , 0 , insert ) ;
content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
else {
new obsidian . Notice ( "There was an issue prepending content, please try again" , 2000 ) ;
}
} ;
const appendContent = async ( app , insert , lineEnd ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const file = activeView . file ;
let content = await app . vault . read ( file ) ;
const contentArray = content . split ( "\n" ) ;
let insertionPoint ;
if ( contentArray [ lineEnd + 1 ] &&
contentArray [ lineEnd + 1 ] . includes ( "^button" ) ) {
insertionPoint = lineEnd + 2 ;
insert = ` \n ${ insert } ` ;
}
else {
insertionPoint = lineEnd + 1 ;
}
contentArray . splice ( insertionPoint , 0 , ` ${ insert } ` ) ;
content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
else {
new obsidian . Notice ( "There was an issue appending content, please try again" , 2000 ) ;
}
} ;
const addContentAtLine = async ( app , insert , type ) => {
const lineNumber = type . match ( /(\d+)/g ) ;
if ( lineNumber [ 0 ] ) {
const insertionPoint = parseInt ( lineNumber [ 0 ] ) - 1 ;
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const file = activeView . file ;
let content = await app . vault . read ( file ) ;
const contentArray = content . split ( "\n" ) ;
contentArray . splice ( insertionPoint , 0 , ` ${ insert } ` ) ;
content = contentArray . join ( "\n" ) ;
await app . vault . modify ( file , content ) ;
}
}
else {
new obsidian . Notice ( "There was an issue adding content, please try again" , 2000 ) ;
}
} ;
const createNote = async ( app , content , type ) => {
const path = type . match ( /\(([\s\S]*?),?\s?(split)?\)/ ) ;
if ( path ) {
try {
await app . vault . create ( ` ${ path [ 1 ] } .md ` , content ) ;
const file = app . vault . getAbstractFileByPath ( ` ${ path [ 1 ] } .md ` ) ;
if ( path [ 2 ] ) {
await app . workspace . splitActiveLeaf ( ) . openFile ( file ) ;
}
else {
app . workspace . activeLeaf . openFile ( file ) ;
}
}
catch ( e ) {
new obsidian . Notice ( "There was an error! Maybe the file already exists?" , 2000 ) ;
}
}
else {
new obsidian . Notice ( ` couldn't parse the path! ` , 2000 ) ;
}
} ;
const getButtonPosition = ( content , args ) => {
let finalPosition ;
const possiblePositions = [ ] ;
let possiblePosition = { lineStart : 0 , lineEnd : 0 } ;
const contentArray = content . split ( "\n" ) ;
let open = false ;
contentArray . forEach ( ( item , index ) => {
if ( item . includes ( "```" ) ) {
if ( open === false ) {
possiblePosition . lineStart = index ;
open = true ;
}
else {
possiblePosition . lineEnd = index ;
possiblePositions . push ( possiblePosition ) ;
possiblePosition = { lineStart : 0 , lineEnd : 0 } ;
open = false ;
}
}
} ) ;
possiblePositions . forEach ( ( position ) => {
const codeblock = contentArray
. slice ( position . lineStart , position . lineEnd + 1 )
. join ( "\n" ) ;
if ( codeblock . includes ( "button" ) && codeblock . includes ( args . name ) ) {
finalPosition = position ;
}
} ) ;
return finalPosition ;
} ;
const getInlineButtonPosition = async ( app , id ) => {
const content = await createContentArray ( app ) ;
const position = { lineStart : 0 , lineEnd : 0 } ;
content . contentArray
. map ( ( line ) => line . split ( " " ) )
. forEach ( ( words , index ) => {
words . forEach ( ( word ) => {
if ( word . startsWith ( "`button" ) ) {
if ( word === ` \` button- ${ id } \` ` ) {
position . lineStart = index ;
position . lineEnd = index ;
}
}
} ) ;
} ) ;
return position ;
} ;
const findNumber = async ( app , lineNumber ) => {
const content = await createContentArray ( app ) ;
const value = [ ] ;
content . contentArray . forEach ( ( line , index ) => {
if ( index === lineNumber - 1 ) {
value . push ( line ) ;
}
} ) ;
const convertWords = value
. join ( "" )
. replace ( "plus" , "+" )
. replace ( "minus" , "-" )
. replace ( "times" , "*" )
. replace ( /divide(d)?(\sby)?/g , "/" ) ;
const numbers = convertWords . replace ( /\s/g , "" ) . match ( /[^\w:]*?\d+?/g ) ;
return numbers ;
} ;
const calculate = async ( app , { action } , position ) => {
let equation = action ;
const variables = action . match ( /\$[0-9]*/g ) ;
if ( variables ) {
const output = variables . map ( async ( value ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const lineNumber = parseInt ( value . substring ( 1 ) ) ;
const numbers = await findNumber ( app , lineNumber ) ;
return { variable : value , numbers } ;
}
else {
new obsidian . Notice ( ` couldn't read file ` , 2000 ) ;
}
} ) ;
const resolved = await Promise . all ( output ) ;
resolved . forEach ( ( term ) => {
if ( term . numbers ) {
equation = equation . replace ( term . variable , term . numbers . join ( "" ) ) ;
}
else {
new obsidian . Notice ( "Check the line number in your calculate button" , 3000 ) ;
equation = undefined ;
}
} ) ;
}
const fun = equation && formula _evaluator . eval ( equation ) ;
fun && appendContent ( app , ` Result: ${ fun } ` , position . lineEnd ) ;
} ;
const remove = ( app , { remove } , { lineStart , lineEnd } ) => {
setTimeout ( ( ) => removeButton ( app , remove , lineStart , lineEnd ) , 1000 ) ;
} ;
const replace = ( app , { replace } ) => {
removeSection ( app , replace ) ;
} ;
const text = async ( app , args , position ) => {
// prepend template above the button
if ( args . type . includes ( "prepend" ) ) {
prependContent ( app , args . action , position . lineStart ) ;
}
// append template below the button
if ( args . type . includes ( "append" ) ) {
appendContent ( app , args . action , position . lineEnd ) ;
}
if ( args . type . includes ( "note" ) ) {
createNote ( app , args . action , args . type ) ;
}
if ( args . type . includes ( "line" ) ) {
addContentAtLine ( app , args . action , args . type ) ;
}
} ;
const template = async ( app , args , position ) => {
const templatesEnabled = app . internalPlugins . plugins . templates . enabled ;
const templaterPluginEnabled = app . plugins . plugins [ "templater-obsidian" ] ;
// only run if templates plugin is enabled
if ( templatesEnabled || templaterPluginEnabled ) {
const folders = [
templatesEnabled && app . internalPlugins . plugins . templates . instance . options . folder ? . toLowerCase ( ) ,
templaterPluginEnabled && app . plugins ? . plugins [ "templater-obsidian" ] ? . settings . template _folder ? . toLowerCase ( ) ,
templaterPluginEnabled && app . plugins ? . plugins [ "templater-obsidian" ] ? . settings . templates _folder ? . toLowerCase ( ) ,
] . filter ( ( folder ) => folder ) ;
const templateFile = args . action . toLowerCase ( ) ;
const allFiles = app . vault . getFiles ( ) ;
const file = allFiles . filter ( ( file ) => {
let found = false ;
folders [ 0 ] &&
folders . forEach ( ( folder ) => {
if ( file . path . toLowerCase ( ) === ` ${ folder } / ${ templateFile } .md ` ) {
found = true ;
}
} ) ;
return found ;
} ) [ 0 ] ;
if ( file ) {
const content = await app . vault . read ( file ) ;
// prepend template above the button
if ( args . type . includes ( "prepend" ) ) {
prependContent ( app , content , position . lineStart ) ;
setTimeout ( ( ) => app . commands . executeCommandById ( "templater-obsidian:replace-in-file-templater" ) , 100 ) ;
}
// append template below the button
if ( args . type . includes ( "append" ) ) {
appendContent ( app , content , position . lineEnd ) ;
setTimeout ( ( ) => app . commands . executeCommandById ( "templater-obsidian:replace-in-file-templater" ) , 100 ) ;
}
if ( args . type . includes ( "note" ) ) {
createNote ( app , content , args . type ) ;
}
if ( args . type . includes ( "line" ) ) {
addContentAtLine ( app , content , args . type ) ;
setTimeout ( ( ) => app . commands . executeCommandById ( "templater-obsidian:replace-in-file-templater" ) , 100 ) ;
}
}
else {
new obsidian . Notice ( ` Couldn't find the specified template, please check and try again ` , 2000 ) ;
}
}
else {
new obsidian . Notice ( "You need to have the Templates or Templater plugin enabled and Template folder defined" , 2000 ) ;
}
} ;
const link = ( { action } ) => {
const link = action . trim ( ) ;
window . open ( link ) ;
} ;
const command = ( app , { action } ) => {
const allCommands = app . commands . listCommands ( ) ;
const command = allCommands . filter ( ( command ) => command . name . toUpperCase ( ) === action . toUpperCase ( ) . trim ( ) ) [ 0 ] ;
app . commands . executeCommandById ( command . id ) ;
} ;
const swap = async ( app , swap , id , inline , file ) => {
handleValueArray ( swap , async ( argArray ) => {
const swap = await getButtonSwapById ( app , id ) ;
const newSwap = swap + 1 > argArray . length - 1 ? 0 : swap + 1 ;
setButtonSwapById ( app , id , newSwap ) ;
let args = await getButtonById ( app , argArray [ swap ] ) ;
let position ;
let content ;
if ( args ) {
if ( args . templater ) {
args = await templater ( app , position ) ;
if ( inline ) {
new obsidian . Notice ( "templater args don't work with inline buttons yet" , 2000 ) ;
}
}
if ( args . replace ) {
replace ( app , args ) ;
}
if ( args . type === "command" ) {
command ( app , args ) ;
}
// handle link buttons
if ( args . type === "link" ) {
link ( args ) ;
}
// handle template buttons
if ( args . type && args . type . includes ( "template" ) ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
template ( app , args , position ) ;
} , 50 ) ;
}
if ( args . type === "calculate" ) {
calculate ( app , args , position ) ;
}
if ( args . type && args . type . includes ( "text" ) ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
text ( app , args , position ) ;
} , 50 ) ;
}
// handle removing the button
if ( args . remove ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
remove ( app , args , position ) ;
} , 75 ) ;
}
if ( args . replace ) {
replace ( app , args ) ;
}
}
} ) ;
} ;
const templater = async ( app , position ) => {
app . commands . executeCommandById ( "editor:save-file" ) ;
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const file = activeView . file ;
const content = await app . vault . cachedRead ( file ) ;
app . commands . executeCommandById ( "templater-obsidian:replace-in-file-templater" ) ;
const { args } = await getNewArgs ( app , position ) ;
const cachedData = [ ] ;
const cacheChange = app . vault . on ( "modify" , ( file ) => {
cachedData . push ( file . unsafeCachedData ) ;
} ) ;
setTimeout ( async ( ) => {
const button = content
. split ( "\n" )
. splice ( position . lineStart , position . lineEnd - position . lineStart + 2 )
. join ( "\n" ) ;
let finalContent ;
if ( cachedData [ 0 ] ) {
const cachedContent = cachedData [ cachedData . length - 1 ] . split ( "\n" ) ;
let addOne = false ;
if ( args . type . includes ( "prepend" ) ) {
addOne = true ;
}
else if ( args . type . includes ( "line" ) ) {
const lineNumber = args . type . match ( /(\d+)/g ) ;
if ( lineNumber [ 0 ] ) {
const line = parseInt ( lineNumber [ 0 ] ) - 1 ;
if ( line < position . lineStart && ! args . replace ) {
addOne = true ;
}
}
}
if ( addOne ) {
cachedContent . splice ( position . lineStart + 1 , position . lineEnd - position . lineStart + 2 , button ) ;
}
else {
cachedContent . splice ( position . lineStart , position . lineEnd - position . lineStart + 2 , button ) ;
}
finalContent = cachedContent . join ( "\n" ) ;
}
else {
finalContent = content ;
}
await app . vault . modify ( file , finalContent ) ;
app . metadataCache . offref ( cacheChange ) ;
} , 200 ) ;
return args ;
}
} ;
const createButton = ( { app , el , args , inline , id , clickOverride , } ) => {
//create the button element
const button = el . createEl ( "button" , {
cls : args . class
? ` ${ args . class } ${ args . color } `
: ` button-default ${ args . color ? args . color : "" } ` ,
} ) ;
button . innerHTML = args . name ;
args . id ? button . setAttribute ( "id" , args . id ) : "" ;
button . on ( "click" , "button" , ( ) => {
clickOverride
? clickOverride . click ( ... clickOverride . params )
: clickHandler ( app , args , inline , id ) ;
} ) ;
return button ;
} ;
const clickHandler = async ( app , args , inline , id ) => {
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
let content = await app . vault . read ( activeView . file ) ;
let position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
// handle command buttons
if ( args . templater ) {
args = await templater ( app , position ) ;
if ( inline ) {
new obsidian . Notice ( "templater args don't work with inline buttons yet" , 2000 ) ;
}
}
if ( args . replace ) {
replace ( app , args ) ;
}
if ( args . type === "command" ) {
command ( app , args ) ;
}
// handle link buttons
if ( args . type === "link" ) {
link ( args ) ;
}
// handle template buttons
if ( args . type && args . type . includes ( "template" ) ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( activeView . file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
template ( app , args , position ) ;
} , 50 ) ;
}
if ( args . type === "calculate" ) {
calculate ( app , args , position ) ;
}
if ( args . type && args . type . includes ( "text" ) ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( activeView . file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
text ( app , args , position ) ;
} , 50 ) ;
}
// handle removing the button
if ( args . remove ) {
setTimeout ( async ( ) => {
content = await app . vault . read ( activeView . file ) ;
position = inline
? await getInlineButtonPosition ( app , id )
: getButtonPosition ( content , args ) ;
remove ( app , args , position ) ;
} , 1000 ) ;
}
if ( args . swap ) {
if ( ! inline ) {
new obsidian . Notice ( "swap args only work in inline buttons for now" , 2000 ) ;
}
else {
swap ( app , args . swap , id , inline , activeView . file ) ;
}
}
} ;
var top = 'top' ;
var bottom = 'bottom' ;
var right = 'right' ;
var left = 'left' ;
var auto = 'auto' ;
var basePlacements = [ top , bottom , right , left ] ;
var start = 'start' ;
var end = 'end' ;
var clippingParents = 'clippingParents' ;
var viewport = 'viewport' ;
var popper = 'popper' ;
var reference = 'reference' ;
var variationPlacements = /*#__PURE__*/ basePlacements . reduce ( function ( acc , placement ) {
return acc . concat ( [ placement + "-" + start , placement + "-" + end ] ) ;
} , [ ] ) ;
var placements = /*#__PURE__*/ [ ] . concat ( basePlacements , [ auto ] ) . reduce ( function ( acc , placement ) {
return acc . concat ( [ placement , placement + "-" + start , placement + "-" + end ] ) ;
} , [ ] ) ; // modifiers that need to read the DOM
var beforeRead = 'beforeRead' ;
var read = 'read' ;
var afterRead = 'afterRead' ; // pure-logic modifiers
var beforeMain = 'beforeMain' ;
var main = 'main' ;
var afterMain = 'afterMain' ; // modifier with the purpose to write to the DOM (or write into a framework state)
var beforeWrite = 'beforeWrite' ;
var write = 'write' ;
var afterWrite = 'afterWrite' ;
var modifierPhases = [ beforeRead , read , afterRead , beforeMain , main , afterMain , beforeWrite , write , afterWrite ] ;
function getNodeName ( element ) {
return element ? ( element . nodeName || '' ) . toLowerCase ( ) : null ;
}
function getWindow ( node ) {
if ( node == null ) {
return window ;
}
if ( node . toString ( ) !== '[object Window]' ) {
var ownerDocument = node . ownerDocument ;
return ownerDocument ? ownerDocument . defaultView || window : window ;
}
return node ;
}
function isElement ( node ) {
var OwnElement = getWindow ( node ) . Element ;
return node instanceof OwnElement || node instanceof Element ;
}
function isHTMLElement ( node ) {
var OwnElement = getWindow ( node ) . HTMLElement ;
return node instanceof OwnElement || node instanceof HTMLElement ;
}
function isShadowRoot ( node ) {
// IE 11 has no ShadowRoot
if ( typeof ShadowRoot === 'undefined' ) {
return false ;
}
var OwnElement = getWindow ( node ) . ShadowRoot ;
return node instanceof OwnElement || node instanceof ShadowRoot ;
}
// and applies them to the HTMLElements such as popper and arrow
function applyStyles ( _ref ) {
var state = _ref . state ;
Object . keys ( state . elements ) . forEach ( function ( name ) {
var style = state . styles [ name ] || { } ;
var attributes = state . attributes [ name ] || { } ;
var element = state . elements [ name ] ; // arrow is optional + virtual elements
if ( ! isHTMLElement ( element ) || ! getNodeName ( element ) ) {
return ;
} // Flow doesn't support to extend this property, but it's the most
// effective way to apply styles to an HTMLElement
// $FlowFixMe[cannot-write]
Object . assign ( element . style , style ) ;
Object . keys ( attributes ) . forEach ( function ( name ) {
var value = attributes [ name ] ;
if ( value === false ) {
element . removeAttribute ( name ) ;
} else {
element . setAttribute ( name , value === true ? '' : value ) ;
}
} ) ;
} ) ;
}
function effect$2 ( _ref2 ) {
var state = _ref2 . state ;
var initialStyles = {
popper : {
position : state . options . strategy ,
left : '0' ,
top : '0' ,
margin : '0'
} ,
arrow : {
position : 'absolute'
} ,
reference : { }
} ;
Object . assign ( state . elements . popper . style , initialStyles . popper ) ;
state . styles = initialStyles ;
if ( state . elements . arrow ) {
Object . assign ( state . elements . arrow . style , initialStyles . arrow ) ;
}
return function ( ) {
Object . keys ( state . elements ) . forEach ( function ( name ) {
var element = state . elements [ name ] ;
var attributes = state . attributes [ name ] || { } ;
var styleProperties = Object . keys ( state . styles . hasOwnProperty ( name ) ? state . styles [ name ] : initialStyles [ name ] ) ; // Set all values to an empty string to unset them
var style = styleProperties . reduce ( function ( style , property ) {
style [ property ] = '' ;
return style ;
} , { } ) ; // arrow is optional + virtual elements
if ( ! isHTMLElement ( element ) || ! getNodeName ( element ) ) {
return ;
}
Object . assign ( element . style , style ) ;
Object . keys ( attributes ) . forEach ( function ( attribute ) {
element . removeAttribute ( attribute ) ;
} ) ;
} ) ;
} ;
} // eslint-disable-next-line import/no-unused-modules
var applyStyles$1 = {
name : 'applyStyles' ,
enabled : true ,
phase : 'write' ,
fn : applyStyles ,
effect : effect$2 ,
requires : [ 'computeStyles' ]
} ;
function getBasePlacement ( placement ) {
return placement . split ( '-' ) [ 0 ] ;
}
var max = Math . max ;
var min = Math . min ;
var round = Math . round ;
function getUAString ( ) {
var uaData = navigator . userAgentData ;
if ( uaData != null && uaData . brands ) {
return uaData . brands . map ( function ( item ) {
return item . brand + "/" + item . version ;
} ) . join ( ' ' ) ;
}
return navigator . userAgent ;
}
function isLayoutViewport ( ) {
return ! /^((?!chrome|android).)*safari/i . test ( getUAString ( ) ) ;
}
function getBoundingClientRect ( element , includeScale , isFixedStrategy ) {
if ( includeScale === void 0 ) {
includeScale = false ;
}
if ( isFixedStrategy === void 0 ) {
isFixedStrategy = false ;
}
var clientRect = element . getBoundingClientRect ( ) ;
var scaleX = 1 ;
var scaleY = 1 ;
if ( includeScale && isHTMLElement ( element ) ) {
scaleX = element . offsetWidth > 0 ? round ( clientRect . width ) / element . offsetWidth || 1 : 1 ;
scaleY = element . offsetHeight > 0 ? round ( clientRect . height ) / element . offsetHeight || 1 : 1 ;
}
var _ref = isElement ( element ) ? getWindow ( element ) : window ,
visualViewport = _ref . visualViewport ;
var addVisualOffsets = ! isLayoutViewport ( ) && isFixedStrategy ;
var x = ( clientRect . left + ( addVisualOffsets && visualViewport ? visualViewport . offsetLeft : 0 ) ) / scaleX ;
var y = ( clientRect . top + ( addVisualOffsets && visualViewport ? visualViewport . offsetTop : 0 ) ) / scaleY ;
var width = clientRect . width / scaleX ;
var height = clientRect . height / scaleY ;
return {
width : width ,
height : height ,
top : y ,
right : x + width ,
bottom : y + height ,
left : x ,
x : x ,
y : y
} ;
}
// means it doesn't take into account transforms.
function getLayoutRect ( element ) {
var clientRect = getBoundingClientRect ( element ) ; // Use the clientRect sizes if it's not been transformed.
// Fixes https://github.com/popperjs/popper-core/issues/1223
var width = element . offsetWidth ;
var height = element . offsetHeight ;
if ( Math . abs ( clientRect . width - width ) <= 1 ) {
width = clientRect . width ;
}
if ( Math . abs ( clientRect . height - height ) <= 1 ) {
height = clientRect . height ;
}
return {
x : element . offsetLeft ,
y : element . offsetTop ,
width : width ,
height : height
} ;
}
function contains ( parent , child ) {
var rootNode = child . getRootNode && child . getRootNode ( ) ; // First, attempt with faster native method
if ( parent . contains ( child ) ) {
return true ;
} // then fallback to custom implementation with Shadow DOM support
else if ( rootNode && isShadowRoot ( rootNode ) ) {
var next = child ;
do {
if ( next && parent . isSameNode ( next ) ) {
return true ;
} // $FlowFixMe[prop-missing]: need a better way to handle this...
next = next . parentNode || next . host ;
} while ( next ) ;
} // Give up, the result is false
return false ;
}
function getComputedStyle ( element ) {
return getWindow ( element ) . getComputedStyle ( element ) ;
}
function isTableElement ( element ) {
return [ 'table' , 'td' , 'th' ] . indexOf ( getNodeName ( element ) ) >= 0 ;
}
function getDocumentElement ( element ) {
// $FlowFixMe[incompatible-return]: assume body is always available
return ( ( isElement ( element ) ? element . ownerDocument : // $FlowFixMe[prop-missing]
element . document ) || window . document ) . documentElement ;
}
function getParentNode ( element ) {
if ( getNodeName ( element ) === 'html' ) {
return element ;
}
return ( // this is a quicker (but less type safe) way to save quite some bytes from the bundle
// $FlowFixMe[incompatible-return]
// $FlowFixMe[prop-missing]
element . assignedSlot || // step into the shadow DOM of the parent of a slotted node
element . parentNode || ( // DOM Element detected
isShadowRoot ( element ) ? element . host : null ) || // ShadowRoot detected
// $FlowFixMe[incompatible-call]: HTMLElement is a Node
getDocumentElement ( element ) // fallback
) ;
}
function getTrueOffsetParent ( element ) {
if ( ! isHTMLElement ( element ) || // https://github.com/popperjs/popper-core/issues/837
getComputedStyle ( element ) . position === 'fixed' ) {
return null ;
}
return element . offsetParent ;
} // `.offsetParent` reports `null` for fixed elements, while absolute elements
// return the containing block
function getContainingBlock ( element ) {
var isFirefox = /firefox/i . test ( getUAString ( ) ) ;
var isIE = /Trident/i . test ( getUAString ( ) ) ;
if ( isIE && isHTMLElement ( element ) ) {
// In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
var elementCss = getComputedStyle ( element ) ;
if ( elementCss . position === 'fixed' ) {
return null ;
}
}
var currentNode = getParentNode ( element ) ;
if ( isShadowRoot ( currentNode ) ) {
currentNode = currentNode . host ;
}
while ( isHTMLElement ( currentNode ) && [ 'html' , 'body' ] . indexOf ( getNodeName ( currentNode ) ) < 0 ) {
var css = getComputedStyle ( currentNode ) ; // This is non-exhaustive but covers the most common CSS properties that
// create a containing block.
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
if ( css . transform !== 'none' || css . perspective !== 'none' || css . contain === 'paint' || [ 'transform' , 'perspective' ] . indexOf ( css . willChange ) !== - 1 || isFirefox && css . willChange === 'filter' || isFirefox && css . filter && css . filter !== 'none' ) {
return currentNode ;
} else {
currentNode = currentNode . parentNode ;
}
}
return null ;
} // Gets the closest ancestor positioned element. Handles some edge cases,
// such as table ancestors and cross browser bugs.
function getOffsetParent ( element ) {
var window = getWindow ( element ) ;
var offsetParent = getTrueOffsetParent ( element ) ;
while ( offsetParent && isTableElement ( offsetParent ) && getComputedStyle ( offsetParent ) . position === 'static' ) {
offsetParent = getTrueOffsetParent ( offsetParent ) ;
}
if ( offsetParent && ( getNodeName ( offsetParent ) === 'html' || getNodeName ( offsetParent ) === 'body' && getComputedStyle ( offsetParent ) . position === 'static' ) ) {
return window ;
}
return offsetParent || getContainingBlock ( element ) || window ;
}
function getMainAxisFromPlacement ( placement ) {
return [ 'top' , 'bottom' ] . indexOf ( placement ) >= 0 ? 'x' : 'y' ;
}
function within ( min$1 , value , max$1 ) {
return max ( min$1 , min ( value , max$1 ) ) ;
}
function withinMaxClamp ( min , value , max ) {
var v = within ( min , value , max ) ;
return v > max ? max : v ;
}
function getFreshSideObject ( ) {
return {
top : 0 ,
right : 0 ,
bottom : 0 ,
left : 0
} ;
}
function mergePaddingObject ( paddingObject ) {
return Object . assign ( { } , getFreshSideObject ( ) , paddingObject ) ;
}
function expandToHashMap ( value , keys ) {
return keys . reduce ( function ( hashMap , key ) {
hashMap [ key ] = value ;
return hashMap ;
} , { } ) ;
}
var toPaddingObject = function toPaddingObject ( padding , state ) {
padding = typeof padding === 'function' ? padding ( Object . assign ( { } , state . rects , {
placement : state . placement
} ) ) : padding ;
return mergePaddingObject ( typeof padding !== 'number' ? padding : expandToHashMap ( padding , basePlacements ) ) ;
} ;
function arrow ( _ref ) {
var _state$modifiersData$ ;
var state = _ref . state ,
name = _ref . name ,
options = _ref . options ;
var arrowElement = state . elements . arrow ;
var popperOffsets = state . modifiersData . popperOffsets ;
var basePlacement = getBasePlacement ( state . placement ) ;
var axis = getMainAxisFromPlacement ( basePlacement ) ;
var isVertical = [ left , right ] . indexOf ( basePlacement ) >= 0 ;
var len = isVertical ? 'height' : 'width' ;
if ( ! arrowElement || ! popperOffsets ) {
return ;
}
var paddingObject = toPaddingObject ( options . padding , state ) ;
var arrowRect = getLayoutRect ( arrowElement ) ;
var minProp = axis === 'y' ? top : left ;
var maxProp = axis === 'y' ? bottom : right ;
var endDiff = state . rects . reference [ len ] + state . rects . reference [ axis ] - popperOffsets [ axis ] - state . rects . popper [ len ] ;
var startDiff = popperOffsets [ axis ] - state . rects . reference [ axis ] ;
var arrowOffsetParent = getOffsetParent ( arrowElement ) ;
var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent . clientHeight || 0 : arrowOffsetParent . clientWidth || 0 : 0 ;
var centerToReference = endDiff / 2 - startDiff / 2 ; // Make sure the arrow doesn't overflow the popper if the center point is
// outside of the popper bounds
var min = paddingObject [ minProp ] ;
var max = clientSize - arrowRect [ len ] - paddingObject [ maxProp ] ;
var center = clientSize / 2 - arrowRect [ len ] / 2 + centerToReference ;
var offset = within ( min , center , max ) ; // Prevents breaking syntax highlighting...
var axisProp = axis ;
state . modifiersData [ name ] = ( _state$modifiersData$ = { } , _state$modifiersData$ [ axisProp ] = offset , _state$modifiersData$ . centerOffset = offset - center , _state$modifiersData$ ) ;
}
function effect$1 ( _ref2 ) {
var state = _ref2 . state ,
options = _ref2 . options ;
var _options$element = options . element ,
arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element ;
if ( arrowElement == null ) {
return ;
} // CSS selector
if ( typeof arrowElement === 'string' ) {
arrowElement = state . elements . popper . querySelector ( arrowElement ) ;
if ( ! arrowElement ) {
return ;
}
}
if ( process . env . NODE _ENV !== "production" ) {
if ( ! isHTMLElement ( arrowElement ) ) {
console . error ( [ 'Popper: "arrow" element must be an HTMLElement (not an SVGElement).' , 'To use an SVG arrow, wrap it in an HTMLElement that will be used as' , 'the arrow.' ] . join ( ' ' ) ) ;
}
}
if ( ! contains ( state . elements . popper , arrowElement ) ) {
if ( process . env . NODE _ENV !== "production" ) {
console . error ( [ 'Popper: "arrow" modifier\'s `element` must be a child of the popper' , 'element.' ] . join ( ' ' ) ) ;
}
return ;
}
state . elements . arrow = arrowElement ;
} // eslint-disable-next-line import/no-unused-modules
var arrow$1 = {
name : 'arrow' ,
enabled : true ,
phase : 'main' ,
fn : arrow ,
effect : effect$1 ,
requires : [ 'popperOffsets' ] ,
requiresIfExists : [ 'preventOverflow' ]
} ;
function getVariation ( placement ) {
return placement . split ( '-' ) [ 1 ] ;
}
var unsetSides = {
top : 'auto' ,
right : 'auto' ,
bottom : 'auto' ,
left : 'auto'
} ; // Round the offsets to the nearest suitable subpixel based on the DPR.
// Zooming can change the DPR, but it seems to report a value that will
// cleanly divide the values into the appropriate subpixels.
function roundOffsetsByDPR ( _ref ) {
var x = _ref . x ,
y = _ref . y ;
var win = window ;
var dpr = win . devicePixelRatio || 1 ;
return {
x : round ( x * dpr ) / dpr || 0 ,
y : round ( y * dpr ) / dpr || 0
} ;
}
function mapToStyles ( _ref2 ) {
var _Object$assign2 ;
var popper = _ref2 . popper ,
popperRect = _ref2 . popperRect ,
placement = _ref2 . placement ,
variation = _ref2 . variation ,
offsets = _ref2 . offsets ,
position = _ref2 . position ,
gpuAcceleration = _ref2 . gpuAcceleration ,
adaptive = _ref2 . adaptive ,
roundOffsets = _ref2 . roundOffsets ,
isFixed = _ref2 . isFixed ;
var _offsets$x = offsets . x ,
x = _offsets$x === void 0 ? 0 : _offsets$x ,
_offsets$y = offsets . y ,
y = _offsets$y === void 0 ? 0 : _offsets$y ;
var _ref3 = typeof roundOffsets === 'function' ? roundOffsets ( {
x : x ,
y : y
} ) : {
x : x ,
y : y
} ;
x = _ref3 . x ;
y = _ref3 . y ;
var hasX = offsets . hasOwnProperty ( 'x' ) ;
var hasY = offsets . hasOwnProperty ( 'y' ) ;
var sideX = left ;
var sideY = top ;
var win = window ;
if ( adaptive ) {
var offsetParent = getOffsetParent ( popper ) ;
var heightProp = 'clientHeight' ;
var widthProp = 'clientWidth' ;
if ( offsetParent === getWindow ( popper ) ) {
offsetParent = getDocumentElement ( popper ) ;
if ( getComputedStyle ( offsetParent ) . position !== 'static' && position === 'absolute' ) {
heightProp = 'scrollHeight' ;
widthProp = 'scrollWidth' ;
}
} // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it
offsetParent = offsetParent ;
if ( placement === top || ( placement === left || placement === right ) && variation === end ) {
sideY = bottom ;
var offsetY = isFixed && offsetParent === win && win . visualViewport ? win . visualViewport . height : // $FlowFixMe[prop-missing]
offsetParent [ heightProp ] ;
y -= offsetY - popperRect . height ;
y *= gpuAcceleration ? 1 : - 1 ;
}
if ( placement === left || ( placement === top || placement === bottom ) && variation === end ) {
sideX = right ;
var offsetX = isFixed && offsetParent === win && win . visualViewport ? win . visualViewport . width : // $FlowFixMe[prop-missing]
offsetParent [ widthProp ] ;
x -= offsetX - popperRect . width ;
x *= gpuAcceleration ? 1 : - 1 ;
}
}
var commonStyles = Object . assign ( {
position : position
} , adaptive && unsetSides ) ;
var _ref4 = roundOffsets === true ? roundOffsetsByDPR ( {
x : x ,
y : y
} ) : {
x : x ,
y : y
} ;
x = _ref4 . x ;
y = _ref4 . y ;
if ( gpuAcceleration ) {
var _Object$assign ;
return Object . assign ( { } , commonStyles , ( _Object$assign = { } , _Object$assign [ sideY ] = hasY ? '0' : '' , _Object$assign [ sideX ] = hasX ? '0' : '' , _Object$assign . transform = ( win . devicePixelRatio || 1 ) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)" , _Object$assign ) ) ;
}
return Object . assign ( { } , commonStyles , ( _Object$assign2 = { } , _Object$assign2 [ sideY ] = hasY ? y + "px" : '' , _Object$assign2 [ sideX ] = hasX ? x + "px" : '' , _Object$assign2 . transform = '' , _Object$assign2 ) ) ;
}
function computeStyles ( _ref5 ) {
var state = _ref5 . state ,
options = _ref5 . options ;
var _options$gpuAccelerat = options . gpuAcceleration ,
gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat ,
_options$adaptive = options . adaptive ,
adaptive = _options$adaptive === void 0 ? true : _options$adaptive ,
_options$roundOffsets = options . roundOffsets ,
roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets ;
if ( process . env . NODE _ENV !== "production" ) {
var transitionProperty = getComputedStyle ( state . elements . popper ) . transitionProperty || '' ;
if ( adaptive && [ 'transform' , 'top' , 'right' , 'bottom' , 'left' ] . some ( function ( property ) {
return transitionProperty . indexOf ( property ) >= 0 ;
} ) ) {
console . warn ( [ 'Popper: Detected CSS transitions on at least one of the following' , 'CSS properties: "transform", "top", "right", "bottom", "left".' , '\n\n' , 'Disable the "computeStyles" modifier\'s `adaptive` option to allow' , 'for smooth transitions, or remove these properties from the CSS' , 'transition declaration on the popper element if only transitioning' , 'opacity or background-color for example.' , '\n\n' , 'We recommend using the popper element as a wrapper around an inner' , 'element that can have any CSS property transitioned for animations.' ] . join ( ' ' ) ) ;
}
}
var commonStyles = {
placement : getBasePlacement ( state . placement ) ,
variation : getVariation ( state . placement ) ,
popper : state . elements . popper ,
popperRect : state . rects . popper ,
gpuAcceleration : gpuAcceleration ,
isFixed : state . options . strategy === 'fixed'
} ;
if ( state . modifiersData . popperOffsets != null ) {
state . styles . popper = Object . assign ( { } , state . styles . popper , mapToStyles ( Object . assign ( { } , commonStyles , {
offsets : state . modifiersData . popperOffsets ,
position : state . options . strategy ,
adaptive : adaptive ,
roundOffsets : roundOffsets
} ) ) ) ;
}
if ( state . modifiersData . arrow != null ) {
state . styles . arrow = Object . assign ( { } , state . styles . arrow , mapToStyles ( Object . assign ( { } , commonStyles , {
offsets : state . modifiersData . arrow ,
position : 'absolute' ,
adaptive : false ,
roundOffsets : roundOffsets
} ) ) ) ;
}
state . attributes . popper = Object . assign ( { } , state . attributes . popper , {
'data-popper-placement' : state . placement
} ) ;
} // eslint-disable-next-line import/no-unused-modules
var computeStyles$1 = {
name : 'computeStyles' ,
enabled : true ,
phase : 'beforeWrite' ,
fn : computeStyles ,
data : { }
} ;
var passive = {
passive : true
} ;
function effect ( _ref ) {
var state = _ref . state ,
instance = _ref . instance ,
options = _ref . options ;
var _options$scroll = options . scroll ,
scroll = _options$scroll === void 0 ? true : _options$scroll ,
_options$resize = options . resize ,
resize = _options$resize === void 0 ? true : _options$resize ;
var window = getWindow ( state . elements . popper ) ;
var scrollParents = [ ] . concat ( state . scrollParents . reference , state . scrollParents . popper ) ;
if ( scroll ) {
scrollParents . forEach ( function ( scrollParent ) {
scrollParent . addEventListener ( 'scroll' , instance . update , passive ) ;
} ) ;
}
if ( resize ) {
window . addEventListener ( 'resize' , instance . update , passive ) ;
}
return function ( ) {
if ( scroll ) {
scrollParents . forEach ( function ( scrollParent ) {
scrollParent . removeEventListener ( 'scroll' , instance . update , passive ) ;
} ) ;
}
if ( resize ) {
window . removeEventListener ( 'resize' , instance . update , passive ) ;
}
} ;
} // eslint-disable-next-line import/no-unused-modules
var eventListeners = {
name : 'eventListeners' ,
enabled : true ,
phase : 'write' ,
fn : function fn ( ) { } ,
effect : effect ,
data : { }
} ;
var hash$1 = {
left : 'right' ,
right : 'left' ,
bottom : 'top' ,
top : 'bottom'
} ;
function getOppositePlacement ( placement ) {
return placement . replace ( /left|right|bottom|top/g , function ( matched ) {
return hash$1 [ matched ] ;
} ) ;
}
var hash = {
start : 'end' ,
end : 'start'
} ;
function getOppositeVariationPlacement ( placement ) {
return placement . replace ( /start|end/g , function ( matched ) {
return hash [ matched ] ;
} ) ;
}
function getWindowScroll ( node ) {
var win = getWindow ( node ) ;
var scrollLeft = win . pageXOffset ;
var scrollTop = win . pageYOffset ;
return {
scrollLeft : scrollLeft ,
scrollTop : scrollTop
} ;
}
function getWindowScrollBarX ( element ) {
// If <html> has a CSS width greater than the viewport, then this will be
// incorrect for RTL.
// Popper 1 is broken in this case and never had a bug report so let's assume
// it's not an issue. I don't think anyone ever specifies width on <html>
// anyway.
// Browsers where the left scrollbar doesn't cause an issue report `0` for
// this (e.g. Edge 2019, IE11, Safari)
return getBoundingClientRect ( getDocumentElement ( element ) ) . left + getWindowScroll ( element ) . scrollLeft ;
}
function getViewportRect ( element , strategy ) {
var win = getWindow ( element ) ;
var html = getDocumentElement ( element ) ;
var visualViewport = win . visualViewport ;
var width = html . clientWidth ;
var height = html . clientHeight ;
var x = 0 ;
var y = 0 ;
if ( visualViewport ) {
width = visualViewport . width ;
height = visualViewport . height ;
var layoutViewport = isLayoutViewport ( ) ;
if ( layoutViewport || ! layoutViewport && strategy === 'fixed' ) {
x = visualViewport . offsetLeft ;
y = visualViewport . offsetTop ;
}
}
return {
width : width ,
height : height ,
x : x + getWindowScrollBarX ( element ) ,
y : y
} ;
}
// of the `<html>` and `<body>` rect bounds if horizontally scrollable
function getDocumentRect ( element ) {
var _element$ownerDocumen ;
var html = getDocumentElement ( element ) ;
var winScroll = getWindowScroll ( element ) ;
var body = ( _element$ownerDocumen = element . ownerDocument ) == null ? void 0 : _element$ownerDocumen . body ;
var width = max ( html . scrollWidth , html . clientWidth , body ? body . scrollWidth : 0 , body ? body . clientWidth : 0 ) ;
var height = max ( html . scrollHeight , html . clientHeight , body ? body . scrollHeight : 0 , body ? body . clientHeight : 0 ) ;
var x = - winScroll . scrollLeft + getWindowScrollBarX ( element ) ;
var y = - winScroll . scrollTop ;
if ( getComputedStyle ( body || html ) . direction === 'rtl' ) {
x += max ( html . clientWidth , body ? body . clientWidth : 0 ) - width ;
}
return {
width : width ,
height : height ,
x : x ,
y : y
} ;
}
function isScrollParent ( element ) {
// Firefox wants us to check `-x` and `-y` variations as well
var _getComputedStyle = getComputedStyle ( element ) ,
overflow = _getComputedStyle . overflow ,
overflowX = _getComputedStyle . overflowX ,
overflowY = _getComputedStyle . overflowY ;
return /auto|scroll|overlay|hidden/ . test ( overflow + overflowY + overflowX ) ;
}
function getScrollParent ( node ) {
if ( [ 'html' , 'body' , '#document' ] . indexOf ( getNodeName ( node ) ) >= 0 ) {
// $FlowFixMe[incompatible-return]: assume body is always available
return node . ownerDocument . body ;
}
if ( isHTMLElement ( node ) && isScrollParent ( node ) ) {
return node ;
}
return getScrollParent ( getParentNode ( node ) ) ;
}
/ *
given a DOM element , return the list of all scroll parents , up the list of ancesors
until we get to the top window object . This list is what we attach scroll listeners
to , because if any of these parent elements scroll , we ' ll need to re - calculate the
reference element ' s position .
* /
function listScrollParents ( element , list ) {
var _element$ownerDocumen ;
if ( list === void 0 ) {
list = [ ] ;
}
var scrollParent = getScrollParent ( element ) ;
var isBody = scrollParent === ( ( _element$ownerDocumen = element . ownerDocument ) == null ? void 0 : _element$ownerDocumen . body ) ;
var win = getWindow ( scrollParent ) ;
var target = isBody ? [ win ] . concat ( win . visualViewport || [ ] , isScrollParent ( scrollParent ) ? scrollParent : [ ] ) : scrollParent ;
var updatedList = list . concat ( target ) ;
return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
updatedList . concat ( listScrollParents ( getParentNode ( target ) ) ) ;
}
function rectToClientRect ( rect ) {
return Object . assign ( { } , rect , {
left : rect . x ,
top : rect . y ,
right : rect . x + rect . width ,
bottom : rect . y + rect . height
} ) ;
}
function getInnerBoundingClientRect ( element , strategy ) {
var rect = getBoundingClientRect ( element , false , strategy === 'fixed' ) ;
rect . top = rect . top + element . clientTop ;
rect . left = rect . left + element . clientLeft ;
rect . bottom = rect . top + element . clientHeight ;
rect . right = rect . left + element . clientWidth ;
rect . width = element . clientWidth ;
rect . height = element . clientHeight ;
rect . x = rect . left ;
rect . y = rect . top ;
return rect ;
}
function getClientRectFromMixedType ( element , clippingParent , strategy ) {
return clippingParent === viewport ? rectToClientRect ( getViewportRect ( element , strategy ) ) : isElement ( clippingParent ) ? getInnerBoundingClientRect ( clippingParent , strategy ) : rectToClientRect ( getDocumentRect ( getDocumentElement ( element ) ) ) ;
} // A "clipping parent" is an overflowable container with the characteristic of
// clipping (or hiding) overflowing elements with a position different from
// `initial`
function getClippingParents ( element ) {
var clippingParents = listScrollParents ( getParentNode ( element ) ) ;
var canEscapeClipping = [ 'absolute' , 'fixed' ] . indexOf ( getComputedStyle ( element ) . position ) >= 0 ;
var clipperElement = canEscapeClipping && isHTMLElement ( element ) ? getOffsetParent ( element ) : element ;
if ( ! isElement ( clipperElement ) ) {
return [ ] ;
} // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414
return clippingParents . filter ( function ( clippingParent ) {
return isElement ( clippingParent ) && contains ( clippingParent , clipperElement ) && getNodeName ( clippingParent ) !== 'body' ;
} ) ;
} // Gets the maximum area that the element is visible in due to any number of
// clipping parents
function getClippingRect ( element , boundary , rootBoundary , strategy ) {
var mainClippingParents = boundary === 'clippingParents' ? getClippingParents ( element ) : [ ] . concat ( boundary ) ;
var clippingParents = [ ] . concat ( mainClippingParents , [ rootBoundary ] ) ;
var firstClippingParent = clippingParents [ 0 ] ;
var clippingRect = clippingParents . reduce ( function ( accRect , clippingParent ) {
var rect = getClientRectFromMixedType ( element , clippingParent , strategy ) ;
accRect . top = max ( rect . top , accRect . top ) ;
accRect . right = min ( rect . right , accRect . right ) ;
accRect . bottom = min ( rect . bottom , accRect . bottom ) ;
accRect . left = max ( rect . left , accRect . left ) ;
return accRect ;
} , getClientRectFromMixedType ( element , firstClippingParent , strategy ) ) ;
clippingRect . width = clippingRect . right - clippingRect . left ;
clippingRect . height = clippingRect . bottom - clippingRect . top ;
clippingRect . x = clippingRect . left ;
clippingRect . y = clippingRect . top ;
return clippingRect ;
}
function computeOffsets ( _ref ) {
var reference = _ref . reference ,
element = _ref . element ,
placement = _ref . placement ;
var basePlacement = placement ? getBasePlacement ( placement ) : null ;
var variation = placement ? getVariation ( placement ) : null ;
var commonX = reference . x + reference . width / 2 - element . width / 2 ;
var commonY = reference . y + reference . height / 2 - element . height / 2 ;
var offsets ;
switch ( basePlacement ) {
case top :
offsets = {
x : commonX ,
y : reference . y - element . height
} ;
break ;
case bottom :
offsets = {
x : commonX ,
y : reference . y + reference . height
} ;
break ;
case right :
offsets = {
x : reference . x + reference . width ,
y : commonY
} ;
break ;
case left :
offsets = {
x : reference . x - element . width ,
y : commonY
} ;
break ;
default :
offsets = {
x : reference . x ,
y : reference . y
} ;
}
var mainAxis = basePlacement ? getMainAxisFromPlacement ( basePlacement ) : null ;
if ( mainAxis != null ) {
var len = mainAxis === 'y' ? 'height' : 'width' ;
switch ( variation ) {
case start :
offsets [ mainAxis ] = offsets [ mainAxis ] - ( reference [ len ] / 2 - element [ len ] / 2 ) ;
break ;
case end :
offsets [ mainAxis ] = offsets [ mainAxis ] + ( reference [ len ] / 2 - element [ len ] / 2 ) ;
break ;
}
}
return offsets ;
}
function detectOverflow ( state , options ) {
if ( options === void 0 ) {
options = { } ;
}
var _options = options ,
_options$placement = _options . placement ,
placement = _options$placement === void 0 ? state . placement : _options$placement ,
_options$strategy = _options . strategy ,
strategy = _options$strategy === void 0 ? state . strategy : _options$strategy ,
_options$boundary = _options . boundary ,
boundary = _options$boundary === void 0 ? clippingParents : _options$boundary ,
_options$rootBoundary = _options . rootBoundary ,
rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary ,
_options$elementConte = _options . elementContext ,
elementContext = _options$elementConte === void 0 ? popper : _options$elementConte ,
_options$altBoundary = _options . altBoundary ,
altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary ,
_options$padding = _options . padding ,
padding = _options$padding === void 0 ? 0 : _options$padding ;
var paddingObject = mergePaddingObject ( typeof padding !== 'number' ? padding : expandToHashMap ( padding , basePlacements ) ) ;
var altContext = elementContext === popper ? reference : popper ;
var popperRect = state . rects . popper ;
var element = state . elements [ altBoundary ? altContext : elementContext ] ;
var clippingClientRect = getClippingRect ( isElement ( element ) ? element : element . contextElement || getDocumentElement ( state . elements . popper ) , boundary , rootBoundary , strategy ) ;
var referenceClientRect = getBoundingClientRect ( state . elements . reference ) ;
var popperOffsets = computeOffsets ( {
reference : referenceClientRect ,
element : popperRect ,
strategy : 'absolute' ,
placement : placement
} ) ;
var popperClientRect = rectToClientRect ( Object . assign ( { } , popperRect , popperOffsets ) ) ;
var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect ; // positive = overflowing the clipping rect
// 0 or negative = within the clipping rect
var overflowOffsets = {
top : clippingClientRect . top - elementClientRect . top + paddingObject . top ,
bottom : elementClientRect . bottom - clippingClientRect . bottom + paddingObject . bottom ,
left : clippingClientRect . left - elementClientRect . left + paddingObject . left ,
right : elementClientRect . right - clippingClientRect . right + paddingObject . right
} ;
var offsetData = state . modifiersData . offset ; // Offsets can be applied only to the popper element
if ( elementContext === popper && offsetData ) {
var offset = offsetData [ placement ] ;
Object . keys ( overflowOffsets ) . forEach ( function ( key ) {
var multiply = [ right , bottom ] . indexOf ( key ) >= 0 ? 1 : - 1 ;
var axis = [ top , bottom ] . indexOf ( key ) >= 0 ? 'y' : 'x' ;
overflowOffsets [ key ] += offset [ axis ] * multiply ;
} ) ;
}
return overflowOffsets ;
}
function computeAutoPlacement ( state , options ) {
if ( options === void 0 ) {
options = { } ;
}
var _options = options ,
placement = _options . placement ,
boundary = _options . boundary ,
rootBoundary = _options . rootBoundary ,
padding = _options . padding ,
flipVariations = _options . flipVariations ,
_options$allowedAutoP = _options . allowedAutoPlacements ,
allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP ;
var variation = getVariation ( placement ) ;
var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements . filter ( function ( placement ) {
return getVariation ( placement ) === variation ;
} ) : basePlacements ;
var allowedPlacements = placements$1 . filter ( function ( placement ) {
return allowedAutoPlacements . indexOf ( placement ) >= 0 ;
} ) ;
if ( allowedPlacements . length === 0 ) {
allowedPlacements = placements$1 ;
if ( process . env . NODE _ENV !== "production" ) {
console . error ( [ 'Popper: The `allowedAutoPlacements` option did not allow any' , 'placements. Ensure the `placement` option matches the variation' , 'of the allowed placements.' , 'For example, "auto" cannot be used to allow "bottom-start".' , 'Use "auto-start" instead.' ] . join ( ' ' ) ) ;
}
} // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...
var overflows = allowedPlacements . reduce ( function ( acc , placement ) {
acc [ placement ] = detectOverflow ( state , {
placement : placement ,
boundary : boundary ,
rootBoundary : rootBoundary ,
padding : padding
} ) [ getBasePlacement ( placement ) ] ;
return acc ;
} , { } ) ;
return Object . keys ( overflows ) . sort ( function ( a , b ) {
return overflows [ a ] - overflows [ b ] ;
} ) ;
}
function getExpandedFallbackPlacements ( placement ) {
if ( getBasePlacement ( placement ) === auto ) {
return [ ] ;
}
var oppositePlacement = getOppositePlacement ( placement ) ;
return [ getOppositeVariationPlacement ( placement ) , oppositePlacement , getOppositeVariationPlacement ( oppositePlacement ) ] ;
}
function flip ( _ref ) {
var state = _ref . state ,
options = _ref . options ,
name = _ref . name ;
if ( state . modifiersData [ name ] . _skip ) {
return ;
}
var _options$mainAxis = options . mainAxis ,
checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis ,
_options$altAxis = options . altAxis ,
checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis ,
specifiedFallbackPlacements = options . fallbackPlacements ,
padding = options . padding ,
boundary = options . boundary ,
rootBoundary = options . rootBoundary ,
altBoundary = options . altBoundary ,
_options$flipVariatio = options . flipVariations ,
flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio ,
allowedAutoPlacements = options . allowedAutoPlacements ;
var preferredPlacement = state . options . placement ;
var basePlacement = getBasePlacement ( preferredPlacement ) ;
var isBasePlacement = basePlacement === preferredPlacement ;
var fallbackPlacements = specifiedFallbackPlacements || ( isBasePlacement || ! flipVariations ? [ getOppositePlacement ( preferredPlacement ) ] : getExpandedFallbackPlacements ( preferredPlacement ) ) ;
var placements = [ preferredPlacement ] . concat ( fallbackPlacements ) . reduce ( function ( acc , placement ) {
return acc . concat ( getBasePlacement ( placement ) === auto ? computeAutoPlacement ( state , {
placement : placement ,
boundary : boundary ,
rootBoundary : rootBoundary ,
padding : padding ,
flipVariations : flipVariations ,
allowedAutoPlacements : allowedAutoPlacements
} ) : placement ) ;
} , [ ] ) ;
var referenceRect = state . rects . reference ;
var popperRect = state . rects . popper ;
var checksMap = new Map ( ) ;
var makeFallbackChecks = true ;
var firstFittingPlacement = placements [ 0 ] ;
for ( var i = 0 ; i < placements . length ; i ++ ) {
var placement = placements [ i ] ;
var _basePlacement = getBasePlacement ( placement ) ;
var isStartVariation = getVariation ( placement ) === start ;
var isVertical = [ top , bottom ] . indexOf ( _basePlacement ) >= 0 ;
var len = isVertical ? 'width' : 'height' ;
var overflow = detectOverflow ( state , {
placement : placement ,
boundary : boundary ,
rootBoundary : rootBoundary ,
altBoundary : altBoundary ,
padding : padding
} ) ;
var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top ;
if ( referenceRect [ len ] > popperRect [ len ] ) {
mainVariationSide = getOppositePlacement ( mainVariationSide ) ;
}
var altVariationSide = getOppositePlacement ( mainVariationSide ) ;
var checks = [ ] ;
if ( checkMainAxis ) {
checks . push ( overflow [ _basePlacement ] <= 0 ) ;
}
if ( checkAltAxis ) {
checks . push ( overflow [ mainVariationSide ] <= 0 , overflow [ altVariationSide ] <= 0 ) ;
}
if ( checks . every ( function ( check ) {
return check ;
} ) ) {
firstFittingPlacement = placement ;
makeFallbackChecks = false ;
break ;
}
checksMap . set ( placement , checks ) ;
}
if ( makeFallbackChecks ) {
// `2` may be desired in some cases – research later
var numberOfChecks = flipVariations ? 3 : 1 ;
var _loop = function _loop ( _i ) {
var fittingPlacement = placements . find ( function ( placement ) {
var checks = checksMap . get ( placement ) ;
if ( checks ) {
return checks . slice ( 0 , _i ) . every ( function ( check ) {
return check ;
} ) ;
}
} ) ;
if ( fittingPlacement ) {
firstFittingPlacement = fittingPlacement ;
return "break" ;
}
} ;
for ( var _i = numberOfChecks ; _i > 0 ; _i -- ) {
var _ret = _loop ( _i ) ;
if ( _ret === "break" ) break ;
}
}
if ( state . placement !== firstFittingPlacement ) {
state . modifiersData [ name ] . _skip = true ;
state . placement = firstFittingPlacement ;
state . reset = true ;
}
} // eslint-disable-next-line import/no-unused-modules
var flip$1 = {
name : 'flip' ,
enabled : true ,
phase : 'main' ,
fn : flip ,
requiresIfExists : [ 'offset' ] ,
data : {
_skip : false
}
} ;
function getSideOffsets ( overflow , rect , preventedOffsets ) {
if ( preventedOffsets === void 0 ) {
preventedOffsets = {
x : 0 ,
y : 0
} ;
}
return {
top : overflow . top - rect . height - preventedOffsets . y ,
right : overflow . right - rect . width + preventedOffsets . x ,
bottom : overflow . bottom - rect . height + preventedOffsets . y ,
left : overflow . left - rect . width - preventedOffsets . x
} ;
}
function isAnySideFullyClipped ( overflow ) {
return [ top , right , bottom , left ] . some ( function ( side ) {
return overflow [ side ] >= 0 ;
} ) ;
}
function hide ( _ref ) {
var state = _ref . state ,
name = _ref . name ;
var referenceRect = state . rects . reference ;
var popperRect = state . rects . popper ;
var preventedOffsets = state . modifiersData . preventOverflow ;
var referenceOverflow = detectOverflow ( state , {
elementContext : 'reference'
} ) ;
var popperAltOverflow = detectOverflow ( state , {
altBoundary : true
} ) ;
var referenceClippingOffsets = getSideOffsets ( referenceOverflow , referenceRect ) ;
var popperEscapeOffsets = getSideOffsets ( popperAltOverflow , popperRect , preventedOffsets ) ;
var isReferenceHidden = isAnySideFullyClipped ( referenceClippingOffsets ) ;
var hasPopperEscaped = isAnySideFullyClipped ( popperEscapeOffsets ) ;
state . modifiersData [ name ] = {
referenceClippingOffsets : referenceClippingOffsets ,
popperEscapeOffsets : popperEscapeOffsets ,
isReferenceHidden : isReferenceHidden ,
hasPopperEscaped : hasPopperEscaped
} ;
state . attributes . popper = Object . assign ( { } , state . attributes . popper , {
'data-popper-reference-hidden' : isReferenceHidden ,
'data-popper-escaped' : hasPopperEscaped
} ) ;
} // eslint-disable-next-line import/no-unused-modules
var hide$1 = {
name : 'hide' ,
enabled : true ,
phase : 'main' ,
requiresIfExists : [ 'preventOverflow' ] ,
fn : hide
} ;
function distanceAndSkiddingToXY ( placement , rects , offset ) {
var basePlacement = getBasePlacement ( placement ) ;
var invertDistance = [ left , top ] . indexOf ( basePlacement ) >= 0 ? - 1 : 1 ;
var _ref = typeof offset === 'function' ? offset ( Object . assign ( { } , rects , {
placement : placement
} ) ) : offset ,
skidding = _ref [ 0 ] ,
distance = _ref [ 1 ] ;
skidding = skidding || 0 ;
distance = ( distance || 0 ) * invertDistance ;
return [ left , right ] . indexOf ( basePlacement ) >= 0 ? {
x : distance ,
y : skidding
} : {
x : skidding ,
y : distance
} ;
}
function offset ( _ref2 ) {
var state = _ref2 . state ,
options = _ref2 . options ,
name = _ref2 . name ;
var _options$offset = options . offset ,
offset = _options$offset === void 0 ? [ 0 , 0 ] : _options$offset ;
var data = placements . reduce ( function ( acc , placement ) {
acc [ placement ] = distanceAndSkiddingToXY ( placement , state . rects , offset ) ;
return acc ;
} , { } ) ;
var _data$state$placement = data [ state . placement ] ,
x = _data$state$placement . x ,
y = _data$state$placement . y ;
if ( state . modifiersData . popperOffsets != null ) {
state . modifiersData . popperOffsets . x += x ;
state . modifiersData . popperOffsets . y += y ;
}
state . modifiersData [ name ] = data ;
} // eslint-disable-next-line import/no-unused-modules
var offset$1 = {
name : 'offset' ,
enabled : true ,
phase : 'main' ,
requires : [ 'popperOffsets' ] ,
fn : offset
} ;
function popperOffsets ( _ref ) {
var state = _ref . state ,
name = _ref . name ;
// Offsets are the actual position the popper needs to have to be
// properly positioned near its reference element
// This is the most basic placement, and will be adjusted by
// the modifiers in the next step
state . modifiersData [ name ] = computeOffsets ( {
reference : state . rects . reference ,
element : state . rects . popper ,
strategy : 'absolute' ,
placement : state . placement
} ) ;
} // eslint-disable-next-line import/no-unused-modules
var popperOffsets$1 = {
name : 'popperOffsets' ,
enabled : true ,
phase : 'read' ,
fn : popperOffsets ,
data : { }
} ;
function getAltAxis ( axis ) {
return axis === 'x' ? 'y' : 'x' ;
}
function preventOverflow ( _ref ) {
var state = _ref . state ,
options = _ref . options ,
name = _ref . name ;
var _options$mainAxis = options . mainAxis ,
checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis ,
_options$altAxis = options . altAxis ,
checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis ,
boundary = options . boundary ,
rootBoundary = options . rootBoundary ,
altBoundary = options . altBoundary ,
padding = options . padding ,
_options$tether = options . tether ,
tether = _options$tether === void 0 ? true : _options$tether ,
_options$tetherOffset = options . tetherOffset ,
tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset ;
var overflow = detectOverflow ( state , {
boundary : boundary ,
rootBoundary : rootBoundary ,
padding : padding ,
altBoundary : altBoundary
} ) ;
var basePlacement = getBasePlacement ( state . placement ) ;
var variation = getVariation ( state . placement ) ;
var isBasePlacement = ! variation ;
var mainAxis = getMainAxisFromPlacement ( basePlacement ) ;
var altAxis = getAltAxis ( mainAxis ) ;
var popperOffsets = state . modifiersData . popperOffsets ;
var referenceRect = state . rects . reference ;
var popperRect = state . rects . popper ;
var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset ( Object . assign ( { } , state . rects , {
placement : state . placement
} ) ) : tetherOffset ;
var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {
mainAxis : tetherOffsetValue ,
altAxis : tetherOffsetValue
} : Object . assign ( {
mainAxis : 0 ,
altAxis : 0
} , tetherOffsetValue ) ;
var offsetModifierState = state . modifiersData . offset ? state . modifiersData . offset [ state . placement ] : null ;
var data = {
x : 0 ,
y : 0
} ;
if ( ! popperOffsets ) {
return ;
}
if ( checkMainAxis ) {
var _offsetModifierState$ ;
var mainSide = mainAxis === 'y' ? top : left ;
var altSide = mainAxis === 'y' ? bottom : right ;
var len = mainAxis === 'y' ? 'height' : 'width' ;
var offset = popperOffsets [ mainAxis ] ;
var min$1 = offset + overflow [ mainSide ] ;
var max$1 = offset - overflow [ altSide ] ;
var additive = tether ? - popperRect [ len ] / 2 : 0 ;
var minLen = variation === start ? referenceRect [ len ] : popperRect [ len ] ;
var maxLen = variation === start ? - popperRect [ len ] : - referenceRect [ len ] ; // We need to include the arrow in the calculation so the arrow doesn't go
// outside the reference bounds
var arrowElement = state . elements . arrow ;
var arrowRect = tether && arrowElement ? getLayoutRect ( arrowElement ) : {
width : 0 ,
height : 0
} ;
var arrowPaddingObject = state . modifiersData [ 'arrow#persistent' ] ? state . modifiersData [ 'arrow#persistent' ] . padding : getFreshSideObject ( ) ;
var arrowPaddingMin = arrowPaddingObject [ mainSide ] ;
var arrowPaddingMax = arrowPaddingObject [ altSide ] ; // If the reference length is smaller than the arrow length, we don't want
// to include its full size in the calculation. If the reference is small
// and near the edge of a boundary, the popper can overflow even if the
// reference is not overflowing as well (e.g. virtual elements with no
// width or height)
var arrowLen = within ( 0 , referenceRect [ len ] , arrowRect [ len ] ) ;
var minOffset = isBasePlacement ? referenceRect [ len ] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue . mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue . mainAxis ;
var maxOffset = isBasePlacement ? - referenceRect [ len ] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue . mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue . mainAxis ;
var arrowOffsetParent = state . elements . arrow && getOffsetParent ( state . elements . arrow ) ;
var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent . clientTop || 0 : arrowOffsetParent . clientLeft || 0 : 0 ;
var offsetModifierValue = ( _offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState [ mainAxis ] ) != null ? _offsetModifierState$ : 0 ;
var tetherMin = offset + minOffset - offsetModifierValue - clientOffset ;
var tetherMax = offset + maxOffset - offsetModifierValue ;
var preventedOffset = within ( tether ? min ( min$1 , tetherMin ) : min$1 , offset , tether ? max ( max$1 , tetherMax ) : max$1 ) ;
popperOffsets [ mainAxis ] = preventedOffset ;
data [ mainAxis ] = preventedOffset - offset ;
}
if ( checkAltAxis ) {
var _offsetModifierState$2 ;
var _mainSide = mainAxis === 'x' ? top : left ;
var _altSide = mainAxis === 'x' ? bottom : right ;
var _offset = popperOffsets [ altAxis ] ;
var _len = altAxis === 'y' ? 'height' : 'width' ;
var _min = _offset + overflow [ _mainSide ] ;
var _max = _offset - overflow [ _altSide ] ;
var isOriginSide = [ top , left ] . indexOf ( basePlacement ) !== - 1 ;
var _offsetModifierValue = ( _offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState [ altAxis ] ) != null ? _offsetModifierState$2 : 0 ;
var _tetherMin = isOriginSide ? _min : _offset - referenceRect [ _len ] - popperRect [ _len ] - _offsetModifierValue + normalizedTetherOffsetValue . altAxis ;
var _tetherMax = isOriginSide ? _offset + referenceRect [ _len ] + popperRect [ _len ] - _offsetModifierValue - normalizedTetherOffsetValue . altAxis : _max ;
var _preventedOffset = tether && isOriginSide ? withinMaxClamp ( _tetherMin , _offset , _tetherMax ) : within ( tether ? _tetherMin : _min , _offset , tether ? _tetherMax : _max ) ;
popperOffsets [ altAxis ] = _preventedOffset ;
data [ altAxis ] = _preventedOffset - _offset ;
}
state . modifiersData [ name ] = data ;
} // eslint-disable-next-line import/no-unused-modules
var preventOverflow$1 = {
name : 'preventOverflow' ,
enabled : true ,
phase : 'main' ,
fn : preventOverflow ,
requiresIfExists : [ 'offset' ]
} ;
function getHTMLElementScroll ( element ) {
return {
scrollLeft : element . scrollLeft ,
scrollTop : element . scrollTop
} ;
}
function getNodeScroll ( node ) {
if ( node === getWindow ( node ) || ! isHTMLElement ( node ) ) {
return getWindowScroll ( node ) ;
} else {
return getHTMLElementScroll ( node ) ;
}
}
function isElementScaled ( element ) {
var rect = element . getBoundingClientRect ( ) ;
var scaleX = round ( rect . width ) / element . offsetWidth || 1 ;
var scaleY = round ( rect . height ) / element . offsetHeight || 1 ;
return scaleX !== 1 || scaleY !== 1 ;
} // Returns the composite rect of an element relative to its offsetParent.
// Composite means it takes into account transforms as well as layout.
function getCompositeRect ( elementOrVirtualElement , offsetParent , isFixed ) {
if ( isFixed === void 0 ) {
isFixed = false ;
}
var isOffsetParentAnElement = isHTMLElement ( offsetParent ) ;
var offsetParentIsScaled = isHTMLElement ( offsetParent ) && isElementScaled ( offsetParent ) ;
var documentElement = getDocumentElement ( offsetParent ) ;
var rect = getBoundingClientRect ( elementOrVirtualElement , offsetParentIsScaled , isFixed ) ;
var scroll = {
scrollLeft : 0 ,
scrollTop : 0
} ;
var offsets = {
x : 0 ,
y : 0
} ;
if ( isOffsetParentAnElement || ! isOffsetParentAnElement && ! isFixed ) {
if ( getNodeName ( offsetParent ) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
isScrollParent ( documentElement ) ) {
scroll = getNodeScroll ( offsetParent ) ;
}
if ( isHTMLElement ( offsetParent ) ) {
offsets = getBoundingClientRect ( offsetParent , true ) ;
offsets . x += offsetParent . clientLeft ;
offsets . y += offsetParent . clientTop ;
} else if ( documentElement ) {
offsets . x = getWindowScrollBarX ( documentElement ) ;
}
}
return {
x : rect . left + scroll . scrollLeft - offsets . x ,
y : rect . top + scroll . scrollTop - offsets . y ,
width : rect . width ,
height : rect . height
} ;
}
function order ( modifiers ) {
var map = new Map ( ) ;
var visited = new Set ( ) ;
var result = [ ] ;
modifiers . forEach ( function ( modifier ) {
map . set ( modifier . name , modifier ) ;
} ) ; // On visiting object, check for its dependencies and visit them recursively
function sort ( modifier ) {
visited . add ( modifier . name ) ;
var requires = [ ] . concat ( modifier . requires || [ ] , modifier . requiresIfExists || [ ] ) ;
requires . forEach ( function ( dep ) {
if ( ! visited . has ( dep ) ) {
var depModifier = map . get ( dep ) ;
if ( depModifier ) {
sort ( depModifier ) ;
}
}
} ) ;
result . push ( modifier ) ;
}
modifiers . forEach ( function ( modifier ) {
if ( ! visited . has ( modifier . name ) ) {
// check for visited object
sort ( modifier ) ;
}
} ) ;
return result ;
}
function orderModifiers ( modifiers ) {
// order based on dependencies
var orderedModifiers = order ( modifiers ) ; // order based on phase
return modifierPhases . reduce ( function ( acc , phase ) {
return acc . concat ( orderedModifiers . filter ( function ( modifier ) {
return modifier . phase === phase ;
} ) ) ;
} , [ ] ) ;
}
function debounce ( fn ) {
var pending ;
return function ( ) {
if ( ! pending ) {
pending = new Promise ( function ( resolve ) {
Promise . resolve ( ) . then ( function ( ) {
pending = undefined ;
resolve ( fn ( ) ) ;
} ) ;
} ) ;
}
return pending ;
} ;
}
function format ( str ) {
for ( var _len = arguments . length , args = new Array ( _len > 1 ? _len - 1 : 0 ) , _key = 1 ; _key < _len ; _key ++ ) {
args [ _key - 1 ] = arguments [ _key ] ;
}
return [ ] . concat ( args ) . reduce ( function ( p , c ) {
return p . replace ( /%s/ , c ) ;
} , str ) ;
}
var INVALID _MODIFIER _ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s' ;
var MISSING _DEPENDENCY _ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available' ;
var VALID _PROPERTIES = [ 'name' , 'enabled' , 'phase' , 'fn' , 'effect' , 'requires' , 'options' ] ;
function validateModifiers ( modifiers ) {
modifiers . forEach ( function ( modifier ) {
[ ] . concat ( Object . keys ( modifier ) , VALID _PROPERTIES ) // IE11-compatible replacement for `new Set(iterable)`
. filter ( function ( value , index , self ) {
return self . indexOf ( value ) === index ;
} ) . forEach ( function ( key ) {
switch ( key ) {
case 'name' :
if ( typeof modifier . name !== 'string' ) {
console . error ( format ( INVALID _MODIFIER _ERROR , String ( modifier . name ) , '"name"' , '"string"' , "\"" + String ( modifier . name ) + "\"" ) ) ;
}
break ;
case 'enabled' :
if ( typeof modifier . enabled !== 'boolean' ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"enabled"' , '"boolean"' , "\"" + String ( modifier . enabled ) + "\"" ) ) ;
}
break ;
case 'phase' :
if ( modifierPhases . indexOf ( modifier . phase ) < 0 ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"phase"' , "either " + modifierPhases . join ( ', ' ) , "\"" + String ( modifier . phase ) + "\"" ) ) ;
}
break ;
case 'fn' :
if ( typeof modifier . fn !== 'function' ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"fn"' , '"function"' , "\"" + String ( modifier . fn ) + "\"" ) ) ;
}
break ;
case 'effect' :
if ( modifier . effect != null && typeof modifier . effect !== 'function' ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"effect"' , '"function"' , "\"" + String ( modifier . fn ) + "\"" ) ) ;
}
break ;
case 'requires' :
if ( modifier . requires != null && ! Array . isArray ( modifier . requires ) ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"requires"' , '"array"' , "\"" + String ( modifier . requires ) + "\"" ) ) ;
}
break ;
case 'requiresIfExists' :
if ( ! Array . isArray ( modifier . requiresIfExists ) ) {
console . error ( format ( INVALID _MODIFIER _ERROR , modifier . name , '"requiresIfExists"' , '"array"' , "\"" + String ( modifier . requiresIfExists ) + "\"" ) ) ;
}
break ;
case 'options' :
case 'data' :
break ;
default :
console . error ( "PopperJS: an invalid property has been provided to the \"" + modifier . name + "\" modifier, valid properties are " + VALID _PROPERTIES . map ( function ( s ) {
return "\"" + s + "\"" ;
} ) . join ( ', ' ) + "; but \"" + key + "\" was provided." ) ;
}
modifier . requires && modifier . requires . forEach ( function ( requirement ) {
if ( modifiers . find ( function ( mod ) {
return mod . name === requirement ;
} ) == null ) {
console . error ( format ( MISSING _DEPENDENCY _ERROR , String ( modifier . name ) , requirement , requirement ) ) ;
}
} ) ;
} ) ;
} ) ;
}
function uniqueBy ( arr , fn ) {
var identifiers = new Set ( ) ;
return arr . filter ( function ( item ) {
var identifier = fn ( item ) ;
if ( ! identifiers . has ( identifier ) ) {
identifiers . add ( identifier ) ;
return true ;
}
} ) ;
}
function mergeByName ( modifiers ) {
var merged = modifiers . reduce ( function ( merged , current ) {
var existing = merged [ current . name ] ;
merged [ current . name ] = existing ? Object . assign ( { } , existing , current , {
options : Object . assign ( { } , existing . options , current . options ) ,
data : Object . assign ( { } , existing . data , current . data )
} ) : current ;
return merged ;
} , { } ) ; // IE11 does not support Object.values
return Object . keys ( merged ) . map ( function ( key ) {
return merged [ key ] ;
} ) ;
}
var INVALID _ELEMENT _ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.' ;
var INFINITE _LOOP _ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.' ;
var DEFAULT _OPTIONS = {
placement : 'bottom' ,
modifiers : [ ] ,
strategy : 'absolute'
} ;
function areValidElements ( ) {
for ( var _len = arguments . length , args = new Array ( _len ) , _key = 0 ; _key < _len ; _key ++ ) {
args [ _key ] = arguments [ _key ] ;
}
return ! args . some ( function ( element ) {
return ! ( element && typeof element . getBoundingClientRect === 'function' ) ;
} ) ;
}
function popperGenerator ( generatorOptions ) {
if ( generatorOptions === void 0 ) {
generatorOptions = { } ;
}
var _generatorOptions = generatorOptions ,
_generatorOptions$def = _generatorOptions . defaultModifiers ,
defaultModifiers = _generatorOptions$def === void 0 ? [ ] : _generatorOptions$def ,
_generatorOptions$def2 = _generatorOptions . defaultOptions ,
defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT _OPTIONS : _generatorOptions$def2 ;
return function createPopper ( reference , popper , options ) {
if ( options === void 0 ) {
options = defaultOptions ;
}
var state = {
placement : 'bottom' ,
orderedModifiers : [ ] ,
options : Object . assign ( { } , DEFAULT _OPTIONS , defaultOptions ) ,
modifiersData : { } ,
elements : {
reference : reference ,
popper : popper
} ,
attributes : { } ,
styles : { }
} ;
var effectCleanupFns = [ ] ;
var isDestroyed = false ;
var instance = {
state : state ,
setOptions : function setOptions ( setOptionsAction ) {
var options = typeof setOptionsAction === 'function' ? setOptionsAction ( state . options ) : setOptionsAction ;
cleanupModifierEffects ( ) ;
state . options = Object . assign ( { } , defaultOptions , state . options , options ) ;
state . scrollParents = {
reference : isElement ( reference ) ? listScrollParents ( reference ) : reference . contextElement ? listScrollParents ( reference . contextElement ) : [ ] ,
popper : listScrollParents ( popper )
} ; // Orders the modifiers based on their dependencies and `phase`
// properties
var orderedModifiers = orderModifiers ( mergeByName ( [ ] . concat ( defaultModifiers , state . options . modifiers ) ) ) ; // Strip out disabled modifiers
state . orderedModifiers = orderedModifiers . filter ( function ( m ) {
return m . enabled ;
} ) ; // Validate the provided modifiers so that the consumer will get warned
// if one of the modifiers is invalid for any reason
if ( process . env . NODE _ENV !== "production" ) {
var modifiers = uniqueBy ( [ ] . concat ( orderedModifiers , state . options . modifiers ) , function ( _ref ) {
var name = _ref . name ;
return name ;
} ) ;
validateModifiers ( modifiers ) ;
if ( getBasePlacement ( state . options . placement ) === auto ) {
var flipModifier = state . orderedModifiers . find ( function ( _ref2 ) {
var name = _ref2 . name ;
return name === 'flip' ;
} ) ;
if ( ! flipModifier ) {
console . error ( [ 'Popper: "auto" placements require the "flip" modifier be' , 'present and enabled to work.' ] . join ( ' ' ) ) ;
}
}
var _getComputedStyle = getComputedStyle ( popper ) ,
marginTop = _getComputedStyle . marginTop ,
marginRight = _getComputedStyle . marginRight ,
marginBottom = _getComputedStyle . marginBottom ,
marginLeft = _getComputedStyle . marginLeft ; // We no longer take into account `margins` on the popper, and it can
// cause bugs with positioning, so we'll warn the consumer
if ( [ marginTop , marginRight , marginBottom , marginLeft ] . some ( function ( margin ) {
return parseFloat ( margin ) ;
} ) ) {
console . warn ( [ 'Popper: CSS "margin" styles cannot be used to apply padding' , 'between the popper and its reference element or boundary.' , 'To replicate margin, use the `offset` modifier, as well as' , 'the `padding` option in the `preventOverflow` and `flip`' , 'modifiers.' ] . join ( ' ' ) ) ;
}
}
runModifierEffects ( ) ;
return instance . update ( ) ;
} ,
// Sync update – it will always be executed, even if not necessary. This
// is useful for low frequency updates where sync behavior simplifies the
// logic.
// For high frequency updates (e.g. `resize` and `scroll` events), always
// prefer the async Popper#update method
forceUpdate : function forceUpdate ( ) {
if ( isDestroyed ) {
return ;
}
var _state$elements = state . elements ,
reference = _state$elements . reference ,
popper = _state$elements . popper ; // Don't proceed if `reference` or `popper` are not valid elements
// anymore
if ( ! areValidElements ( reference , popper ) ) {
if ( process . env . NODE _ENV !== "production" ) {
console . error ( INVALID _ELEMENT _ERROR ) ;
}
return ;
} // Store the reference and popper rects to be read by modifiers
state . rects = {
reference : getCompositeRect ( reference , getOffsetParent ( popper ) , state . options . strategy === 'fixed' ) ,
popper : getLayoutRect ( popper )
} ; // Modifiers have the ability to reset the current update cycle. The
// most common use case for this is the `flip` modifier changing the
// placement, which then needs to re-run all the modifiers, because the
// logic was previously ran for the previous placement and is therefore
// stale/incorrect
state . reset = false ;
state . placement = state . options . placement ; // On each update cycle, the `modifiersData` property for each modifier
// is filled with the initial data specified by the modifier. This means
// it doesn't persist and is fresh on each update.
// To ensure persistent data, use `${name}#persistent`
state . orderedModifiers . forEach ( function ( modifier ) {
return state . modifiersData [ modifier . name ] = Object . assign ( { } , modifier . data ) ;
} ) ;
var _ _debug _loops _ _ = 0 ;
for ( var index = 0 ; index < state . orderedModifiers . length ; index ++ ) {
if ( process . env . NODE _ENV !== "production" ) {
_ _debug _loops _ _ += 1 ;
if ( _ _debug _loops _ _ > 100 ) {
console . error ( INFINITE _LOOP _ERROR ) ;
break ;
}
}
if ( state . reset === true ) {
state . reset = false ;
index = - 1 ;
continue ;
}
var _state$orderedModifie = state . orderedModifiers [ index ] ,
fn = _state$orderedModifie . fn ,
_state$orderedModifie2 = _state$orderedModifie . options ,
_options = _state$orderedModifie2 === void 0 ? { } : _state$orderedModifie2 ,
name = _state$orderedModifie . name ;
if ( typeof fn === 'function' ) {
state = fn ( {
state : state ,
options : _options ,
name : name ,
instance : instance
} ) || state ;
}
}
} ,
// Async and optimistically optimized update – it will not be executed if
// not necessary (debounced to run at most once-per-tick)
update : debounce ( function ( ) {
return new Promise ( function ( resolve ) {
instance . forceUpdate ( ) ;
resolve ( state ) ;
} ) ;
} ) ,
destroy : function destroy ( ) {
cleanupModifierEffects ( ) ;
isDestroyed = true ;
}
} ;
if ( ! areValidElements ( reference , popper ) ) {
if ( process . env . NODE _ENV !== "production" ) {
console . error ( INVALID _ELEMENT _ERROR ) ;
}
return instance ;
}
instance . setOptions ( options ) . then ( function ( state ) {
if ( ! isDestroyed && options . onFirstUpdate ) {
options . onFirstUpdate ( state ) ;
}
} ) ; // Modifiers have the ability to execute arbitrary code before the first
// update cycle runs. They will be executed in the same order as the update
// cycle. This is useful when a modifier adds some persistent data that
// other modifiers need to use, but the modifier is run after the dependent
// one.
function runModifierEffects ( ) {
state . orderedModifiers . forEach ( function ( _ref3 ) {
var name = _ref3 . name ,
_ref3$options = _ref3 . options ,
options = _ref3$options === void 0 ? { } : _ref3$options ,
effect = _ref3 . effect ;
if ( typeof effect === 'function' ) {
var cleanupFn = effect ( {
state : state ,
name : name ,
instance : instance ,
options : options
} ) ;
var noopFn = function noopFn ( ) { } ;
effectCleanupFns . push ( cleanupFn || noopFn ) ;
}
} ) ;
}
function cleanupModifierEffects ( ) {
effectCleanupFns . forEach ( function ( fn ) {
return fn ( ) ;
} ) ;
effectCleanupFns = [ ] ;
}
return instance ;
} ;
}
var defaultModifiers = [ eventListeners , popperOffsets$1 , computeStyles$1 , applyStyles$1 , offset$1 , flip$1 , preventOverflow$1 , arrow$1 , hide$1 ] ;
var createPopper = /*#__PURE__*/ popperGenerator ( {
defaultModifiers : defaultModifiers
} ) ; // eslint-disable-next-line import/no-unused-modules
// Stole All this from Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
class Suggest {
constructor ( owner , containerEl , scope ) {
this . owner = owner ;
this . containerEl = containerEl ;
containerEl . on ( "click" , ".suggestion-item" , this . onSuggestionClick . bind ( this ) ) ;
containerEl . on ( "mousemove" , ".suggestion-item" , this . onSuggestionMouseover . bind ( this ) ) ;
scope . register ( [ ] , "ArrowUp" , ( event ) => {
if ( ! event . isComposing ) {
this . setSelectedItem ( this . selectedItem - 1 , true ) ;
return false ;
}
} ) ;
scope . register ( [ ] , "ArrowDown" , ( event ) => {
if ( ! event . isComposing ) {
this . setSelectedItem ( this . selectedItem + 1 , true ) ;
return false ;
}
} ) ;
scope . register ( [ ] , "Enter" , ( event ) => {
if ( ! event . isComposing ) {
this . useSelectedItem ( event ) ;
return false ;
}
} ) ;
}
onSuggestionClick ( event , el ) {
event . preventDefault ( ) ;
const item = this . suggestions . indexOf ( el ) ;
this . setSelectedItem ( item , false ) ;
this . useSelectedItem ( event ) ;
}
onSuggestionMouseover ( _event , el ) {
const item = this . suggestions . indexOf ( el ) ;
this . setSelectedItem ( item , false ) ;
}
setSuggestions ( values ) {
this . containerEl . empty ( ) ;
const suggestionEls = [ ] ;
values . forEach ( ( value ) => {
const suggestionEl = this . containerEl . createDiv ( "suggestion-item" ) ;
this . owner . renderSuggestion ( value , suggestionEl ) ;
suggestionEls . push ( suggestionEl ) ;
} ) ;
this . values = values ;
this . suggestions = suggestionEls ;
this . setSelectedItem ( 0 , false ) ;
}
useSelectedItem ( event ) {
const currentValue = this . values [ this . selectedItem ] ;
if ( currentValue ) {
this . owner . selectSuggestion ( currentValue , event ) ;
}
}
setSelectedItem ( selectedIndex , scrollIntoView ) {
const normalizedIndex = wrapAround ( selectedIndex , this . suggestions . length ) ;
const prevSelectedSuggestion = this . suggestions [ this . selectedItem ] ;
const selectedSuggestion = this . suggestions [ normalizedIndex ] ;
prevSelectedSuggestion ? . removeClass ( "is-selected" ) ;
selectedSuggestion ? . addClass ( "is-selected" ) ;
this . selectedItem = normalizedIndex ;
if ( scrollIntoView ) {
selectedSuggestion . scrollIntoView ( false ) ;
}
}
}
class TextInputSuggest {
constructor ( app , inputEl ) {
this . app = app ;
this . inputEl = inputEl ;
this . scope = new obsidian . Scope ( ) ;
this . suggestEl = createDiv ( "suggestion-container" ) ;
const suggestion = this . suggestEl . createDiv ( "suggestion" ) ;
this . suggest = new Suggest ( this , suggestion , this . scope ) ;
this . scope . register ( [ ] , "Escape" , this . close . bind ( this ) ) ;
this . inputEl . addEventListener ( "input" , this . onInputChanged . bind ( this ) ) ;
this . inputEl . addEventListener ( "focus" , this . onInputChanged . bind ( this ) ) ;
this . inputEl . addEventListener ( "blur" , this . close . bind ( this ) ) ;
this . suggestEl . on ( "mousedown" , ".suggestion-container" , ( event ) => {
event . preventDefault ( ) ;
} ) ;
}
onInputChanged ( ) {
const inputStr = this . inputEl . value ;
const suggestions = this . getSuggestions ( inputStr ) ;
if ( suggestions . length > 0 ) {
this . suggest . setSuggestions ( suggestions ) ;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this . open ( this . app . dom . appContainerEl , this . inputEl ) ;
}
}
open ( container , inputEl ) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this . app . keymap . pushScope ( this . scope ) ;
container . appendChild ( this . suggestEl ) ;
this . popper = createPopper ( inputEl , this . suggestEl , {
placement : "bottom-start" ,
modifiers : [
{
name : "sameWidth" ,
enabled : true ,
fn : ( { state , instance } ) => {
// Note: positioning needs to be calculated twice -
// first pass - positioning it according to the width of the popper
// second pass - position it with the width bound to the reference element
// we need to early exit to avoid an infinite loop
const targetWidth = ` ${ state . rects . reference . width } px ` ;
if ( state . styles . popper . width === targetWidth ) {
return ;
}
state . styles . popper . width = targetWidth ;
instance . update ( ) ;
} ,
phase : "beforeWrite" ,
requires : [ "computeStyles" ] ,
} ,
] ,
} ) ;
}
close ( ) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this . app . keymap . popScope ( this . scope ) ;
this . suggest . setSuggestions ( [ ] ) ;
this . popper && this . popper . destroy ( ) ;
this . suggestEl . detach ( ) ;
}
}
class CommandSuggest extends TextInputSuggest {
getSuggestions ( inputStr ) {
const commands = this . app . commands . commands ;
const commandNames = [ ] ;
const inputLowerCase = inputStr . toLowerCase ( ) ;
for ( const command in commands ) {
const commandObj = commands [ command ] ;
if ( commandObj . name . toLowerCase ( ) . contains ( inputLowerCase ) ) {
commandNames . push ( commandObj ) ;
}
}
return commandNames ;
}
renderSuggestion ( command , el ) {
el . setText ( command . name ) ;
}
selectSuggestion ( command ) {
this . inputEl . value = command . name ;
this . inputEl . trigger ( "input" ) ;
this . close ( ) ;
}
}
class TemplateSuggest extends TextInputSuggest {
constructor ( ) {
super ( ... arguments ) ;
this . templatesEnabled = this . app . internalPlugins . plugins . templates . enabled ;
this . templaterPlugin = this . app . plugins . plugins [ "templater-obsidian" ] ;
// only run if templates plugin is enabled
this . folder = ( ) => {
const folders = [ ] ;
if ( this . templatesEnabled ) {
const folder = this . app . internalPlugins . plugins . templates . instance . options
. folder ;
if ( folder ) {
folders . push ( folder . toLowerCase ( ) ) ;
}
if ( this . templaterPlugin ) {
const folder = this . templaterPlugin . settings . template _folder ;
if ( folder ) {
folders . push ( folder . toLowerCase ( ) ) ;
}
}
}
return folders [ 0 ] ? folders : undefined ;
} ;
}
getSuggestions ( inputStr ) {
const abstractFiles = this . app . vault . getAllLoadedFiles ( ) ;
const files = [ ] ;
const lowerCaseInputStr = inputStr . toLowerCase ( ) ;
const folders = this . folder ( ) ;
abstractFiles . forEach ( ( file ) => {
let exists = false ;
folders &&
folders . forEach ( ( folder ) => {
if ( file . path . toLowerCase ( ) . contains ( ` ${ folder } / ` ) ) {
exists = true ;
}
} ) ;
if ( file instanceof obsidian . TFile &&
file . extension === "md" &&
exists &&
file . path . toLowerCase ( ) . contains ( lowerCaseInputStr ) ) {
files . push ( file ) ;
}
} ) ;
return files ;
}
renderSuggestion ( file , el ) {
el . setText ( file . name . split ( "." ) [ 0 ] ) ;
}
selectSuggestion ( file ) {
this . inputEl . value = file . name . split ( "." ) [ 0 ] ;
this . inputEl . trigger ( "input" ) ;
this . close ( ) ;
}
}
class ButtonSuggest extends TextInputSuggest {
getSuggestions ( ) {
const buttonStore = getStore ( this . app . isMobile ) ;
const buttons = [ ] ;
buttonStore . forEach ( ( button ) => {
const trimmed = button . id . split ( "-" ) [ 1 ] ;
buttons . push ( trimmed ) ;
} ) ;
return buttons ;
}
renderSuggestion ( button , el ) {
el . setText ( button ) ;
}
selectSuggestion ( button ) {
this . inputEl . value = this . inputEl . value + button ;
this . inputEl . trigger ( "input" ) ;
this . close ( ) ;
}
}
class ButtonModal extends obsidian . Modal {
constructor ( app ) {
super ( app ) ;
this . buttonPreviewEl = createEl ( "p" ) ;
this . commandSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . fileSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . removeSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . swapSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . idSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . outputObject = {
name : "" ,
type : "" ,
action : "" ,
swap : "" ,
remove : "" ,
replace : "" ,
id : "" ,
templater : false ,
class : "" ,
color : "" ,
blockId : "" ,
} ;
this . commandSuggest = new CommandSuggest ( this . app , this . commandSuggestEl ) ;
this . commandSuggestEl . placeholder = "Toggle Pin" ;
this . commandSuggestEl . addEventListener ( "change" , ( e ) => {
this . outputObject . action = e . target . value ;
} ) ;
this . commandSuggestEl . addEventListener ( "blur" , ( e ) => {
this . outputObject . action = e . target . value ;
} ) ;
this . fileSuggest = new TemplateSuggest ( this . app , this . fileSuggestEl ) ;
this . fileSuggestEl . placeholder = "My Template" ;
this . fileSuggestEl . addEventListener ( "change" , ( e ) => {
this . outputObject . action = e . target . value ;
} ) ;
this . fileSuggestEl . addEventListener ( "blur" , ( e ) => {
this . outputObject . action = e . target . value ;
} ) ;
this . removeSuggest = new ButtonSuggest ( this . app , this . removeSuggestEl ) ;
this . removeSuggestEl . value = "true" ;
this . removeSuggestEl . addEventListener ( "change" , ( e ) => {
this . outputObject . remove = e . target . value ;
} ) ;
this . removeSuggestEl . addEventListener ( "blur" , ( e ) => {
this . outputObject . remove = e . target . value ;
} ) ;
this . swapSuggest = new ButtonSuggest ( this . app , this . swapSuggestEl ) ;
this . swapSuggestEl . addEventListener ( "change" , ( e ) => {
this . outputObject . swap = e . target . value ;
} ) ;
this . swapSuggestEl . addEventListener ( "blur" , ( e ) => {
this . outputObject . swap = e . target . value ;
} ) ;
this . idSuggest = new ButtonSuggest ( this . app , this . idSuggestEl ) ;
this . idSuggestEl . addEventListener ( "change" , ( e ) => {
this . outputObject . id = e . target . value ;
} ) ;
this . idSuggestEl . addEventListener ( "blur" , ( e ) => {
this . outputObject . id = e . target . value ;
} ) ;
this . swapSuggestEl . placeholder = "[idOne, idTwo]" ;
}
onOpen ( ) {
const { titleEl , contentEl } = this ;
titleEl . setText ( "Button Maker" ) ;
contentEl . addClass ( "button-maker" ) ;
contentEl . createEl ( "form" , { } , ( formEl ) => {
new obsidian . Setting ( formEl )
. setName ( "Button Name" )
. setDesc ( "What would you like to call this button?" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "My Awesome Button" ) ;
textEl . onChange ( ( value ) => {
this . buttonPreviewEl . setText ( value ) ;
this . outputObject . name = value ;
} ) ;
window . setTimeout ( ( ) => textEl . inputEl . focus ( ) , 10 ) ;
} ) ;
const typeContainer = createEl ( "div" ) ;
const typeTitle = createEl ( "span" , { cls : "setting-item-title" } ) ;
typeTitle . setText ( "Button Type" ) ;
const typeDesc = createEl ( "div" , { cls : "setting-item-description" } ) ;
typeDesc . setText ( "What type of button are you making?" ) ;
formEl . appendChild ( typeContainer ) ;
typeContainer . appendChild ( typeTitle ) ;
typeContainer . appendChild ( typeDesc ) ;
new obsidian . Setting ( typeDesc ) . addDropdown ( ( drop ) => {
drop . addOption ( "pre" , "Select a Button Type" ) ;
drop . addOption ( "command" , "Command - run a command prompt command" ) ;
drop . addOption ( "link" , "Link - open a url or uri" ) ;
drop . addOption ( "template" , "Template - insert or create notes from templates" ) ;
drop . addOption ( "text" , "Text - insert or create notes with text" ) ;
drop . addOption ( "calculate" , "Calculate - run a mathematical calculation" ) ;
drop . addOption ( "swap" , "Swap - Create a multi-purpose Inline Button from other Buttons" ) ;
const action = formEl . createEl ( "div" ) ;
drop . onChange ( ( value ) => {
this . outputObject . type = value ;
if ( value === "link" ) {
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Link" )
. setDesc ( "Enter a link to open" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "https://obsidian.md" ) ;
textEl . onChange ( ( value ) => ( this . outputObject . action = value ) ) ;
} ) ;
}
if ( value === "command" ) {
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Command" )
. setDesc ( "Enter a command to run" )
. addText ( ( textEl ) => {
textEl . inputEl . replaceWith ( this . commandSuggestEl ) ;
} ) ;
}
if ( value . includes ( "template" ) ) {
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Template" )
. setDesc ( "Select a template note and what should happen" )
. addDropdown ( ( drop ) => {
drop . addOption ( "pre" , "Do this..." ) ;
drop . addOption ( "prepend template" , "Prepend" ) ;
drop . addOption ( "append template" , "Append" ) ;
drop . addOption ( "line template" , "Line" ) ;
drop . addOption ( "note template" , "Note" ) ;
drop . onChange ( ( value ) => {
this . outputObject . type = value ;
if ( value == "line template" ) {
new obsidian . Setting ( action )
. setName ( "Line Number" )
. setDesc ( "At which line should the template be inserted?" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "69" ) ;
textEl . onChange ( ( value ) => {
this . outputObject . type = ` line( ${ value } ) template ` ;
} ) ;
} ) ;
}
if ( value == "note template" ) {
new obsidian . Setting ( action )
. setName ( "Note Name" )
. setDesc ( "What should the new note be named?" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "My New Note" ) ;
new obsidian . Setting ( action )
. setName ( "Split" )
. setDesc ( "Should the new note open in a split pane?" )
. addToggle ( ( toggleEl ) => {
this . outputObject . type = ` note( ${ textEl . getValue } ) template ` ;
textEl . onChange ( ( textVal ) => {
const toggleVal = toggleEl . getValue ( ) ;
if ( toggleVal ) {
this . outputObject . type = ` note( ${ textVal } , split) template ` ;
}
if ( ! toggleVal ) {
this . outputObject . type = ` note( ${ textVal } ) template ` ;
}
} ) ;
toggleEl . onChange ( ( toggleVal ) => {
const textVal = textEl . getValue ( ) ;
if ( toggleVal ) {
this . outputObject . type = ` note( ${ textVal } , split) template ` ;
}
if ( ! toggleVal ) {
this . outputObject . type = ` note( ${ textVal } ) template ` ;
}
} ) ;
} ) ;
} ) ;
}
} ) ;
} )
. addText ( ( textEl ) => {
textEl . inputEl . replaceWith ( this . fileSuggestEl ) ;
} ) ;
}
if ( value . includes ( "text" ) ) {
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Text" )
. setDesc ( "What text and where should it go?" )
. addDropdown ( ( drop ) => {
drop . addOption ( "pre" , "Do this..." ) ;
drop . addOption ( "prepend text" , "Prepend" ) ;
drop . addOption ( "append text" , "Append" ) ;
drop . addOption ( "line text" , "Line" ) ;
drop . addOption ( "note text" , "Note" ) ;
drop . onChange ( ( value ) => {
this . outputObject . type = value ;
if ( value == "line text" ) {
new obsidian . Setting ( action )
. setName ( "Line Number" )
. setDesc ( "At which line should the template be inserted?" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "69" ) ;
textEl . onChange ( ( value ) => {
this . outputObject . type = ` line( ${ value } ) text ` ;
} ) ;
} ) ;
}
if ( value == "note text" ) {
new obsidian . Setting ( action )
. setName ( "Note Name" )
. setDesc ( "What should the new note be named?" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "My New Note" ) ;
new obsidian . Setting ( action )
. setName ( "Split" )
. setDesc ( "Should the new note open in a split pane?" )
. addToggle ( ( toggleEl ) => {
this . outputObject . type = ` note( ${ textEl . getValue } ) text ` ;
textEl . onChange ( ( textVal ) => {
const toggleVal = toggleEl . getValue ( ) ;
if ( toggleVal ) {
this . outputObject . type = ` note( ${ textVal } , split) text ` ;
}
if ( ! toggleVal ) {
this . outputObject . type = ` note( ${ textVal } ) text ` ;
}
} ) ;
toggleEl . onChange ( ( toggleVal ) => {
const textVal = textEl . getValue ( ) ;
if ( toggleVal ) {
this . outputObject . type = ` note( ${ textVal } , split) text ` ;
}
if ( ! toggleVal ) {
this . outputObject . type = ` note( ${ textVal } ) text ` ;
}
} ) ;
} ) ;
} ) ;
}
} ) ;
} )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "My Text to Insert" ) ;
textEl . onChange ( ( value ) => {
this . outputObject . action = value ;
} ) ;
} ) ;
}
if ( value === "calculate" ) {
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Calculate" )
. setDesc ( "Enter a calculation, you can reference a line number with $LineNumber" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "2+$10" ) ;
textEl . onChange ( ( value ) => ( this . outputObject . action = value ) ) ;
} ) ;
}
if ( value === "swap" ) {
this . outputObject . type = "" ;
action . empty ( ) ;
new obsidian . Setting ( action )
. setName ( "Swap" )
. setDesc ( "choose buttons to be included in the Inline Swap Button" )
. addText ( ( textEl ) => {
textEl . inputEl . replaceWith ( this . swapSuggestEl ) ;
} ) ;
}
} ) ;
} ) ;
new obsidian . Setting ( formEl )
. setName ( "Button Block ID" )
. setDesc ( "Provide a custom button-block-id" )
. addText ( ( textEl ) => {
textEl . setPlaceholder ( "buttonId" ) ;
textEl . onChange ( ( value ) => {
this . outputObject . blockId = value ;
} ) ;
} ) ;
new obsidian . Setting ( formEl )
. setName ( "Remove" )
. setDesc ( "Would you like to remove this button (or other buttons) after clicking?" )
. addToggle ( ( toggleEl ) => {
toggleEl . onChange ( ( value ) => {
if ( value ) {
new obsidian . Setting ( remove )
. setName ( "Select Remove" )
. setDesc ( "Use true to remove this button, or supply an [array] of button block-ids" )
. addText ( ( textEl ) => {
textEl . inputEl . replaceWith ( this . removeSuggestEl ) ;
} ) ;
}
if ( ! value ) {
this . outputObject . remove = "" ;
remove . empty ( ) ;
}
} ) ;
} ) ;
const remove = formEl . createEl ( "div" ) ;
new obsidian . Setting ( formEl )
. setName ( "Replace" )
. setDesc ( "Would you like to replace lines in the note after clicking?" )
. addToggle ( ( toggleEl ) => {
toggleEl . onChange ( ( value ) => {
if ( value ) {
new obsidian . Setting ( replace )
. setName ( "Select Lines" )
. setDesc ( "Supply an array of [startingLine, endingLine] to be replaced" )
. addText ( ( textEl ) => {
textEl . setValue ( "[]" ) ;
textEl . onChange ( ( value ) => ( this . outputObject . replace = value ) ) ;
} ) ;
}
if ( ! value ) {
replace . empty ( ) ;
}
} ) ;
} ) ;
const replace = formEl . createEl ( "div" ) ;
new obsidian . Setting ( formEl )
. setName ( "Inherit" )
. setDesc ( "Would you like to inherit args by adding an existing button block-id?" )
. addToggle ( ( toggleEl ) => {
toggleEl . onChange ( ( value ) => {
if ( value ) {
new obsidian . Setting ( id )
. setName ( "id" )
. setDesc ( "inherit from other Buttons by adding their button block-id" )
. addText ( ( textEl ) => {
textEl . inputEl . replaceWith ( this . idSuggestEl ) ;
} ) ;
}
if ( ! value ) {
this . outputObject . replace = "" ;
id . empty ( ) ;
}
} ) ;
} ) ;
const id = formEl . createEl ( "div" ) ;
new obsidian . Setting ( formEl )
. setName ( "Templater" )
. setDesc ( "Do you want to convert a templater command inside your Button on each click?" )
. addToggle ( ( toggleEl ) => {
toggleEl . setTooltip ( "Do not use for inline Button" ) ;
toggleEl . onChange ( ( value ) => {
this . outputObject . templater = value ;
} ) ;
} ) ;
new obsidian . Setting ( formEl )
. setName ( "Custom Class" )
. setDesc ( "Add a custom class for button styling" )
. addText ( ( textEl ) => {
textEl . onChange ( ( value ) => {
this . buttonPreviewEl . setAttribute ( "class" , value ) ;
this . outputObject . class = value ;
if ( value === "" ) {
this . buttonPreviewEl . setAttribute ( "class" , "button-default" ) ;
}
} ) ;
} ) ;
new obsidian . Setting ( formEl )
. setName ( "Color" )
. setDesc ( "What color would you like your button to be?" )
. addDropdown ( ( drop ) => {
drop . addOption ( "default" , "Default Color" ) ;
drop . addOption ( "blue" , "Blue" ) ;
drop . addOption ( "red" , "Red" ) ;
drop . addOption ( "green" , "Green" ) ;
drop . addOption ( "yellow" , "Yellow" ) ;
drop . addOption ( "purple" , "Purple" ) ;
drop . onChange ( ( value ) => {
this . outputObject . color = value ;
const buttonClass = this . buttonPreviewEl
. getAttribute ( "class" )
. replace ( " blue" , "" )
. replace ( " red" , "" )
. replace ( " green" , "" )
. replace ( " yellow" , "" )
. replace ( " purple" , "" ) ;
if ( value !== "default" ) {
this . buttonPreviewEl . setAttribute ( "class" , ` ${ buttonClass } ${ value } ` ) ;
if ( value === "blue" ) {
value = "#76b3fa" ;
}
if ( value === "purple" ) {
value = "#725585" ;
}
this . buttonPreviewEl . setAttribute ( "style" , ` background: ${ value } ` ) ;
}
else {
this . buttonPreviewEl . setAttribute ( "class" , ` ${ buttonClass } ` ) ;
this . buttonPreviewEl . removeAttribute ( "style" ) ;
}
} ) ;
} ) ;
formEl . createDiv ( "modal-button-container" , ( buttonContainerEl ) => {
buttonContainerEl
. createEl ( "button" , {
attr : { type : "button" } ,
cls : "button-default" ,
text : "Cancel" ,
} )
. addEventListener ( "click" , ( ) => this . close ( ) ) ;
buttonContainerEl . createEl ( "button" , {
attr : { type : "submit" } ,
cls : "button-default mod-cta" ,
text : "Insert Button" ,
} ) ;
} ) ;
formEl . addEventListener ( "submit" , ( e ) => {
e . preventDefault ( ) ;
insertButton ( this . app , this . outputObject ) ;
this . close ( ) ;
} ) ;
} ) ;
contentEl . createEl ( "p" ) . setText ( "Button Preview" ) ;
this . buttonPreviewEl = createButton ( {
app : this . app ,
el : contentEl ,
args : { name : "My Awesome Button" } ,
} ) ;
}
onClose ( ) {
const { contentEl } = this ;
contentEl . empty ( ) ;
}
}
class InlineButtonModal extends obsidian . Modal {
constructor ( app ) {
super ( app ) ;
this . buttonSuggestEl = createEl ( "input" , { type : "text" } ) ;
this . buttonSuggest = new ButtonSuggest ( this . app , this . buttonSuggestEl ) ;
this . buttonSuggestEl . setAttribute ( "style" , "width: 100%; height: 40px" ) ;
}
onOpen ( ) {
const { titleEl , contentEl } = this ;
titleEl . setText ( "Insert Inline Button" ) ;
contentEl . createEl ( "form" , { } , ( formEl ) => {
formEl . appendChild ( this . buttonSuggestEl ) ;
formEl . addEventListener ( "submit" , ( e ) => {
e . preventDefault ( ) ;
insertInlineButton ( this . app , this . buttonSuggestEl . value ) ;
this . close ( ) ;
} ) ;
} ) ;
}
onClose ( ) {
const { contentEl } = this ;
contentEl . empty ( ) ;
}
}
const checkVersion = ( ) => {
const savedVersion = localStorage . getItem ( "buttonsVersion" ) ;
const installedVersion = app . plugins . plugins . buttons . manifest . version ;
if ( parseInt ( savedVersion ) < parseInt ( installedVersion ) ||
savedVersion === null ) {
return true ;
}
return false ;
} ;
const saveVersion = ( ) => {
localStorage . setItem ( "buttonsVersion" , app . plugins . plugins . buttons . manifest . version ) ;
} ;
const releaseNote = `
There is a major update to Buttons coming that will bring much needed improvements . The plugin has been rewritten from scratch to make it easier to squash bugs and add new features . Some existing features will also be removed . This is a warning for all Buttons users to prepare for what may break your buttons .
# # Breaking Changes
- Calculate buttons are deprecated : use template buttons and Templater to do calculations
- Text buttons are deprecated : use template buttons to add text
- Core Templates plugin is no longer supported . Use Templater .
- Button Inheritance is no longer supported ( this doesn ' t include inline buttons , which will now work in Live Preview ) .
- All Buttons now run Templater , no need to add templater true
If you read that list and are like _ "Hol Up! I need all those features" _ . I will be forking the existing Buttons plugin which can be manually installed , but will no longer be supported .
# # Buttons 1.0 Features
The biggest change is a much more reliable and safe plugin that should be easier to bugfix and build new features for . There are a few nice improvements that will come with it :
- Templater processing is greatly improved .
- New note templates can be opened in tabs / windows / splits / not at all
- Button Maker command is rewritten with a cleaner UX
- Inline buttons work in Live Preview
- Button Block IDs are hidden unless the cursor is on the line
- Swap buttons will remember their state when leaving and returning to the notes they are in
- A new documentation site with easier to read docs
- A boatload of bugfixes
# # When can I get it ?
It 's coming soon! I want to release it as part of Obsidian October and am in the final 20% of work. That said, I will release when I' m confident I won ' t totally FUBAR your buttons .
Yours in Buttons ,
shabegom
` ;
const deleteIfExists = async ( ) => {
const file = await app . vault . getAbstractFileByPath ( "/Buttons 1.0 is Coming.md" ) ;
if ( file ) {
await app . vault . delete ( file ) ;
}
} ;
const updateWarning = async ( ) => {
const showReleaseNotes = checkVersion ( ) ;
if ( showReleaseNotes ) {
deleteIfExists ( ) ;
const releaseNotes = await app . vault . create ( "Buttons 1.0 is Coming.md" , releaseNote ) ;
app . workspace
. getLeaf ( true )
. openFile ( releaseNotes , { state : { mode : "preview" } } ) ;
saveVersion ( ) ;
setTimeout ( async ( ) => {
const clearReleaseNotes = app . workspace . on ( "layout-change" , async ( ) => {
await app . vault . delete ( releaseNotes ) ;
app . workspace . offref ( clearReleaseNotes ) ;
} ) ;
} , 1000 ) ;
}
} ;
class ButtonsPlugin extends obsidian . Plugin {
constructor ( ) {
super ( ... arguments ) ;
this . storeEvents = new obsidian . Events ( ) ;
this . indexCount = 0 ;
}
async addButtonInEdit ( app ) {
let widget ;
if ( widget ) {
widget . clear ( ) ;
}
const activeView = app . workspace . getActiveViewOfType ( obsidian . MarkdownView ) ;
if ( activeView ) {
const store = getStore ( app . isMobile ) ;
const buttonsInFile = store . filter ( ( button ) => button . path === activeView . file . path ) ;
this . registerCodeMirror ( ( cm ) => {
buttonsInFile . forEach ( async ( button ) => {
const widgetEl = document . createElement ( "div" ) ;
const storeButton = await getButtonFromStore ( app , {
id : button . id . split ( "-" ) [ 1 ] ,
} ) ;
if ( ! app . isMobile &&
storeButton &&
storeButton ? . args . editview === "true" ) {
widget = cm . addLineWidget ( button . position . end . line + 1 , createButton ( {
app ,
el : widgetEl ,
args : storeButton . args ,
inline : false ,
id : button . id ,
} ) ) ;
}
} ) ;
} ) ;
}
}
async onload ( ) {
this . app . workspace . onLayoutReady ( async ( ) => {
await updateWarning ( ) ;
} ) ;
this . buttonEvents = buttonEventListener ( this . app , addButtonToStore ) ;
this . closedFile = openFileListener ( this . app , this . storeEvents , initializeButtonStore ) ;
this . createButton = createButton ;
this . storeEventsRef = this . storeEvents . on ( "index-complete" , ( ) => {
this . indexCount ++ ;
} ) ;
initializeButtonStore ( this . app , this . storeEvents ) ;
this . buttonEdit = openFileListener ( this . app , this . storeEvents , this . addButtonInEdit . bind ( this ) ) ;
this . addCommand ( {
id : "button-maker" ,
name : "Button Maker" ,
callback : ( ) => new ButtonModal ( this . app ) . open ( ) ,
} ) ;
this . addCommand ( {
id : "inline-button" ,
name : "Insert Inline Button" ,
callback : ( ) => new InlineButtonModal ( this . app ) . open ( ) ,
} ) ;
this . registerMarkdownCodeBlockProcessor ( "button" , async ( source , el , ctx ) => {
// create an object out of the arguments
const file = this . app . vault
. getFiles ( )
. find ( ( f ) => f . path === ctx . sourcePath ) ;
addButtonToStore ( this . app , file ) ;
let args = createArgumentObject ( source ) ;
const storeArgs = await getButtonFromStore ( this . app , args ) ;
args = storeArgs ? storeArgs . args : args ;
const id = storeArgs && storeArgs . id ;
createButton ( { app : this . app , el , args , inline : false , id } ) ;
} ) ;
this . registerMarkdownPostProcessor ( async ( el , ctx ) => {
// Search for <code> blocks inside this element; for each one, look for things of the form `
const codeblocks = el . querySelectorAll ( "code" ) ;
for ( let index = 0 ; index < codeblocks . length ; index ++ ) {
const codeblock = codeblocks . item ( index ) ;
const text = codeblock . innerText . trim ( ) ;
if ( text . startsWith ( "button" ) ) {
const id = text . split ( "button-" ) [ 1 ] . trim ( ) ;
if ( this . indexCount < 2 ) {
this . storeEventsRef = this . storeEvents . on ( "index-complete" , async ( ) => {
this . indexCount ++ ;
const args = await getButtonById ( this . app , id ) ;
if ( args ) {
ctx . addChild ( new InlineButton ( codeblock , this . app , args , id ) ) ;
}
} ) ;
}
else {
const args = await getButtonById ( this . app , id ) ;
if ( args ) {
ctx . addChild ( new InlineButton ( codeblock , this . app , args , id ) ) ;
}
}
}
}
} ) ;
}
onunload ( ) {
this . app . metadataCache . offref ( this . buttonEvents ) ;
this . app . workspace . offref ( this . closedFile ) ;
this . app . workspace . offref ( this . buttonEdit ) ;
this . storeEvents . offref ( this . storeEventsRef ) ;
}
}
class InlineButton extends obsidian . MarkdownRenderChild {
constructor ( el , app , args , id ) {
super ( el ) ;
this . el = el ;
this . app = app ;
this . args = args ;
this . id = id ;
}
async onload ( ) {
const button = createButton ( {
app : this . app ,
el : this . el ,
args : this . args ,
inline : true ,
id : this . id ,
} ) ;
this . el . replaceWith ( button ) ;
}
}
module . exports = ButtonsPlugin ;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsic3JjL2J1dHRvblN0b3JlLnRzIiwic3JjL3V0aWxzLnRzIiwic3JjL2V2ZW50cy50cyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9tYXRoLWV4cHJlc3Npb24tZXZhbHVhdG9yQDEuNC4wL25vZGVfbW9kdWxlcy9tYXRoLWV4cHJlc3Npb24tZXZhbHVhdG9yL3NyYy9tYXRoX2Z1bmN0aW9uLmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL21hdGgtZXhwcmVzc2lvbi1ldmFsdWF0b3JAMS40LjAvbm9kZV9tb2R1bGVzL21hdGgtZXhwcmVzc2lvbi1ldmFsdWF0b3Ivc3JjL2xleGVyLmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL21hdGgtZXhwcmVzc2lvbi1ldmFsdWF0b3JAMS40LjAvbm9kZV9tb2R1bGVzL21hdGgtZXhwcmVzc2lvbi1ldmFsdWF0b3Ivc3JjL3Bvc3RmaXguanMiLCJub2RlX21vZHVsZXMvLnBucG0vbWF0aC1leHByZXNzaW9uLWV2YWx1YXRvckAxLjQuMC9ub2RlX21vZHVsZXMvbWF0aC1leHByZXNzaW9uLWV2YWx1YXRvci9zcmMvcG9zdGZpeF9ldmFsdWF0b3IuanMiLCJub2RlX21vZHVsZXMvLnBucG0vbWF0aC1leHByZXNzaW9uLWV2YWx1YXRvckAxLjQuMC9ub2RlX21vZHVsZXMvbWF0aC1leHByZXNzaW9uLWV2YWx1YXRvci9zcmMvZm9ybXVsYV9ldmFsdWF0b3IuanMiLCJzcmMvaGFuZGxlcnMudHMiLCJzcmMvcGFyc2VyLnRzIiwic3JjL2J1dHRvblR5cGVzLnRzIiwic3JjL2J1dHRvbi50cyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9lbnVtcy5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvZ2V0Tm9kZU5hbWUuanMiLCJub2RlX21vZHVsZXMvLnBucG0vQHBvcHBlcmpzK2NvcmVAMi4xMS42L25vZGVfbW9kdWxlcy9AcG9wcGVyanMvY29yZS9saWIvZG9tLXV0aWxzL2dldFdpbmRvdy5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvaW5zdGFuY2VPZi5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9tb2RpZmllcnMvYXBwbHlTdHlsZXMuanMiLCJub2RlX21vZHVsZXMvLnBucG0vQHBvcHBlcmpzK2NvcmVAMi4xMS42L25vZGVfbW9kdWxlcy9AcG9wcGVyanMvY29yZS9saWIvdXRpbHMvZ2V0QmFzZVBsYWNlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi91dGlscy9tYXRoLmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL0Bwb3BwZXJqcytjb3JlQDIuMTEuNi9ub2RlX21vZHVsZXMvQHBvcHBlcmpzL2NvcmUvbGliL3V0aWxzL3VzZXJBZ2VudC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvaXNMYXlvdXRWaWV3cG9ydC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvZ2V0Qm91bmRpbmdDbGllbnRSZWN0LmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL0Bwb3BwZXJqcytjb3JlQDIuMTEuNi9ub2RlX21vZHVsZXMvQHBvcHBlcmpzL2NvcmUvbGliL2RvbS11dGlscy9nZXRMYXlvdXRSZWN0LmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL0Bwb3BwZXJqcytjb3JlQDIuMTEuNi9ub2RlX21vZHVsZXMvQHBvcHBlcmpzL2NvcmUvbGliL2RvbS11dGlscy9jb250YWlucy5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvZ2V0Q29tcHV0ZWRTdHlsZS5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvaXNUYWJsZUVsZW1lbnQuanMiLCJub2RlX21vZHVsZXMvLnBucG0vQHBvcHBlcmpzK2NvcmVAMi4xMS42L25vZGVfbW9kdWxlcy9AcG9wcGVyanMvY29yZS9saWIvZG9tLXV0aWxzL2dldERvY3VtZW50RWxlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvZ2V0UGFyZW50Tm9kZS5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi9kb20tdXRpbHMvZ2V0T2Zmc2V0UGFyZW50LmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL0Bwb3BwZXJqcytjb3JlQDIuMTEuNi9ub2RlX21vZHVsZXMvQHBvcHBlcmpzL2NvcmUvbGliL3V0aWxzL2dldE1haW5BeGlzRnJvbVBsYWNlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi91dGlscy93aXRoaW4uanMiLCJub2RlX21vZHVsZXMvLnBucG0vQHBvcHBlcmpzK2NvcmVAMi4xMS42L25vZGVfbW9kdWxlcy9AcG9wcGVyanMvY29yZS9saWIvdXRpbHMvZ2V0RnJlc2hTaWRlT2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzLy5wbnBtL0Bwb3BwZXJqcytjb3JlQDIuMTEuNi9ub2RlX21vZHVsZXMvQHBvcHBlcmpzL2NvcmUvbGliL3V0aWxzL21lcmdlUGFkZGluZ09iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy8ucG5wbS9AcG9wcGVyanMrY29yZUAyLjExLjYvbm9kZV9tb2R1bGVzL0Bwb3BwZXJqcy9jb3JlL2xpYi91dGlscy9leHBhbmRUb0hhc2hNYXAuanMiLCJub2RlX21vZHVsZXMvLnBucG0vQHBvcHBlcmpzK2NvcmVAMi4xMS42L25vZGVfbW9kdWxlcy9AcG9wcGVyanMvY29yZS9saWIvbW9kaWZpZXJzL2Fycm93LmpzIiw