1+ ace . define ( "ace/ext/beautify" , [ "require" , "exports" , "module" , "ace/token_iterator" ] , function ( require , exports , module ) {
2+ "use strict" ;
3+ var TokenIterator = require ( "../token_iterator" ) . TokenIterator ;
4+
5+ function is ( token , type ) {
6+ return token . type . lastIndexOf ( type + ".xml" ) > - 1 ;
7+ }
8+ exports . singletonTags = [ "area" , "base" , "br" , "col" , "command" , "embed" , "hr" , "html" , "img" , "input" , "keygen" , "link" , "meta" , "param" , "source" , "track" , "wbr" ] ;
9+ exports . blockTags = [ "article" , "aside" , "blockquote" , "body" , "div" , "dl" , "fieldset" , "footer" , "form" , "head" , "header" , "html" , "nav" , "ol" , "p" , "script" , "section" , "style" , "table" , "tbody" , "tfoot" , "thead" , "ul" ] ;
10+
11+ exports . beautify = function ( session ) {
12+ var iterator = new TokenIterator ( session , 0 , 0 ) ;
13+ var token = iterator . getCurrentToken ( ) ;
14+ var tabString = session . getTabString ( ) ;
15+ var singletonTags = exports . singletonTags ;
16+ var blockTags = exports . blockTags ;
17+ var nextToken ;
18+ var breakBefore = false ;
19+ var spaceBefore = false ;
20+ var spaceAfter = false ;
21+ var code = "" ;
22+ var value = "" ;
23+ var tagName = "" ;
24+ var depth = 0 ;
25+ var lastDepth = 0 ;
26+ var lastIndent = 0 ;
27+ var indent = 0 ;
28+ var unindent = 0 ;
29+ var roundDepth = 0 ;
30+ var curlyDepth = 0 ;
31+ var row ;
32+ var curRow = 0 ;
33+ var rowsToAdd = 0 ;
34+ var rowTokens = [ ] ;
35+ var abort = false ;
36+ var i ;
37+ var indentNextLine = false ;
38+ var inTag = false ;
39+ var inCSS = false ;
40+ var inBlock = false ;
41+ var levels = { 0 : 0 } ;
42+ var parents = [ ] ;
43+
44+ var trimNext = function ( ) {
45+ if ( nextToken && nextToken . value && nextToken . type !== 'string.regexp' )
46+ nextToken . value = nextToken . value . trim ( ) ;
47+ } ;
48+
49+ var trimLine = function ( ) {
50+ code = code . replace ( / + $ / , "" ) ;
51+ } ;
52+
53+ var trimCode = function ( ) {
54+ code = code . trimRight ( ) ;
55+ breakBefore = false ;
56+ } ;
57+
58+ while ( token !== null ) {
59+ curRow = iterator . getCurrentTokenRow ( ) ;
60+ rowTokens = iterator . $rowTokens ;
61+ nextToken = iterator . stepForward ( ) ;
62+
63+ if ( typeof token !== "undefined" ) {
64+ value = token . value ;
65+ unindent = 0 ;
66+ inCSS = ( tagName === "style" || session . $modeId === "ace/mode/css" ) ;
67+ if ( is ( token , "tag-open" ) ) {
68+ inTag = true ;
69+ if ( nextToken )
70+ inBlock = ( blockTags . indexOf ( nextToken . value ) !== - 1 ) ;
71+ if ( value === "</" ) {
72+ if ( inBlock && ! breakBefore && rowsToAdd < 1 )
73+ rowsToAdd ++ ;
74+
75+ if ( inCSS )
76+ rowsToAdd = 1 ;
77+
78+ unindent = 1 ;
79+ inBlock = false ;
80+ }
81+ } else if ( is ( token , "tag-close" ) ) {
82+ inTag = false ;
83+ } else if ( is ( token , "comment.start" ) ) {
84+ inBlock = true ;
85+ } else if ( is ( token , "comment.end" ) ) {
86+ inBlock = false ;
87+ }
88+ if ( ! inTag && ! rowsToAdd && token . type === "paren.rparen" && token . value . substr ( 0 , 1 ) === "}" ) {
89+ rowsToAdd ++ ;
90+ }
91+ if ( curRow !== row ) {
92+ rowsToAdd = curRow ;
93+
94+ if ( row )
95+ rowsToAdd -= row ;
96+ }
97+
98+ if ( rowsToAdd ) {
99+ trimCode ( ) ;
100+ for ( ; rowsToAdd > 0 ; rowsToAdd -- )
101+ code += "\n" ;
102+
103+ breakBefore = true ;
104+ if ( ! is ( token , "comment" ) && ! token . type . match ( / ^ ( c o m m e n t | s t r i n g ) $ / ) )
105+ value = value . trimLeft ( ) ;
106+ }
107+
108+ if ( value ) {
109+ if ( token . type === "keyword" && value . match ( / ^ ( i f | e l s e | e l s e i f | f o r | f o r e a c h | w h i l e | s w i t c h ) $ / ) ) {
110+ parents [ depth ] = value ;
111+
112+ trimNext ( ) ;
113+ spaceAfter = true ;
114+ if ( value . match ( / ^ ( e l s e | e l s e i f ) $ / ) ) {
115+ if ( code . match ( / \} [ \s ] * $ / ) ) {
116+ trimCode ( ) ;
117+ spaceBefore = true ;
118+ }
119+ }
120+ } else if ( token . type === "paren.lparen" ) {
121+ trimNext ( ) ;
122+ if ( value . substr ( - 1 ) === "{" ) {
123+ spaceAfter = true ;
124+ indentNextLine = false ;
125+
126+ if ( ! inTag )
127+ rowsToAdd = 1 ;
128+ }
129+ if ( value . substr ( 0 , 1 ) === "{" ) {
130+ spaceBefore = true ;
131+ if ( code . substr ( - 1 ) !== '[' && code . trimRight ( ) . substr ( - 1 ) === '[' ) {
132+ trimCode ( ) ;
133+ spaceBefore = false ;
134+ } else if ( code . trimRight ( ) . substr ( - 1 ) === ')' ) {
135+ trimCode ( ) ;
136+ } else {
137+ trimLine ( ) ;
138+ }
139+ }
140+ } else if ( token . type === "paren.rparen" ) {
141+ unindent = 1 ;
142+ if ( value . substr ( 0 , 1 ) === "}" ) {
143+ if ( parents [ depth - 1 ] === 'case' )
144+ unindent ++ ;
145+
146+ if ( code . trimRight ( ) . substr ( - 1 ) === '{' ) {
147+ trimCode ( ) ;
148+ } else {
149+ spaceBefore = true ;
150+
151+ if ( inCSS )
152+ rowsToAdd += 2 ;
153+ }
154+ }
155+ if ( value . substr ( 0 , 1 ) === "]" ) {
156+ if ( code . substr ( - 1 ) !== '}' && code . trimRight ( ) . substr ( - 1 ) === '}' ) {
157+ spaceBefore = false ;
158+ indent ++ ;
159+ trimCode ( ) ;
160+ }
161+ }
162+ if ( value . substr ( 0 , 1 ) === ")" ) {
163+ if ( code . substr ( - 1 ) !== '(' && code . trimRight ( ) . substr ( - 1 ) === '(' ) {
164+ spaceBefore = false ;
165+ indent ++ ;
166+ trimCode ( ) ;
167+ }
168+ }
169+
170+ trimLine ( ) ;
171+ } else if ( ( token . type === "keyword.operator" || token . type === "keyword" ) && value . match ( / ^ ( = | = = | = = = | ! = | ! = = | & & | \| \| | a n d | o r | x o r | \+ = | .= | > | > = | < | < = | = > ) $ / ) ) {
172+ trimCode ( ) ;
173+ trimNext ( ) ;
174+ spaceBefore = true ;
175+ spaceAfter = true ;
176+ } else if ( token . type === "punctuation.operator" && value === ';' ) {
177+ trimCode ( ) ;
178+ trimNext ( ) ;
179+ spaceAfter = true ;
180+
181+ if ( inCSS )
182+ rowsToAdd ++ ;
183+ } else if ( token . type === "punctuation.operator" && value . match ( / ^ ( : | , ) $ / ) ) {
184+ trimCode ( ) ;
185+ trimNext ( ) ;
186+ if ( value . match ( / ^ ( , ) $ / ) && curlyDepth > 0 && roundDepth === 0 ) {
187+ rowsToAdd ++ ;
188+ } else {
189+ spaceAfter = true ;
190+ breakBefore = false ;
191+ }
192+ } else if ( token . type === "support.php_tag" && value === "?>" && ! breakBefore ) {
193+ trimCode ( ) ;
194+ spaceBefore = true ;
195+ } else if ( is ( token , "attribute-name" ) && code . substr ( - 1 ) . match ( / ^ \s $ / ) ) {
196+ spaceBefore = true ;
197+ } else if ( is ( token , "attribute-equals" ) ) {
198+ trimLine ( ) ;
199+ trimNext ( ) ;
200+ } else if ( is ( token , "tag-close" ) ) {
201+ trimLine ( ) ;
202+ if ( value === "/>" )
203+ spaceBefore = true ;
204+ }
205+ if ( breakBefore && ! ( token . type . match ( / ^ ( c o m m e n t ) $ / ) && ! value . substr ( 0 , 1 ) . match ( / ^ [ / # ] $ / ) ) && ! ( token . type . match ( / ^ ( s t r i n g ) $ / ) && ! value . substr ( 0 , 1 ) . match ( / ^ [ ' " ] $ / ) ) ) {
206+
207+ indent = lastIndent ;
208+
209+ if ( depth > lastDepth ) {
210+ indent ++ ;
211+
212+ for ( i = depth ; i > lastDepth ; i -- )
213+ levels [ i ] = indent ;
214+ } else if ( depth < lastDepth )
215+ indent = levels [ depth ] ;
216+
217+ lastDepth = depth ;
218+ lastIndent = indent ;
219+
220+ if ( unindent )
221+ indent -= unindent ;
222+
223+ if ( indentNextLine && ! roundDepth ) {
224+ indent ++ ;
225+ indentNextLine = false ;
226+ }
227+
228+ for ( i = 0 ; i < indent ; i ++ )
229+ code += tabString ;
230+ }
231+
232+
233+ if ( token . type === "keyword" && value . match ( / ^ ( c a s e | d e f a u l t ) $ / ) ) {
234+ parents [ depth ] = value ;
235+ depth ++ ;
236+ }
237+
238+
239+ if ( token . type === "keyword" && value . match ( / ^ ( b r e a k ) $ / ) ) {
240+ if ( parents [ depth - 1 ] && parents [ depth - 1 ] . match ( / ^ ( c a s e | d e f a u l t ) $ / ) ) {
241+ depth -- ;
242+ }
243+ }
244+ if ( token . type === "paren.lparen" ) {
245+ roundDepth += ( value . match ( / \( / g) || [ ] ) . length ;
246+ curlyDepth += ( value . match ( / \{ / g) || [ ] ) . length ;
247+ depth += value . length ;
248+ }
249+
250+ if ( token . type === "keyword" && value . match ( / ^ ( i f | e l s e | e l s e i f | f o r | w h i l e ) $ / ) ) {
251+ indentNextLine = true ;
252+ roundDepth = 0 ;
253+ } else if ( ! roundDepth && value . trim ( ) && token . type !== "comment" )
254+ indentNextLine = false ;
255+
256+ if ( token . type === "paren.rparen" ) {
257+ roundDepth -= ( value . match ( / \) / g) || [ ] ) . length ;
258+ curlyDepth -= ( value . match ( / \} / g) || [ ] ) . length ;
259+
260+ for ( i = 0 ; i < value . length ; i ++ ) {
261+ depth -- ;
262+ if ( value . substr ( i , 1 ) === '}' && parents [ depth ] === 'case' ) {
263+ depth -- ;
264+ }
265+ }
266+ }
267+ if ( spaceBefore && ! breakBefore ) {
268+ trimLine ( ) ;
269+ if ( code . substr ( - 1 ) !== "\n" )
270+ code += " " ;
271+ }
272+
273+ code += value ;
274+
275+ if ( spaceAfter )
276+ code += " " ;
277+
278+ breakBefore = false ;
279+ spaceBefore = false ;
280+ spaceAfter = false ;
281+ if ( ( is ( token , "tag-close" ) && ( inBlock || blockTags . indexOf ( tagName ) !== - 1 ) ) || ( is ( token , "doctype" ) && value === ">" ) ) {
282+ if ( inBlock && nextToken && nextToken . value === "</" )
283+ rowsToAdd = - 1 ;
284+ else
285+ rowsToAdd = 1 ;
286+ }
287+ if ( is ( token , "tag-open" ) && value === "</" ) {
288+ depth -- ;
289+ } else if ( is ( token , "tag-open" ) && value === "<" && singletonTags . indexOf ( nextToken . value ) === - 1 ) {
290+ depth ++ ;
291+ } else if ( is ( token , "tag-name" ) ) {
292+ tagName = value ;
293+ } else if ( is ( token , "tag-close" ) && value === "/>" && singletonTags . indexOf ( tagName ) === - 1 ) {
294+ depth -- ;
295+ }
296+
297+ row = curRow ;
298+ }
299+ }
300+
301+ token = nextToken ;
302+ }
303+
304+ code = code . trim ( ) ;
305+ session . doc . setValue ( code ) ;
306+ } ;
307+
308+ exports . commands = [ {
309+ name : "beautify" ,
310+ description : "Format selection (Beautify)" ,
311+ exec : function ( editor ) {
312+ exports . beautify ( editor . session ) ;
313+ } ,
314+ bindKey : "Ctrl-Shift-B"
315+ } ] ;
316+
317+ } ) ; ( function ( ) {
318+ ace . require ( [ "ace/ext/beautify" ] , function ( m ) {
319+ if ( typeof module == "object" && typeof exports == "object" && module ) {
320+ module . exports = m ;
321+ }
322+ } ) ;
323+ } ) ( ) ;
324+
0 commit comments