Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5960571
ext-emmet.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
50 KB
Referenced Files
None
Subscribers
None
ext-emmet.js
View Options
ace
.
define
(
"ace/snippets"
,[
"require"
,
"exports"
,
"module"
,
"ace/lib/dom"
,
"ace/lib/oop"
,
"ace/lib/event_emitter"
,
"ace/lib/lang"
,
"ace/range"
,
"ace/range_list"
,
"ace/keyboard/hash_handler"
,
"ace/tokenizer"
,
"ace/clipboard"
,
"ace/editor"
],
function
(
require
,
exports
,
module
){
"use strict"
;
var
dom
=
require
(
"./lib/dom"
);
var
oop
=
require
(
"./lib/oop"
);
var
EventEmitter
=
require
(
"./lib/event_emitter"
).
EventEmitter
;
var
lang
=
require
(
"./lib/lang"
);
var
Range
=
require
(
"./range"
).
Range
;
var
RangeList
=
require
(
"./range_list"
).
RangeList
;
var
HashHandler
=
require
(
"./keyboard/hash_handler"
).
HashHandler
;
var
Tokenizer
=
require
(
"./tokenizer"
).
Tokenizer
;
var
clipboard
=
require
(
"./clipboard"
);
var
VARIABLES
=
{
CURRENT_WORD
:
function
(
editor
)
{
return
editor
.
session
.
getTextRange
(
editor
.
session
.
getWordRange
());
},
SELECTION
:
function
(
editor
,
name
,
indentation
)
{
var
text
=
editor
.
session
.
getTextRange
();
if
(
indentation
)
return
text
.
replace
(
/\n\r?([ \t]*\S)/g
,
"\n"
+
indentation
+
"$1"
);
return
text
;
},
CURRENT_LINE
:
function
(
editor
)
{
return
editor
.
session
.
getLine
(
editor
.
getCursorPosition
().
row
);
},
PREV_LINE
:
function
(
editor
)
{
return
editor
.
session
.
getLine
(
editor
.
getCursorPosition
().
row
-
1
);
},
LINE_INDEX
:
function
(
editor
)
{
return
editor
.
getCursorPosition
().
row
;
},
LINE_NUMBER
:
function
(
editor
)
{
return
editor
.
getCursorPosition
().
row
+
1
;
},
SOFT_TABS
:
function
(
editor
)
{
return
editor
.
session
.
getUseSoftTabs
()
?
"YES"
:
"NO"
;
},
TAB_SIZE
:
function
(
editor
)
{
return
editor
.
session
.
getTabSize
();
},
CLIPBOARD
:
function
(
editor
)
{
return
clipboard
.
getText
&&
clipboard
.
getText
();
},
FILENAME
:
function
(
editor
)
{
return
/[^/\\]*$/
.
exec
(
this
.
FILEPATH
(
editor
))[
0
];
},
FILENAME_BASE
:
function
(
editor
)
{
return
/[^/\\]*$/
.
exec
(
this
.
FILEPATH
(
editor
))[
0
].
replace
(
/\.[^.]*$/
,
""
);
},
DIRECTORY
:
function
(
editor
)
{
return
this
.
FILEPATH
(
editor
).
replace
(
/[^/\\]*$/
,
""
);
},
FILEPATH
:
function
(
editor
)
{
return
"/not implemented.txt"
;
},
WORKSPACE_NAME
:
function
()
{
return
"Unknown"
;
},
FULLNAME
:
function
()
{
return
"Unknown"
;
},
BLOCK_COMMENT_START
:
function
(
editor
)
{
var
mode
=
editor
.
session
.
$mode
||
{};
return
mode
.
blockComment
&&
mode
.
blockComment
.
start
||
""
;
},
BLOCK_COMMENT_END
:
function
(
editor
)
{
var
mode
=
editor
.
session
.
$mode
||
{};
return
mode
.
blockComment
&&
mode
.
blockComment
.
end
||
""
;
},
LINE_COMMENT
:
function
(
editor
)
{
var
mode
=
editor
.
session
.
$mode
||
{};
return
mode
.
lineCommentStart
||
""
;
},
CURRENT_YEAR
:
date
.
bind
(
null
,
{
year
:
"numeric"
}),
CURRENT_YEAR_SHORT
:
date
.
bind
(
null
,
{
year
:
"2-digit"
}),
CURRENT_MONTH
:
date
.
bind
(
null
,
{
month
:
"numeric"
}),
CURRENT_MONTH_NAME
:
date
.
bind
(
null
,
{
month
:
"long"
}),
CURRENT_MONTH_NAME_SHORT
:
date
.
bind
(
null
,
{
month
:
"short"
}),
CURRENT_DATE
:
date
.
bind
(
null
,
{
day
:
"2-digit"
}),
CURRENT_DAY_NAME
:
date
.
bind
(
null
,
{
weekday
:
"long"
}),
CURRENT_DAY_NAME_SHORT
:
date
.
bind
(
null
,
{
weekday
:
"short"
}),
CURRENT_HOUR
:
date
.
bind
(
null
,
{
hour
:
"2-digit"
,
hour12
:
false
}),
CURRENT_MINUTE
:
date
.
bind
(
null
,
{
minute
:
"2-digit"
}),
CURRENT_SECOND
:
date
.
bind
(
null
,
{
second
:
"2-digit"
})
};
VARIABLES
.
SELECTED_TEXT
=
VARIABLES
.
SELECTION
;
function
date
(
dateFormat
)
{
var
str
=
new
Date
().
toLocaleString
(
"en-us"
,
dateFormat
);
return
str
.
length
==
1
?
"0"
+
str
:
str
;
}
var
SnippetManager
=
/** @class */
(
function
()
{
function
SnippetManager
()
{
this
.
snippetMap
=
{};
this
.
snippetNameMap
=
{};
this
.
variables
=
VARIABLES
;
}
SnippetManager
.
prototype
.
getTokenizer
=
function
()
{
return
SnippetManager
[
"$tokenizer"
]
||
this
.
createTokenizer
();
};
SnippetManager
.
prototype
.
createTokenizer
=
function
()
{
function
TabstopToken
(
str
)
{
str
=
str
.
substr
(
1
);
if
(
/^\d+$/
.
test
(
str
))
return
[{
tabstopId
:
parseInt
(
str
,
10
)
}];
return
[{
text
:
str
}];
}
function
escape
(
ch
)
{
return
"(?:[^\\\\"
+
ch
+
"]|\\\\.)"
;
}
var
formatMatcher
=
{
regex
:
"/("
+
escape
(
"/"
)
+
"+)/"
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
ts
=
stack
[
0
];
ts
.
fmtString
=
true
;
ts
.
guard
=
val
.
slice
(
1
,
-
1
);
ts
.
flag
=
""
;
return
""
;
},
next
:
"formatString"
};
SnippetManager
[
"$tokenizer"
]
=
new
Tokenizer
({
start
:
[
{
regex
:
/\\./
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
ch
=
val
[
1
];
if
(
ch
==
"}"
&&
stack
.
length
)
{
val
=
ch
;
}
else
if
(
"`$\\"
.
indexOf
(
ch
)
!=
-
1
)
{
val
=
ch
;
}
return
[
val
];
}
},
{
regex
:
/}/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
return
[
stack
.
length
?
stack
.
shift
()
:
val
];
}
},
{
regex
:
/\$(?:\d+|\w+)/
,
onMatch
:
TabstopToken
},
{
regex
:
/\$\{[\dA-Z_a-z]+/
,
onMatch
:
function
(
str
,
state
,
stack
)
{
var
t
=
TabstopToken
(
str
.
substr
(
1
));
stack
.
unshift
(
t
[
0
]);
return
t
;
},
next
:
"snippetVar"
},
{
regex
:
/\n/
,
token
:
"newline"
,
merge
:
false
}
],
snippetVar
:
[
{
regex
:
"\\|"
+
escape
(
"\\|"
)
+
"*\\|"
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
choices
=
val
.
slice
(
1
,
-
1
).
replace
(
/\\[,|\\]|,/g
,
function
(
operator
)
{
return
operator
.
length
==
2
?
operator
[
1
]
:
"\x00"
;
}).
split
(
"\x00"
).
map
(
function
(
value
)
{
return
{
value
:
value
};
});
stack
[
0
].
choices
=
choices
;
return
[
choices
[
0
]];
},
next
:
"start"
},
formatMatcher
,
{
regex
:
"([^:}\\\\]|\\\\.)*:?"
,
token
:
""
,
next
:
"start"
}
],
formatString
:
[
{
regex
:
/:/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
if
(
stack
.
length
&&
stack
[
0
].
expectElse
)
{
stack
[
0
].
expectElse
=
false
;
stack
[
0
].
ifEnd
=
{
elseEnd
:
stack
[
0
]
};
return
[
stack
[
0
].
ifEnd
];
}
return
":"
;
}
},
{
regex
:
/\\./
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
ch
=
val
[
1
];
if
(
ch
==
"}"
&&
stack
.
length
)
val
=
ch
;
else
if
(
"`$\\"
.
indexOf
(
ch
)
!=
-
1
)
val
=
ch
;
else
if
(
ch
==
"n"
)
val
=
"\n"
;
else
if
(
ch
==
"t"
)
val
=
"\t"
;
else
if
(
"ulULE"
.
indexOf
(
ch
)
!=
-
1
)
val
=
{
changeCase
:
ch
,
local
:
ch
>
"a"
};
return
[
val
];
}
},
{
regex
:
"/\\w*}"
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
next
=
stack
.
shift
();
if
(
next
)
next
.
flag
=
val
.
slice
(
1
,
-
1
);
this
.
next
=
next
&&
next
.
tabstopId
?
"start"
:
""
;
return
[
next
||
val
];
},
next
:
"start"
},
{
regex
:
/\$(?:\d+|\w+)/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
return
[{
text
:
val
.
slice
(
1
)
}];
}
},
{
regex
:
/\${\w+/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
token
=
{
text
:
val
.
slice
(
2
)
};
stack
.
unshift
(
token
);
return
[
token
];
},
next
:
"formatStringVar"
},
{
regex
:
/\n/
,
token
:
"newline"
,
merge
:
false
},
{
regex
:
/}/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
next
=
stack
.
shift
();
this
.
next
=
next
&&
next
.
tabstopId
?
"start"
:
""
;
return
[
next
||
val
];
},
next
:
"start"
}
],
formatStringVar
:
[
{
regex
:
/:\/\w+}/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
var
ts
=
stack
[
0
];
ts
.
formatFunction
=
val
.
slice
(
2
,
-
1
);
return
[
stack
.
shift
()];
},
next
:
"formatString"
},
formatMatcher
,
{
regex
:
/:[\?\-+]?/
,
onMatch
:
function
(
val
,
state
,
stack
)
{
if
(
val
[
1
]
==
"+"
)
stack
[
0
].
ifEnd
=
stack
[
0
];
if
(
val
[
1
]
==
"?"
)
stack
[
0
].
expectElse
=
true
;
},
next
:
"formatString"
},
{
regex
:
"([^:}\\\\]|\\\\.)*:?"
,
token
:
""
,
next
:
"formatString"
}
]
});
return
SnippetManager
[
"$tokenizer"
];
};
SnippetManager
.
prototype
.
tokenizeTmSnippet
=
function
(
str
,
startState
)
{
return
this
.
getTokenizer
().
getLineTokens
(
str
,
startState
).
tokens
.
map
(
function
(
x
)
{
return
x
.
value
||
x
;
});
};
SnippetManager
.
prototype
.
getVariableValue
=
function
(
editor
,
name
,
indentation
)
{
if
(
/^\d+$/
.
test
(
name
))
return
(
this
.
variables
.
__
||
{})[
name
]
||
""
;
if
(
/^[A-Z]\d+$/
.
test
(
name
))
return
(
this
.
variables
[
name
[
0
]
+
"__"
]
||
{})[
name
.
substr
(
1
)]
||
""
;
name
=
name
.
replace
(
/^TM_/
,
""
);
if
(
!
this
.
variables
.
hasOwnProperty
(
name
))
return
""
;
var
value
=
this
.
variables
[
name
];
if
(
typeof
value
==
"function"
)
value
=
this
.
variables
[
name
](
editor
,
name
,
indentation
);
return
value
==
null
?
""
:
value
;
};
SnippetManager
.
prototype
.
tmStrFormat
=
function
(
str
,
ch
,
editor
)
{
if
(
!
ch
.
fmt
)
return
str
;
var
flag
=
ch
.
flag
||
""
;
var
re
=
ch
.
guard
;
re
=
new
RegExp
(
re
,
flag
.
replace
(
/[^gim]/g
,
""
));
var
fmtTokens
=
typeof
ch
.
fmt
==
"string"
?
this
.
tokenizeTmSnippet
(
ch
.
fmt
,
"formatString"
)
:
ch
.
fmt
;
var
_self
=
this
;
var
formatted
=
str
.
replace
(
re
,
function
()
{
var
oldArgs
=
_self
.
variables
.
__
;
_self
.
variables
.
__
=
[].
slice
.
call
(
arguments
);
var
fmtParts
=
_self
.
resolveVariables
(
fmtTokens
,
editor
);
var
gChangeCase
=
"E"
;
for
(
var
i
=
0
;
i
<
fmtParts
.
length
;
i
++
)
{
var
ch
=
fmtParts
[
i
];
if
(
typeof
ch
==
"object"
)
{
fmtParts
[
i
]
=
""
;
if
(
ch
.
changeCase
&&
ch
.
local
)
{
var
next
=
fmtParts
[
i
+
1
];
if
(
next
&&
typeof
next
==
"string"
)
{
if
(
ch
.
changeCase
==
"u"
)
fmtParts
[
i
]
=
next
[
0
].
toUpperCase
();
else
fmtParts
[
i
]
=
next
[
0
].
toLowerCase
();
fmtParts
[
i
+
1
]
=
next
.
substr
(
1
);
}
}
else
if
(
ch
.
changeCase
)
{
gChangeCase
=
ch
.
changeCase
;
}
}
else
if
(
gChangeCase
==
"U"
)
{
fmtParts
[
i
]
=
ch
.
toUpperCase
();
}
else
if
(
gChangeCase
==
"L"
)
{
fmtParts
[
i
]
=
ch
.
toLowerCase
();
}
}
_self
.
variables
.
__
=
oldArgs
;
return
fmtParts
.
join
(
""
);
});
return
formatted
;
};
SnippetManager
.
prototype
.
tmFormatFunction
=
function
(
str
,
ch
,
editor
)
{
if
(
ch
.
formatFunction
==
"upcase"
)
return
str
.
toUpperCase
();
if
(
ch
.
formatFunction
==
"downcase"
)
return
str
.
toLowerCase
();
return
str
;
};
SnippetManager
.
prototype
.
resolveVariables
=
function
(
snippet
,
editor
)
{
var
result
=
[];
var
indentation
=
""
;
var
afterNewLine
=
true
;
for
(
var
i
=
0
;
i
<
snippet
.
length
;
i
++
)
{
var
ch
=
snippet
[
i
];
if
(
typeof
ch
==
"string"
)
{
result
.
push
(
ch
);
if
(
ch
==
"\n"
)
{
afterNewLine
=
true
;
indentation
=
""
;
}
else
if
(
afterNewLine
)
{
indentation
=
/^\t*/
.
exec
(
ch
)[
0
];
afterNewLine
=
/\S/
.
test
(
ch
);
}
continue
;
}
if
(
!
ch
)
continue
;
afterNewLine
=
false
;
if
(
ch
.
fmtString
)
{
var
j
=
snippet
.
indexOf
(
ch
,
i
+
1
);
if
(
j
==
-
1
)
j
=
snippet
.
length
;
ch
.
fmt
=
snippet
.
slice
(
i
+
1
,
j
);
i
=
j
;
}
if
(
ch
.
text
)
{
var
value
=
this
.
getVariableValue
(
editor
,
ch
.
text
,
indentation
)
+
""
;
if
(
ch
.
fmtString
)
value
=
this
.
tmStrFormat
(
value
,
ch
,
editor
);
if
(
ch
.
formatFunction
)
value
=
this
.
tmFormatFunction
(
value
,
ch
,
editor
);
if
(
value
&&
!
ch
.
ifEnd
)
{
result
.
push
(
value
);
gotoNext
(
ch
);
}
else
if
(
!
value
&&
ch
.
ifEnd
)
{
gotoNext
(
ch
.
ifEnd
);
}
}
else
if
(
ch
.
elseEnd
)
{
gotoNext
(
ch
.
elseEnd
);
}
else
if
(
ch
.
tabstopId
!=
null
)
{
result
.
push
(
ch
);
}
else
if
(
ch
.
changeCase
!=
null
)
{
result
.
push
(
ch
);
}
}
function
gotoNext
(
ch
)
{
var
i1
=
snippet
.
indexOf
(
ch
,
i
+
1
);
if
(
i1
!=
-
1
)
i
=
i1
;
}
return
result
;
};
SnippetManager
.
prototype
.
getDisplayTextForSnippet
=
function
(
editor
,
snippetText
)
{
var
processedSnippet
=
processSnippetText
.
call
(
this
,
editor
,
snippetText
);
return
processedSnippet
.
text
;
};
SnippetManager
.
prototype
.
insertSnippetForSelection
=
function
(
editor
,
snippetText
,
options
)
{
if
(
options
===
void
0
)
{
options
=
{};
}
var
processedSnippet
=
processSnippetText
.
call
(
this
,
editor
,
snippetText
,
options
);
var
range
=
editor
.
getSelectionRange
();
var
end
=
editor
.
session
.
replace
(
range
,
processedSnippet
.
text
);
var
tabstopManager
=
new
TabstopManager
(
editor
);
var
selectionId
=
editor
.
inVirtualSelectionMode
&&
editor
.
selection
.
index
;
tabstopManager
.
addTabstops
(
processedSnippet
.
tabstops
,
range
.
start
,
end
,
selectionId
);
};
SnippetManager
.
prototype
.
insertSnippet
=
function
(
editor
,
snippetText
,
options
)
{
if
(
options
===
void
0
)
{
options
=
{};
}
var
self
=
this
;
if
(
editor
.
inVirtualSelectionMode
)
return
self
.
insertSnippetForSelection
(
editor
,
snippetText
,
options
);
editor
.
forEachSelection
(
function
()
{
self
.
insertSnippetForSelection
(
editor
,
snippetText
,
options
);
},
null
,
{
keepOrder
:
true
});
if
(
editor
.
tabstopManager
)
editor
.
tabstopManager
.
tabNext
();
};
SnippetManager
.
prototype
.
$getScope
=
function
(
editor
)
{
var
scope
=
editor
.
session
.
$mode
.
$id
||
""
;
scope
=
scope
.
split
(
"/"
).
pop
();
if
(
scope
===
"html"
||
scope
===
"php"
)
{
if
(
scope
===
"php"
&&
!
editor
.
session
.
$mode
.
inlinePhp
)
scope
=
"html"
;
var
c
=
editor
.
getCursorPosition
();
var
state
=
editor
.
session
.
getState
(
c
.
row
);
if
(
typeof
state
===
"object"
)
{
state
=
state
[
0
];
}
if
(
state
.
substring
)
{
if
(
state
.
substring
(
0
,
3
)
==
"js-"
)
scope
=
"javascript"
;
else
if
(
state
.
substring
(
0
,
4
)
==
"css-"
)
scope
=
"css"
;
else
if
(
state
.
substring
(
0
,
4
)
==
"php-"
)
scope
=
"php"
;
}
}
return
scope
;
};
SnippetManager
.
prototype
.
getActiveScopes
=
function
(
editor
)
{
var
scope
=
this
.
$getScope
(
editor
);
var
scopes
=
[
scope
];
var
snippetMap
=
this
.
snippetMap
;
if
(
snippetMap
[
scope
]
&&
snippetMap
[
scope
].
includeScopes
)
{
scopes
.
push
.
apply
(
scopes
,
snippetMap
[
scope
].
includeScopes
);
}
scopes
.
push
(
"_"
);
return
scopes
;
};
SnippetManager
.
prototype
.
expandWithTab
=
function
(
editor
,
options
)
{
var
self
=
this
;
var
result
=
editor
.
forEachSelection
(
function
()
{
return
self
.
expandSnippetForSelection
(
editor
,
options
);
},
null
,
{
keepOrder
:
true
});
if
(
result
&&
editor
.
tabstopManager
)
editor
.
tabstopManager
.
tabNext
();
return
result
;
};
SnippetManager
.
prototype
.
expandSnippetForSelection
=
function
(
editor
,
options
)
{
var
cursor
=
editor
.
getCursorPosition
();
var
line
=
editor
.
session
.
getLine
(
cursor
.
row
);
var
before
=
line
.
substring
(
0
,
cursor
.
column
);
var
after
=
line
.
substr
(
cursor
.
column
);
var
snippetMap
=
this
.
snippetMap
;
var
snippet
;
this
.
getActiveScopes
(
editor
).
some
(
function
(
scope
)
{
var
snippets
=
snippetMap
[
scope
];
if
(
snippets
)
snippet
=
this
.
findMatchingSnippet
(
snippets
,
before
,
after
);
return
!!
snippet
;
},
this
);
if
(
!
snippet
)
return
false
;
if
(
options
&&
options
.
dryRun
)
return
true
;
editor
.
session
.
doc
.
removeInLine
(
cursor
.
row
,
cursor
.
column
-
snippet
.
replaceBefore
.
length
,
cursor
.
column
+
snippet
.
replaceAfter
.
length
);
this
.
variables
.
M__
=
snippet
.
matchBefore
;
this
.
variables
.
T__
=
snippet
.
matchAfter
;
this
.
insertSnippetForSelection
(
editor
,
snippet
.
content
);
this
.
variables
.
M__
=
this
.
variables
.
T__
=
null
;
return
true
;
};
SnippetManager
.
prototype
.
findMatchingSnippet
=
function
(
snippetList
,
before
,
after
)
{
for
(
var
i
=
snippetList
.
length
;
i
--
;)
{
var
s
=
snippetList
[
i
];
if
(
s
.
startRe
&&
!
s
.
startRe
.
test
(
before
))
continue
;
if
(
s
.
endRe
&&
!
s
.
endRe
.
test
(
after
))
continue
;
if
(
!
s
.
startRe
&&
!
s
.
endRe
)
continue
;
s
.
matchBefore
=
s
.
startRe
?
s
.
startRe
.
exec
(
before
)
:
[
""
];
s
.
matchAfter
=
s
.
endRe
?
s
.
endRe
.
exec
(
after
)
:
[
""
];
s
.
replaceBefore
=
s
.
triggerRe
?
s
.
triggerRe
.
exec
(
before
)[
0
]
:
""
;
s
.
replaceAfter
=
s
.
endTriggerRe
?
s
.
endTriggerRe
.
exec
(
after
)[
0
]
:
""
;
return
s
;
}
};
SnippetManager
.
prototype
.
register
=
function
(
snippets
,
scope
)
{
var
snippetMap
=
this
.
snippetMap
;
var
snippetNameMap
=
this
.
snippetNameMap
;
var
self
=
this
;
if
(
!
snippets
)
snippets
=
[];
function
wrapRegexp
(
src
)
{
if
(
src
&&
!
/^\^?\(.*\)\$?$|^\\b$/
.
test
(
src
))
src
=
"(?:"
+
src
+
")"
;
return
src
||
""
;
}
function
guardedRegexp
(
re
,
guard
,
opening
)
{
re
=
wrapRegexp
(
re
);
guard
=
wrapRegexp
(
guard
);
if
(
opening
)
{
re
=
guard
+
re
;
if
(
re
&&
re
[
re
.
length
-
1
]
!=
"$"
)
re
=
re
+
"$"
;
}
else
{
re
=
re
+
guard
;
if
(
re
&&
re
[
0
]
!=
"^"
)
re
=
"^"
+
re
;
}
return
new
RegExp
(
re
);
}
function
addSnippet
(
s
)
{
if
(
!
s
.
scope
)
s
.
scope
=
scope
||
"_"
;
scope
=
s
.
scope
;
if
(
!
snippetMap
[
scope
])
{
snippetMap
[
scope
]
=
[];
snippetNameMap
[
scope
]
=
{};
}
var
map
=
snippetNameMap
[
scope
];
if
(
s
.
name
)
{
var
old
=
map
[
s
.
name
];
if
(
old
)
self
.
unregister
(
old
);
map
[
s
.
name
]
=
s
;
}
snippetMap
[
scope
].
push
(
s
);
if
(
s
.
prefix
)
s
.
tabTrigger
=
s
.
prefix
;
if
(
!
s
.
content
&&
s
.
body
)
s
.
content
=
Array
.
isArray
(
s
.
body
)
?
s
.
body
.
join
(
"\n"
)
:
s
.
body
;
if
(
s
.
tabTrigger
&&
!
s
.
trigger
)
{
if
(
!
s
.
guard
&&
/^\w/
.
test
(
s
.
tabTrigger
))
s
.
guard
=
"\\b"
;
s
.
trigger
=
lang
.
escapeRegExp
(
s
.
tabTrigger
);
}
if
(
!
s
.
trigger
&&
!
s
.
guard
&&
!
s
.
endTrigger
&&
!
s
.
endGuard
)
return
;
s
.
startRe
=
guardedRegexp
(
s
.
trigger
,
s
.
guard
,
true
);
s
.
triggerRe
=
new
RegExp
(
s
.
trigger
);
s
.
endRe
=
guardedRegexp
(
s
.
endTrigger
,
s
.
endGuard
,
true
);
s
.
endTriggerRe
=
new
RegExp
(
s
.
endTrigger
);
}
if
(
Array
.
isArray
(
snippets
))
{
snippets
.
forEach
(
addSnippet
);
}
else
{
Object
.
keys
(
snippets
).
forEach
(
function
(
key
)
{
addSnippet
(
snippets
[
key
]);
});
}
this
.
_signal
(
"registerSnippets"
,
{
scope
:
scope
});
};
SnippetManager
.
prototype
.
unregister
=
function
(
snippets
,
scope
)
{
var
snippetMap
=
this
.
snippetMap
;
var
snippetNameMap
=
this
.
snippetNameMap
;
function
removeSnippet
(
s
)
{
var
nameMap
=
snippetNameMap
[
s
.
scope
||
scope
];
if
(
nameMap
&&
nameMap
[
s
.
name
])
{
delete
nameMap
[
s
.
name
];
var
map
=
snippetMap
[
s
.
scope
||
scope
];
var
i
=
map
&&
map
.
indexOf
(
s
);
if
(
i
>=
0
)
map
.
splice
(
i
,
1
);
}
}
if
(
snippets
.
content
)
removeSnippet
(
snippets
);
else
if
(
Array
.
isArray
(
snippets
))
snippets
.
forEach
(
removeSnippet
);
};
SnippetManager
.
prototype
.
parseSnippetFile
=
function
(
str
)
{
str
=
str
.
replace
(
/\r/g
,
""
);
var
list
=
[],
/**@type{Snippet}*/
snippet
=
{};
var
re
=
/^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm
;
var
m
;
while
(
m
=
re
.
exec
(
str
))
{
if
(
m
[
1
])
{
try
{
snippet
=
JSON
.
parse
(
m
[
1
]);
list
.
push
(
snippet
);
}
catch
(
e
)
{
}
}
if
(
m
[
4
])
{
snippet
.
content
=
m
[
4
].
replace
(
/^\t/gm
,
""
);
list
.
push
(
snippet
);
snippet
=
{};
}
else
{
var
key
=
m
[
2
],
val
=
m
[
3
];
if
(
key
==
"regex"
)
{
var
guardRe
=
/\/((?:[^\/\\]|\\.)*)|$/g
;
snippet
.
guard
=
guardRe
.
exec
(
val
)[
1
];
snippet
.
trigger
=
guardRe
.
exec
(
val
)[
1
];
snippet
.
endTrigger
=
guardRe
.
exec
(
val
)[
1
];
snippet
.
endGuard
=
guardRe
.
exec
(
val
)[
1
];
}
else
if
(
key
==
"snippet"
)
{
snippet
.
tabTrigger
=
val
.
match
(
/^\S*/
)[
0
];
if
(
!
snippet
.
name
)
snippet
.
name
=
val
;
}
else
if
(
key
)
{
snippet
[
key
]
=
val
;
}
}
}
return
list
;
};
SnippetManager
.
prototype
.
getSnippetByName
=
function
(
name
,
editor
)
{
var
snippetMap
=
this
.
snippetNameMap
;
var
snippet
;
this
.
getActiveScopes
(
editor
).
some
(
function
(
scope
)
{
var
snippets
=
snippetMap
[
scope
];
if
(
snippets
)
snippet
=
snippets
[
name
];
return
!!
snippet
;
},
this
);
return
snippet
;
};
return
SnippetManager
;
}());
oop
.
implement
(
SnippetManager
.
prototype
,
EventEmitter
);
var
processSnippetText
=
function
(
editor
,
snippetText
,
options
)
{
if
(
options
===
void
0
)
{
options
=
{};
}
var
cursor
=
editor
.
getCursorPosition
();
var
line
=
editor
.
session
.
getLine
(
cursor
.
row
);
var
tabString
=
editor
.
session
.
getTabString
();
var
indentString
=
line
.
match
(
/^\s*/
)[
0
];
if
(
cursor
.
column
<
indentString
.
length
)
indentString
=
indentString
.
slice
(
0
,
cursor
.
column
);
snippetText
=
snippetText
.
replace
(
/\r/g
,
""
);
var
tokens
=
this
.
tokenizeTmSnippet
(
snippetText
);
tokens
=
this
.
resolveVariables
(
tokens
,
editor
);
tokens
=
tokens
.
map
(
function
(
x
)
{
if
(
x
==
"\n"
&&
!
options
.
excludeExtraIndent
)
return
x
+
indentString
;
if
(
typeof
x
==
"string"
)
return
x
.
replace
(
/\t/g
,
tabString
);
return
x
;
});
var
tabstops
=
[];
tokens
.
forEach
(
function
(
p
,
i
)
{
if
(
typeof
p
!=
"object"
)
return
;
var
id
=
p
.
tabstopId
;
var
ts
=
tabstops
[
id
];
if
(
!
ts
)
{
ts
=
tabstops
[
id
]
=
[];
ts
.
index
=
id
;
ts
.
value
=
""
;
ts
.
parents
=
{};
}
if
(
ts
.
indexOf
(
p
)
!==
-
1
)
return
;
if
(
p
.
choices
&&
!
ts
.
choices
)
ts
.
choices
=
p
.
choices
;
ts
.
push
(
p
);
var
i1
=
tokens
.
indexOf
(
p
,
i
+
1
);
if
(
i1
===
-
1
)
return
;
var
value
=
tokens
.
slice
(
i
+
1
,
i1
);
var
isNested
=
value
.
some
(
function
(
t
)
{
return
typeof
t
===
"object"
;
});
if
(
isNested
&&
!
ts
.
value
)
{
ts
.
value
=
value
;
}
else
if
(
value
.
length
&&
(
!
ts
.
value
||
typeof
ts
.
value
!==
"string"
))
{
ts
.
value
=
value
.
join
(
""
);
}
});
tabstops
.
forEach
(
function
(
ts
)
{
ts
.
length
=
0
;
});
var
expanding
=
{};
function
copyValue
(
val
)
{
var
copy
=
[];
for
(
var
i
=
0
;
i
<
val
.
length
;
i
++
)
{
var
p
=
val
[
i
];
if
(
typeof
p
==
"object"
)
{
if
(
expanding
[
p
.
tabstopId
])
continue
;
var
j
=
val
.
lastIndexOf
(
p
,
i
-
1
);
p
=
copy
[
j
]
||
{
tabstopId
:
p
.
tabstopId
};
}
copy
[
i
]
=
p
;
}
return
copy
;
}
for
(
var
i
=
0
;
i
<
tokens
.
length
;
i
++
)
{
var
p
=
tokens
[
i
];
if
(
typeof
p
!=
"object"
)
continue
;
var
id
=
p
.
tabstopId
;
var
ts
=
tabstops
[
id
];
var
i1
=
tokens
.
indexOf
(
p
,
i
+
1
);
if
(
expanding
[
id
])
{
if
(
expanding
[
id
]
===
p
)
{
delete
expanding
[
id
];
Object
.
keys
(
expanding
).
forEach
(
function
(
parentId
)
{
ts
.
parents
[
parentId
]
=
true
;
});
}
continue
;
}
expanding
[
id
]
=
p
;
var
value
=
ts
.
value
;
if
(
typeof
value
!==
"string"
)
value
=
copyValue
(
value
);
else
if
(
p
.
fmt
)
value
=
this
.
tmStrFormat
(
value
,
p
,
editor
);
tokens
.
splice
.
apply
(
tokens
,
[
i
+
1
,
Math
.
max
(
0
,
i1
-
i
)].
concat
(
value
,
p
));
if
(
ts
.
indexOf
(
p
)
===
-
1
)
ts
.
push
(
p
);
}
var
row
=
0
,
column
=
0
;
var
text
=
""
;
tokens
.
forEach
(
function
(
t
)
{
if
(
typeof
t
===
"string"
)
{
var
lines
=
t
.
split
(
"\n"
);
if
(
lines
.
length
>
1
)
{
column
=
lines
[
lines
.
length
-
1
].
length
;
row
+=
lines
.
length
-
1
;
}
else
column
+=
t
.
length
;
text
+=
t
;
}
else
if
(
t
)
{
if
(
!
t
.
start
)
t
.
start
=
{
row
:
row
,
column
:
column
};
else
t
.
end
=
{
row
:
row
,
column
:
column
};
}
});
return
{
text
:
text
,
tabstops
:
tabstops
,
tokens
:
tokens
};
};
var
TabstopManager
=
/** @class */
(
function
()
{
function
TabstopManager
(
editor
)
{
this
.
index
=
0
;
this
.
ranges
=
[];
this
.
tabstops
=
[];
if
(
editor
.
tabstopManager
)
return
editor
.
tabstopManager
;
editor
.
tabstopManager
=
this
;
this
.
$onChange
=
this
.
onChange
.
bind
(
this
);
this
.
$onChangeSelection
=
lang
.
delayedCall
(
this
.
onChangeSelection
.
bind
(
this
)).
schedule
;
this
.
$onChangeSession
=
this
.
onChangeSession
.
bind
(
this
);
this
.
$onAfterExec
=
this
.
onAfterExec
.
bind
(
this
);
this
.
attach
(
editor
);
}
TabstopManager
.
prototype
.
attach
=
function
(
editor
)
{
this
.
$openTabstops
=
null
;
this
.
selectedTabstop
=
null
;
this
.
editor
=
editor
;
this
.
session
=
editor
.
session
;
this
.
editor
.
on
(
"change"
,
this
.
$onChange
);
this
.
editor
.
on
(
"changeSelection"
,
this
.
$onChangeSelection
);
this
.
editor
.
on
(
"changeSession"
,
this
.
$onChangeSession
);
this
.
editor
.
commands
.
on
(
"afterExec"
,
this
.
$onAfterExec
);
this
.
editor
.
keyBinding
.
addKeyboardHandler
(
this
.
keyboardHandler
);
};
TabstopManager
.
prototype
.
detach
=
function
()
{
this
.
tabstops
.
forEach
(
this
.
removeTabstopMarkers
,
this
);
this
.
ranges
.
length
=
0
;
this
.
tabstops
.
length
=
0
;
this
.
selectedTabstop
=
null
;
this
.
editor
.
off
(
"change"
,
this
.
$onChange
);
this
.
editor
.
off
(
"changeSelection"
,
this
.
$onChangeSelection
);
this
.
editor
.
off
(
"changeSession"
,
this
.
$onChangeSession
);
this
.
editor
.
commands
.
off
(
"afterExec"
,
this
.
$onAfterExec
);
this
.
editor
.
keyBinding
.
removeKeyboardHandler
(
this
.
keyboardHandler
);
this
.
editor
.
tabstopManager
=
null
;
this
.
session
=
null
;
this
.
editor
=
null
;
};
TabstopManager
.
prototype
.
onChange
=
function
(
delta
)
{
var
isRemove
=
delta
.
action
[
0
]
==
"r"
;
var
selectedTabstop
=
this
.
selectedTabstop
||
{};
var
parents
=
selectedTabstop
.
parents
||
{};
var
tabstops
=
this
.
tabstops
.
slice
();
for
(
var
i
=
0
;
i
<
tabstops
.
length
;
i
++
)
{
var
ts
=
tabstops
[
i
];
var
active
=
ts
==
selectedTabstop
||
parents
[
ts
.
index
];
ts
.
rangeList
.
$bias
=
active
?
0
:
1
;
if
(
delta
.
action
==
"remove"
&&
ts
!==
selectedTabstop
)
{
var
parentActive
=
ts
.
parents
&&
ts
.
parents
[
selectedTabstop
.
index
];
var
startIndex
=
ts
.
rangeList
.
pointIndex
(
delta
.
start
,
parentActive
);
startIndex
=
startIndex
<
0
?
-
startIndex
-
1
:
startIndex
+
1
;
var
endIndex
=
ts
.
rangeList
.
pointIndex
(
delta
.
end
,
parentActive
);
endIndex
=
endIndex
<
0
?
-
endIndex
-
1
:
endIndex
-
1
;
var
toRemove
=
ts
.
rangeList
.
ranges
.
slice
(
startIndex
,
endIndex
);
for
(
var
j
=
0
;
j
<
toRemove
.
length
;
j
++
)
this
.
removeRange
(
toRemove
[
j
]);
}
ts
.
rangeList
.
$onChange
(
delta
);
}
var
session
=
this
.
session
;
if
(
!
this
.
$inChange
&&
isRemove
&&
session
.
getLength
()
==
1
&&
!
session
.
getValue
())
this
.
detach
();
};
TabstopManager
.
prototype
.
updateLinkedFields
=
function
()
{
var
ts
=
this
.
selectedTabstop
;
if
(
!
ts
||
!
ts
.
hasLinkedRanges
||
!
ts
.
firstNonLinked
)
return
;
this
.
$inChange
=
true
;
var
session
=
this
.
session
;
var
text
=
session
.
getTextRange
(
ts
.
firstNonLinked
);
for
(
var
i
=
0
;
i
<
ts
.
length
;
i
++
)
{
var
range
=
ts
[
i
];
if
(
!
range
.
linked
)
continue
;
var
original
=
range
.
original
;
var
fmt
=
exports
.
snippetManager
.
tmStrFormat
(
text
,
original
,
this
.
editor
);
session
.
replace
(
range
,
fmt
);
}
this
.
$inChange
=
false
;
};
TabstopManager
.
prototype
.
onAfterExec
=
function
(
e
)
{
if
(
e
.
command
&&
!
e
.
command
.
readOnly
)
this
.
updateLinkedFields
();
};
TabstopManager
.
prototype
.
onChangeSelection
=
function
()
{
if
(
!
this
.
editor
)
return
;
var
lead
=
this
.
editor
.
selection
.
lead
;
var
anchor
=
this
.
editor
.
selection
.
anchor
;
var
isEmpty
=
this
.
editor
.
selection
.
isEmpty
();
for
(
var
i
=
0
;
i
<
this
.
ranges
.
length
;
i
++
)
{
if
(
this
.
ranges
[
i
].
linked
)
continue
;
var
containsLead
=
this
.
ranges
[
i
].
contains
(
lead
.
row
,
lead
.
column
);
var
containsAnchor
=
isEmpty
||
this
.
ranges
[
i
].
contains
(
anchor
.
row
,
anchor
.
column
);
if
(
containsLead
&&
containsAnchor
)
return
;
}
this
.
detach
();
};
TabstopManager
.
prototype
.
onChangeSession
=
function
()
{
this
.
detach
();
};
TabstopManager
.
prototype
.
tabNext
=
function
(
dir
)
{
var
max
=
this
.
tabstops
.
length
;
var
index
=
this
.
index
+
(
dir
||
1
);
index
=
Math
.
min
(
Math
.
max
(
index
,
1
),
max
);
if
(
index
==
max
)
index
=
0
;
this
.
selectTabstop
(
index
);
this
.
updateTabstopMarkers
();
if
(
index
===
0
)
{
this
.
detach
();
}
};
TabstopManager
.
prototype
.
selectTabstop
=
function
(
index
)
{
this
.
$openTabstops
=
null
;
var
ts
=
this
.
tabstops
[
this
.
index
];
if
(
ts
)
this
.
addTabstopMarkers
(
ts
);
this
.
index
=
index
;
ts
=
this
.
tabstops
[
this
.
index
];
if
(
!
ts
||
!
ts
.
length
)
return
;
this
.
selectedTabstop
=
ts
;
var
range
=
ts
.
firstNonLinked
||
ts
;
if
(
ts
.
choices
)
range
.
cursor
=
range
.
start
;
if
(
!
this
.
editor
.
inVirtualSelectionMode
)
{
var
sel
=
this
.
editor
.
multiSelect
;
sel
.
toSingleRange
(
range
);
for
(
var
i
=
0
;
i
<
ts
.
length
;
i
++
)
{
if
(
ts
.
hasLinkedRanges
&&
ts
[
i
].
linked
)
continue
;
sel
.
addRange
(
ts
[
i
].
clone
(),
true
);
}
}
else
{
this
.
editor
.
selection
.
fromOrientedRange
(
range
);
}
this
.
editor
.
keyBinding
.
addKeyboardHandler
(
this
.
keyboardHandler
);
if
(
this
.
selectedTabstop
&&
this
.
selectedTabstop
.
choices
)
this
.
editor
.
execCommand
(
"startAutocomplete"
,
{
matches
:
this
.
selectedTabstop
.
choices
});
};
TabstopManager
.
prototype
.
addTabstops
=
function
(
tabstops
,
start
,
end
)
{
var
useLink
=
this
.
useLink
||
!
this
.
editor
.
getOption
(
"enableMultiselect"
);
if
(
!
this
.
$openTabstops
)
this
.
$openTabstops
=
[];
if
(
!
tabstops
[
0
])
{
var
p
=
Range
.
fromPoints
(
end
,
end
);
moveRelative
(
p
.
start
,
start
);
moveRelative
(
p
.
end
,
start
);
tabstops
[
0
]
=
[
p
];
tabstops
[
0
].
index
=
0
;
}
var
i
=
this
.
index
;
var
arg
=
[
i
+
1
,
0
];
var
ranges
=
this
.
ranges
;
var
snippetId
=
this
.
snippetId
=
(
this
.
snippetId
||
0
)
+
1
;
tabstops
.
forEach
(
function
(
ts
,
index
)
{
var
dest
=
this
.
$openTabstops
[
index
]
||
ts
;
dest
.
snippetId
=
snippetId
;
for
(
var
i
=
0
;
i
<
ts
.
length
;
i
++
)
{
var
p
=
ts
[
i
];
var
range
=
Range
.
fromPoints
(
p
.
start
,
p
.
end
||
p
.
start
);
movePoint
(
range
.
start
,
start
);
movePoint
(
range
.
end
,
start
);
range
.
original
=
p
;
range
.
tabstop
=
dest
;
ranges
.
push
(
range
);
if
(
dest
!=
ts
)
dest
.
unshift
(
range
);
else
dest
[
i
]
=
range
;
if
(
p
.
fmtString
||
(
dest
.
firstNonLinked
&&
useLink
))
{
range
.
linked
=
true
;
dest
.
hasLinkedRanges
=
true
;
}
else
if
(
!
dest
.
firstNonLinked
)
dest
.
firstNonLinked
=
range
;
}
if
(
!
dest
.
firstNonLinked
)
dest
.
hasLinkedRanges
=
false
;
if
(
dest
===
ts
)
{
arg
.
push
(
dest
);
this
.
$openTabstops
[
index
]
=
dest
;
}
this
.
addTabstopMarkers
(
dest
);
dest
.
rangeList
=
dest
.
rangeList
||
new
RangeList
();
dest
.
rangeList
.
$bias
=
0
;
dest
.
rangeList
.
addList
(
dest
);
},
this
);
if
(
arg
.
length
>
2
)
{
if
(
this
.
tabstops
.
length
)
arg
.
push
(
arg
.
splice
(
2
,
1
)[
0
]);
this
.
tabstops
.
splice
.
apply
(
this
.
tabstops
,
arg
);
}
};
TabstopManager
.
prototype
.
addTabstopMarkers
=
function
(
ts
)
{
var
session
=
this
.
session
;
ts
.
forEach
(
function
(
range
)
{
if
(
!
range
.
markerId
)
range
.
markerId
=
session
.
addMarker
(
range
,
"ace_snippet-marker"
,
"text"
);
});
};
TabstopManager
.
prototype
.
removeTabstopMarkers
=
function
(
ts
)
{
var
session
=
this
.
session
;
ts
.
forEach
(
function
(
range
)
{
session
.
removeMarker
(
range
.
markerId
);
range
.
markerId
=
null
;
});
};
TabstopManager
.
prototype
.
updateTabstopMarkers
=
function
()
{
if
(
!
this
.
selectedTabstop
)
return
;
var
currentSnippetId
=
this
.
selectedTabstop
.
snippetId
;
if
(
this
.
selectedTabstop
.
index
===
0
)
{
currentSnippetId
--
;
}
this
.
tabstops
.
forEach
(
function
(
ts
)
{
if
(
ts
.
snippetId
===
currentSnippetId
)
this
.
addTabstopMarkers
(
ts
);
else
this
.
removeTabstopMarkers
(
ts
);
},
this
);
};
TabstopManager
.
prototype
.
removeRange
=
function
(
range
)
{
var
i
=
range
.
tabstop
.
indexOf
(
range
);
if
(
i
!=
-
1
)
range
.
tabstop
.
splice
(
i
,
1
);
i
=
this
.
ranges
.
indexOf
(
range
);
if
(
i
!=
-
1
)
this
.
ranges
.
splice
(
i
,
1
);
i
=
range
.
tabstop
.
rangeList
.
ranges
.
indexOf
(
range
);
if
(
i
!=
-
1
)
range
.
tabstop
.
splice
(
i
,
1
);
this
.
session
.
removeMarker
(
range
.
markerId
);
if
(
!
range
.
tabstop
.
length
)
{
i
=
this
.
tabstops
.
indexOf
(
range
.
tabstop
);
if
(
i
!=
-
1
)
this
.
tabstops
.
splice
(
i
,
1
);
if
(
!
this
.
tabstops
.
length
)
this
.
detach
();
}
};
return
TabstopManager
;
}());
TabstopManager
.
prototype
.
keyboardHandler
=
new
HashHandler
();
TabstopManager
.
prototype
.
keyboardHandler
.
bindKeys
({
"Tab"
:
function
(
editor
)
{
if
(
exports
.
snippetManager
&&
exports
.
snippetManager
.
expandWithTab
(
editor
))
return
;
editor
.
tabstopManager
.
tabNext
(
1
);
editor
.
renderer
.
scrollCursorIntoView
();
},
"Shift-Tab"
:
function
(
editor
)
{
editor
.
tabstopManager
.
tabNext
(
-
1
);
editor
.
renderer
.
scrollCursorIntoView
();
},
"Esc"
:
function
(
editor
)
{
editor
.
tabstopManager
.
detach
();
}
});
var
movePoint
=
function
(
point
,
diff
)
{
if
(
point
.
row
==
0
)
point
.
column
+=
diff
.
column
;
point
.
row
+=
diff
.
row
;
};
var
moveRelative
=
function
(
point
,
start
)
{
if
(
point
.
row
==
start
.
row
)
point
.
column
-=
start
.
column
;
point
.
row
-=
start
.
row
;
};
dom
.
importCssString
(
"\n.ace_snippet-marker {\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n background: rgba(194, 193, 208, 0.09);\n border: 1px dotted rgba(211, 208, 235, 0.62);\n position: absolute;\n}"
,
"snippets.css"
,
false
);
exports
.
snippetManager
=
new
SnippetManager
();
var
Editor
=
require
(
"./editor"
).
Editor
;
(
function
()
{
this
.
insertSnippet
=
function
(
content
,
options
)
{
return
exports
.
snippetManager
.
insertSnippet
(
this
,
content
,
options
);
};
this
.
expandSnippet
=
function
(
options
)
{
return
exports
.
snippetManager
.
expandWithTab
(
this
,
options
);
};
}).
call
(
Editor
.
prototype
);
});
ace
.
define
(
"ace/ext/emmet"
,[
"require"
,
"exports"
,
"module"
,
"ace/keyboard/hash_handler"
,
"ace/editor"
,
"ace/snippets"
,
"ace/range"
,
"ace/config"
,
"resources"
,
"resources"
,
"tabStops"
,
"resources"
,
"utils"
,
"actions"
],
function
(
require
,
exports
,
module
){
"use strict"
;
var
HashHandler
=
require
(
"../keyboard/hash_handler"
).
HashHandler
;
var
Editor
=
require
(
"../editor"
).
Editor
;
var
snippetManager
=
require
(
"../snippets"
).
snippetManager
;
var
Range
=
require
(
"../range"
).
Range
;
var
config
=
require
(
"../config"
);
var
emmet
,
emmetPath
;
var
AceEmmetEditor
=
/** @class */
(
function
()
{
function
AceEmmetEditor
()
{
}
AceEmmetEditor
.
prototype
.
setupContext
=
function
(
editor
)
{
this
.
ace
=
editor
;
this
.
indentation
=
editor
.
session
.
getTabString
();
if
(
!
emmet
)
emmet
=
window
[
"emmet"
];
var
resources
=
emmet
.
resources
||
emmet
.
require
(
"resources"
);
resources
.
setVariable
(
"indentation"
,
this
.
indentation
);
this
.
$syntax
=
null
;
this
.
$syntax
=
this
.
getSyntax
();
};
AceEmmetEditor
.
prototype
.
getSelectionRange
=
function
()
{
var
range
=
this
.
ace
.
getSelectionRange
();
var
doc
=
this
.
ace
.
session
.
doc
;
return
{
start
:
doc
.
positionToIndex
(
range
.
start
),
end
:
doc
.
positionToIndex
(
range
.
end
)
};
};
AceEmmetEditor
.
prototype
.
createSelection
=
function
(
start
,
end
)
{
var
doc
=
this
.
ace
.
session
.
doc
;
this
.
ace
.
selection
.
setRange
({
start
:
doc
.
indexToPosition
(
start
),
end
:
doc
.
indexToPosition
(
end
)
});
};
AceEmmetEditor
.
prototype
.
getCurrentLineRange
=
function
()
{
var
ace
=
this
.
ace
;
var
row
=
ace
.
getCursorPosition
().
row
;
var
lineLength
=
ace
.
session
.
getLine
(
row
).
length
;
var
index
=
ace
.
session
.
doc
.
positionToIndex
({
row
:
row
,
column
:
0
});
return
{
start
:
index
,
end
:
index
+
lineLength
};
};
AceEmmetEditor
.
prototype
.
getCaretPos
=
function
()
{
var
pos
=
this
.
ace
.
getCursorPosition
();
return
this
.
ace
.
session
.
doc
.
positionToIndex
(
pos
);
};
AceEmmetEditor
.
prototype
.
setCaretPos
=
function
(
index
)
{
var
pos
=
this
.
ace
.
session
.
doc
.
indexToPosition
(
index
);
this
.
ace
.
selection
.
moveToPosition
(
pos
);
};
AceEmmetEditor
.
prototype
.
getCurrentLine
=
function
()
{
var
row
=
this
.
ace
.
getCursorPosition
().
row
;
return
this
.
ace
.
session
.
getLine
(
row
);
};
AceEmmetEditor
.
prototype
.
replaceContent
=
function
(
value
,
start
,
end
,
noIndent
)
{
if
(
end
==
null
)
end
=
start
==
null
?
this
.
getContent
().
length
:
start
;
if
(
start
==
null
)
start
=
0
;
var
editor
=
this
.
ace
;
var
doc
=
editor
.
session
.
doc
;
var
range
=
Range
.
fromPoints
(
doc
.
indexToPosition
(
start
),
doc
.
indexToPosition
(
end
));
editor
.
session
.
remove
(
range
);
range
.
end
=
range
.
start
;
value
=
this
.
$updateTabstops
(
value
);
snippetManager
.
insertSnippet
(
editor
,
value
);
};
AceEmmetEditor
.
prototype
.
getContent
=
function
()
{
return
this
.
ace
.
getValue
();
};
AceEmmetEditor
.
prototype
.
getSyntax
=
function
()
{
if
(
this
.
$syntax
)
return
this
.
$syntax
;
var
syntax
=
this
.
ace
.
session
.
$modeId
.
split
(
"/"
).
pop
();
if
(
syntax
==
"html"
||
syntax
==
"php"
)
{
var
cursor
=
this
.
ace
.
getCursorPosition
();
var
state
=
this
.
ace
.
session
.
getState
(
cursor
.
row
);
if
(
typeof
state
!=
"string"
)
state
=
state
[
0
];
if
(
state
)
{
state
=
state
.
split
(
"-"
);
if
(
state
.
length
>
1
)
syntax
=
state
[
0
];
else
if
(
syntax
==
"php"
)
syntax
=
"html"
;
}
}
return
syntax
;
};
AceEmmetEditor
.
prototype
.
getProfileName
=
function
()
{
var
resources
=
emmet
.
resources
||
emmet
.
require
(
"resources"
);
switch
(
this
.
getSyntax
())
{
case
"css"
:
return
"css"
;
case
"xml"
:
case
"xsl"
:
return
"xml"
;
case
"html"
:
var
profile
=
resources
.
getVariable
(
"profile"
);
if
(
!
profile
)
profile
=
this
.
ace
.
session
.
getLines
(
0
,
2
).
join
(
""
).
search
(
/<!DOCTYPE[^>]+XHTML/i
)
!=
-
1
?
"xhtml"
:
"html"
;
return
profile
;
default
:
var
mode
=
this
.
ace
.
session
.
$mode
;
return
mode
.
emmetConfig
&&
mode
.
emmetConfig
.
profile
||
"xhtml"
;
}
};
AceEmmetEditor
.
prototype
.
prompt
=
function
(
title
)
{
return
prompt
(
title
);
// eslint-disable-line no-alert
};
AceEmmetEditor
.
prototype
.
getSelection
=
function
()
{
return
this
.
ace
.
session
.
getTextRange
();
};
AceEmmetEditor
.
prototype
.
getFilePath
=
function
()
{
return
""
;
};
AceEmmetEditor
.
prototype
.
$updateTabstops
=
function
(
value
)
{
var
base
=
1000
;
var
zeroBase
=
0
;
var
lastZero
=
null
;
var
ts
=
emmet
.
tabStops
||
emmet
.
require
(
'tabStops'
);
var
resources
=
emmet
.
resources
||
emmet
.
require
(
"resources"
);
var
settings
=
resources
.
getVocabulary
(
"user"
);
var
tabstopOptions
=
{
tabstop
:
function
(
data
)
{
var
group
=
parseInt
(
data
.
group
,
10
);
var
isZero
=
group
===
0
;
if
(
isZero
)
group
=
++
zeroBase
;
else
group
+=
base
;
var
placeholder
=
data
.
placeholder
;
if
(
placeholder
)
{
placeholder
=
ts
.
processText
(
placeholder
,
tabstopOptions
);
}
var
result
=
'${'
+
group
+
(
placeholder
?
':'
+
placeholder
:
''
)
+
'}'
;
if
(
isZero
)
{
lastZero
=
[
data
.
start
,
result
];
}
return
result
;
},
escape
:
function
(
ch
)
{
if
(
ch
==
'$'
)
return
'\\$'
;
if
(
ch
==
'\\'
)
return
'\\\\'
;
return
ch
;
}
};
value
=
ts
.
processText
(
value
,
tabstopOptions
);
if
(
settings
.
variables
[
'insert_final_tabstop'
]
&&
!
/\$\{0\}$/
.
test
(
value
))
{
value
+=
'${0}'
;
}
else
if
(
lastZero
)
{
var
common
=
emmet
.
utils
?
emmet
.
utils
.
common
:
emmet
.
require
(
'utils'
);
value
=
common
.
replaceSubstring
(
value
,
'${0}'
,
lastZero
[
0
],
lastZero
[
1
]);
}
return
value
;
};
return
AceEmmetEditor
;
}());
var
keymap
=
{
expand_abbreviation
:
{
"mac"
:
"ctrl+alt+e"
,
"win"
:
"alt+e"
},
match_pair_outward
:
{
"mac"
:
"ctrl+d"
,
"win"
:
"ctrl+,"
},
match_pair_inward
:
{
"mac"
:
"ctrl+j"
,
"win"
:
"ctrl+shift+0"
},
matching_pair
:
{
"mac"
:
"ctrl+alt+j"
,
"win"
:
"alt+j"
},
next_edit_point
:
"alt+right"
,
prev_edit_point
:
"alt+left"
,
toggle_comment
:
{
"mac"
:
"command+/"
,
"win"
:
"ctrl+/"
},
split_join_tag
:
{
"mac"
:
"shift+command+'"
,
"win"
:
"shift+ctrl+`"
},
remove_tag
:
{
"mac"
:
"command+'"
,
"win"
:
"shift+ctrl+;"
},
evaluate_math_expression
:
{
"mac"
:
"shift+command+y"
,
"win"
:
"shift+ctrl+y"
},
increment_number_by_1
:
"ctrl+up"
,
decrement_number_by_1
:
"ctrl+down"
,
increment_number_by_01
:
"alt+up"
,
decrement_number_by_01
:
"alt+down"
,
increment_number_by_10
:
{
"mac"
:
"alt+command+up"
,
"win"
:
"shift+alt+up"
},
decrement_number_by_10
:
{
"mac"
:
"alt+command+down"
,
"win"
:
"shift+alt+down"
},
select_next_item
:
{
"mac"
:
"shift+command+."
,
"win"
:
"shift+ctrl+."
},
select_previous_item
:
{
"mac"
:
"shift+command+,"
,
"win"
:
"shift+ctrl+,"
},
reflect_css_value
:
{
"mac"
:
"shift+command+r"
,
"win"
:
"shift+ctrl+r"
},
encode_decode_data_url
:
{
"mac"
:
"shift+ctrl+d"
,
"win"
:
"ctrl+'"
},
expand_abbreviation_with_tab
:
"Tab"
,
wrap_with_abbreviation
:
{
"mac"
:
"shift+ctrl+a"
,
"win"
:
"shift+ctrl+a"
}
};
var
editorProxy
=
new
AceEmmetEditor
();
exports
.
commands
=
new
HashHandler
();
exports
.
runEmmetCommand
=
function
runEmmetCommand
(
editor
)
{
if
(
this
.
action
==
"expand_abbreviation_with_tab"
)
{
if
(
!
editor
.
selection
.
isEmpty
())
return
false
;
var
pos
=
editor
.
selection
.
lead
;
var
token
=
editor
.
session
.
getTokenAt
(
pos
.
row
,
pos
.
column
);
if
(
token
&&
/\btag\b/
.
test
(
token
.
type
))
return
false
;
}
try
{
editorProxy
.
setupContext
(
editor
);
var
actions
=
emmet
.
actions
||
emmet
.
require
(
"actions"
);
if
(
this
.
action
==
"wrap_with_abbreviation"
)
{
return
setTimeout
(
function
()
{
actions
.
run
(
"wrap_with_abbreviation"
,
editorProxy
);
},
0
);
}
var
result
=
actions
.
run
(
this
.
action
,
editorProxy
);
}
catch
(
e
)
{
if
(
!
emmet
)
{
var
loading
=
exports
.
load
(
runEmmetCommand
.
bind
(
this
,
editor
));
if
(
this
.
action
==
"expand_abbreviation_with_tab"
)
return
false
;
return
loading
;
}
editor
.
_signal
(
"changeStatus"
,
typeof
e
==
"string"
?
e
:
e
.
message
);
config
.
warn
(
e
);
result
=
false
;
}
return
result
;
};
for
(
var
command
in
keymap
)
{
exports
.
commands
.
addCommand
({
name
:
"emmet:"
+
command
,
action
:
command
,
bindKey
:
keymap
[
command
],
exec
:
exports
.
runEmmetCommand
,
multiSelectAction
:
"forEach"
});
}
exports
.
updateCommands
=
function
(
editor
,
enabled
)
{
if
(
enabled
)
{
editor
.
keyBinding
.
addKeyboardHandler
(
exports
.
commands
);
}
else
{
editor
.
keyBinding
.
removeKeyboardHandler
(
exports
.
commands
);
}
};
exports
.
isSupportedMode
=
function
(
mode
)
{
if
(
!
mode
)
return
false
;
if
(
mode
.
emmetConfig
)
return
true
;
var
id
=
mode
.
$id
||
mode
;
return
/css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/
.
test
(
id
);
};
exports
.
isAvailable
=
function
(
editor
,
command
)
{
if
(
/(evaluate_math_expression|expand_abbreviation)$/
.
test
(
command
))
return
true
;
var
mode
=
editor
.
session
.
$mode
;
var
isSupported
=
exports
.
isSupportedMode
(
mode
);
if
(
isSupported
&&
mode
.
$modes
)
{
try
{
editorProxy
.
setupContext
(
editor
);
if
(
/js|php/
.
test
(
editorProxy
.
getSyntax
()))
isSupported
=
false
;
}
catch
(
e
)
{
}
}
return
isSupported
;
};
var
onChangeMode
=
function
(
e
,
target
)
{
var
editor
=
target
;
if
(
!
editor
)
return
;
var
enabled
=
exports
.
isSupportedMode
(
editor
.
session
.
$mode
);
if
(
e
.
enableEmmet
===
false
)
enabled
=
false
;
if
(
enabled
)
exports
.
load
();
exports
.
updateCommands
(
editor
,
enabled
);
};
exports
.
load
=
function
(
cb
)
{
if
(
typeof
emmetPath
!==
"string"
)
{
config
.
warn
(
"script for emmet-core is not loaded"
);
return
false
;
}
config
.
loadModule
(
emmetPath
,
function
()
{
emmetPath
=
null
;
cb
&&
cb
();
});
return
true
;
};
exports
.
AceEmmetEditor
=
AceEmmetEditor
;
config
.
defineOptions
(
Editor
.
prototype
,
"editor"
,
{
enableEmmet
:
{
set
:
function
(
val
)
{
this
[
val
?
"on"
:
"removeListener"
](
"changeMode"
,
onChangeMode
);
onChangeMode
({
enableEmmet
:
!!
val
},
this
);
},
value
:
true
}
});
exports
.
setCore
=
function
(
e
)
{
if
(
typeof
e
==
"string"
)
emmetPath
=
e
;
else
emmet
=
e
;
};
});
(
function
()
{
ace
.
require
([
"ace/ext/emmet"
],
function
(
m
)
{
if
(
typeof
module
==
"object"
&&
typeof
exports
==
"object"
&&
module
)
{
module
.
exports
=
m
;
}
});
})();
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 07:25 (2 w, 26 m ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
9d/95/e3718ebd084d674aba155ebba079
Default Alt Text
ext-emmet.js (50 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment