├── README.md ├── build.groovy └── war ├── .DS_Store ├── WEB-INF ├── .DS_Store ├── appengine-web.xml ├── datastore-indexes.xml ├── groovy │ ├── atom.groovy │ ├── captchaquestion.groovy │ ├── editscript.groovy │ ├── executor.groovy │ ├── loadscript.groovy │ ├── publish.groovy │ ├── recentscripts.groovy │ └── view.groovy ├── lib │ ├── .DS_Store │ ├── antlr4-4.6.0.3.jar │ ├── antlr4-annotations-4.6.0.3.jar │ ├── antlr4-runtime-4.6.0.3.jar │ ├── appengine-api-1.0-sdk-1.9.75.jar │ ├── appengine-api-labs-1.9.75.jar │ ├── gaelyk-2.1.2.jar │ ├── groovy-2.5.14.jar │ ├── groovy-datetime-2.5.14.jar │ ├── groovy-dateutil-2.5.14.jar │ ├── groovy-json-2.5.14.jar │ ├── groovy-json-direct-2.5.14.jar │ ├── groovy-jsr223-2.5.14.jar │ ├── groovy-macro-2.5.14.jar │ ├── groovy-nio-2.5.14.jar │ ├── groovy-servlet-2.5.14.jar │ ├── groovy-templates-2.5.14.jar │ ├── groovy-xml-2.5.14.jar │ ├── jsp-api-2.2.jar │ ├── prettytime-3.2.5.Final.jar │ └── servlet-api-2.5.jar ├── logging.properties ├── routes.groovy └── web.xml ├── badcaptcha.gtpl ├── css ├── embed.css ├── help.png ├── jscolors.css ├── magnifier.png ├── main.css ├── page_white_code.png ├── page_white_copy.png ├── printer.png ├── redmond │ ├── images │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_55_fbec88_40x100.png │ │ ├── ui-bg_glass_75_d0e5f5_1x400.png │ │ ├── ui-bg_glass_85_dfeffc_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ ├── ui-bg_gloss-wave_55_5c9ccc_500x100.png │ │ ├── ui-bg_inset-hard_100_f5f8f9_1x100.png │ │ ├── ui-bg_inset-hard_100_fcfdfd_1x100.png │ │ ├── ui-icons_217bc0_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_469bdd_256x240.png │ │ ├── ui-icons_6da8d5_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-icons_d8e7f3_256x240.png │ │ └── ui-icons_f9bd01_256x240.png │ └── jquery-ui-1.7.1.custom.css ├── shCore.css ├── shThemeDefault.css └── wrapping.png ├── embed.gtpl ├── favicon.ico ├── flash └── clipboard.swf ├── images ├── ajax-spinner-blue.gif ├── atom-feed.png ├── date.png ├── google-app-engine-groovy.png ├── people.jpg ├── puzzle.png ├── tag_blue.png ├── twitter.png └── user.png ├── index.html ├── js ├── codemirror.js ├── editor.js ├── embed.js ├── jquery-1.6.4.min.js ├── jquery-ui-1.7.2.custom.min.js ├── main.js ├── mirrorframe.js ├── parsejavascript.js ├── select.js ├── shBrushGroovy.js ├── shBrushXml.js ├── shCore.js ├── shLegacy.js ├── stringstream.js ├── tokenize.js ├── tokenizejavascript.js ├── undo.js ├── util.js └── view.js ├── nosuchscript.gtpl ├── recentscripts.gtpl └── view.gtpl /README.md: -------------------------------------------------------------------------------- 1 | This is the archived repository for the old Groovy Web Console. 2 | 3 | Please consider migrating to the new [Groovy Web Console](https://groovyconsole.dev/) and its new [Github repository](https://github.com/groovy-console/groovy-web-console) 4 | -------------------------------------------------------------------------------- /build.groovy: -------------------------------------------------------------------------------- 1 | def ant = new AntBuilder().sequential { 2 | webinf = "war/WEB-INF" 3 | taskdef name: "groovyc", classname: "org.codehaus.groovy.ant.Groovyc" 4 | groovyc srcdir: "src", destdir: "${webinf}/classes", { 5 | classpath { 6 | fileset dir: "${webinf}/lib", { 7 | include name: "*.jar" 8 | } 9 | pathelement path: "${webinf}/classes" 10 | } 11 | javac source: "1.8", target: "1.8", debug: "on" 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /war/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/.DS_Store -------------------------------------------------------------------------------- /war/WEB-INF/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/.DS_Store -------------------------------------------------------------------------------- /war/WEB-INF/appengine-web.xml: -------------------------------------------------------------------------------- 1 | 2 | groovyconsole-hrd 3 | 4 | 2514 5 | 6 | true 7 | 8 | java8 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /war/WEB-INF/datastore-indexes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /war/WEB-INF/groovy/atom.groovy: -------------------------------------------------------------------------------- 1 | import groovy.xml.MarkupBuilder 2 | import com.google.appengine.api.datastore.Query 3 | import com.google.appengine.api.datastore.PreparedQuery 4 | 5 | import static com.google.appengine.api.datastore.FetchOptions.Builder.* 6 | import java.text.SimpleDateFormat 7 | 8 | def query = new Query("savedscript") 9 | query.addSort("dateCreated", Query.SortDirection.DESCENDING) 10 | PreparedQuery preparedQuery = datastore.prepare(query) 11 | def entities = preparedQuery.asList(withLimit(10)) 12 | 13 | def isoTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US) 14 | 15 | response.contentType = "application/atom+xml;charset=utf-8" 16 | 17 | def builder = new MarkupBuilder(out) 18 | 19 | //builder.yieldUnescaped '''''' 20 | 21 | builder.feed(xmlns: "http://www.w3.org/2005/Atom") { 22 | id "http://groovyconsole.appspot.com/" 23 | title "Groovy Web Console for the Groovy Programming Language" 24 | subtitle "Sharing Groovy programming language snippets, one script at a time" 25 | link href: "http://groovyconsole.appspot.com/", rel: "self" 26 | updated isoTime.format(entities[0].dateCreated) 27 | author { 28 | name "Guillaume Laforge" 29 | email "glaforge@gmail.com" 30 | } 31 | generator(uri: "http://gaelyk.appspot.com", version: "2.1.2", "Gaelyk lightweight Groovy toolkit for Google App Engine") 32 | 33 | entities.each { entity -> 34 | def authorText = entity.author && entity.author != 'Anonymous' ? entity.author : 'Anonymous' 35 | def titleText = entity.title ?: 'Untitled' 36 | entry { 37 | id "https://groovyconsole.appspot.com/script/${entity.key.id}" 38 | title titleText 39 | link href: "https://groovyconsole.appspot.com/script/${entity.key.id}" 40 | updated isoTime.format(entity.dateCreated) 41 | author { 42 | name authorText 43 | } 44 | content(type: 'xhtml') { 45 | div(xmlns: "http://www.w3.org/1999/xhtml") { 46 | pre { 47 | mkp.yieldUnescaped "" 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /war/WEB-INF/groovy/captchaquestion.groovy: -------------------------------------------------------------------------------- 1 | out << "${new Random().nextInt(10)} + ${new Random().nextInt(10)}" -------------------------------------------------------------------------------- /war/WEB-INF/groovy/editscript.groovy: -------------------------------------------------------------------------------- 1 | out << new File("index.html").text 2 | out.flush() 3 | -------------------------------------------------------------------------------- /war/WEB-INF/groovy/executor.groovy: -------------------------------------------------------------------------------- 1 | import org.codehaus.groovy.control.CompilerConfiguration 2 | import org.codehaus.groovy.control.MultipleCompilationErrorsException 3 | import groovy.json.* 4 | 5 | import com.google.apphosting.api.ApiProxy 6 | 7 | def scriptText = params.script ?: "'The received script was null.'" 8 | 9 | def encoding = 'UTF-8' 10 | def stream = new ByteArrayOutputStream() 11 | def printStream = new PrintStream(stream, true, encoding) 12 | 13 | def stacktrace = new StringWriter() 14 | def errWriter = new PrintWriter(stacktrace) 15 | 16 | def aBinding = new Binding([out: printStream]) 17 | 18 | def emcEvents = [] 19 | def listener = { MetaClassRegistryChangeEvent event -> 20 | emcEvents << event 21 | } as MetaClassRegistryChangeEventListener 22 | 23 | GroovySystem.metaClassRegistry.addMetaClassRegistryChangeEventListener listener 24 | 25 | def originalOut = System.out 26 | def originalErr = System.err 27 | 28 | System.setOut(printStream) 29 | System.setErr(printStream) 30 | 31 | def env = ApiProxy.currentEnvironment 32 | ApiProxy.clearEnvironmentForCurrentThread() 33 | def result = "" 34 | try { 35 | log.info(scriptText) 36 | result = new GroovyShell(aBinding).evaluate(scriptText) 37 | } catch (MultipleCompilationErrorsException e) { 38 | stacktrace.append(e.message - 'startup failed:\nScript1.groovy: 1: ') 39 | } catch (Throwable t) { 40 | sanitizeStacktrace(t) 41 | def cause = t 42 | while (cause = cause?.cause) { 43 | sanitizeStacktrace(cause) 44 | } 45 | t.printStackTrace(errWriter) 46 | } finally { 47 | ApiProxy.setEnvironmentForCurrentThread(env) 48 | System.setOut(originalOut) 49 | System.setErr(originalErr) 50 | 51 | GroovySystem.metaClassRegistry.removeMetaClassRegistryChangeEventListener listener 52 | emcEvents.each { MetaClassRegistryChangeEvent event -> 53 | GroovySystem.metaClassRegistry.removeMetaClass event.clazz 54 | } 55 | } 56 | 57 | response.contentType = "application/json" 58 | 59 | out.println JsonOutput.toJson([ 60 | "executionResult": "${result}", 61 | "outputText": "${stream.toString(encoding)}", 62 | "stacktraceText": "${stacktrace}" 63 | ]) 64 | 65 | def sanitizeStacktrace(t) { 66 | def filtered = [ 67 | 'com.google.', 'org.eclipse.', 68 | 'java.', 'javax.', 'sun.', 69 | 'groovy.', 'org.codehaus.groovy.', 70 | 'groovyx.gaelyk.', 'executor' 71 | ] 72 | def trace = t.stackTrace 73 | def newTrace = [] 74 | trace.each { stackTraceElement -> 75 | if (filtered.every { !stackTraceElement.className.startsWith(it) }) { 76 | newTrace << stackTraceElement 77 | } 78 | } 79 | def clean = newTrace.toArray(newTrace as StackTraceElement[]) 80 | t.stackTrace = clean 81 | } 82 | -------------------------------------------------------------------------------- /war/WEB-INF/groovy/loadscript.groovy: -------------------------------------------------------------------------------- 1 | import com.google.appengine.api.datastore.Entity 2 | 3 | try { 4 | if (params.id) { 5 | def id = Long.parseLong(params.id) 6 | Entity entity = datastore.get("savedscript", id) 7 | out << entity.script 8 | out.flush() 9 | } 10 | } catch (Throwable t) { 11 | t.printStackTrace() 12 | } -------------------------------------------------------------------------------- /war/WEB-INF/groovy/publish.groovy: -------------------------------------------------------------------------------- 1 | import com.google.appengine.api.datastore.Entity 2 | 3 | def captchaTestPassed = false 4 | try { 5 | // if the question is an addition and the result provided by the user is a number with one or two digits 6 | // the we can safely evaluate those expressions with the GroovyShell#evaluate() method 7 | if (params.captchaQuestion ==~ /\d \+ \d/ && params.captchaAnswer ==~ /\d{1,2}/) { 8 | captchaTestPassed = evaluate(params.captchaQuestion) == evaluate(params.captchaAnswer) 9 | } 10 | } catch (any) {} 11 | 12 | 13 | if (captchaTestPassed) { 14 | def entity = new Entity("savedscript") 15 | entity.unindexed.script = params.script 16 | entity.title = params.title ?: "Untitled" 17 | entity.author = params.author ?: "Anonymous" 18 | entity.dateCreated = new Date() 19 | entity.tags = params.tags ? params.tags?.split(',')*.trim() : [] 20 | entity.save() 21 | 22 | memcache.recentScripts = null 23 | 24 | request['entity'] = entity 25 | 26 | redirect "/script/${entity.key.id}" 27 | } else { 28 | redirect "/badcaptcha" 29 | } 30 | 31 | -------------------------------------------------------------------------------- /war/WEB-INF/groovy/recentscripts.groovy: -------------------------------------------------------------------------------- 1 | import com.google.appengine.api.datastore.Entity 2 | import org.ocpsoft.prettytime.PrettyTime 3 | 4 | def recentScriptsInCache = memcache.recentScripts 5 | def entities = recentScriptsInCache ?: datastore.execute { 6 | select all from savedscript 7 | sort desc by dateCreated 8 | limit params.limit?.toInteger() ?: 1000 9 | } 10 | if (!recentScriptsInCache) memcache.recentScripts = entities 11 | 12 | def tagMap = entities.collect { it.tags }.flatten().groupBy { it } 13 | def authorMap = entities.collect { it.author }.flatten().groupBy { it } 14 | 15 | html.div(class: 'indent') { 16 | ul { 17 | entities.each { Entity entity -> 18 | if (params.author == entity.author || entity.tags?.contains(params.tag) || !(params.author || params.tag)) { 19 | li { 20 | a href: "/script/${entity.key.id}", entity.title ?: 'Untitled' 21 | if (!params.author) { 22 | span " by " 23 | if (entity.author && entity.author != 'Anonymous') { 24 | a href: "/author/${entity.author}", entity.author 25 | } else { 26 | span 'Anonymous' 27 | } 28 | } else { 29 | span ' - ' 30 | } 31 | span new PrettyTime().format(entity.dateCreated) 32 | if (entity.tags?.join()) { 33 | span " with tags " 34 | entity.tags.each { tag -> 35 | a href: "/tag/${tag}", tag 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | html.ul(class: 'taglist') { 45 | li { b "Authors: " } 46 | authorMap.keySet().sort().each {author -> 47 | if (author && author != 'Anonymous') { 48 | li { 49 | img src: '/images/user.png', align: 'top' 50 | a href: "/author/${author}", author 51 | span class: 'smaller', "(${authorMap[author].size()})" 52 | } 53 | } 54 | } 55 | } 56 | 57 | html.ul(class: 'taglist') { 58 | li { b "Tags: " } 59 | tagMap.keySet().sort().each {tag -> 60 | if (tag) { 61 | li { 62 | img src: '/images/tag_blue.png', align: 'top' 63 | a href: "/tag/${tag}", tag 64 | span class: 'smaller', "(${tagMap[tag].size()})" 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /war/WEB-INF/groovy/view.groovy: -------------------------------------------------------------------------------- 1 | import com.google.appengine.api.datastore.Entity 2 | 3 | if (params.id) { 4 | def id = Long.parseLong(params['id']) 5 | 6 | try { 7 | def savedscript = memcache["savedscript-$id"] 8 | Entity script = savedscript ?: datastore.get("savedscript", id) 9 | if (!savedscript) memcache["savedscript-$id"] = script 10 | 11 | request.script = script 12 | forward params['embed'] ? 'embed.gtpl' : 'view.gtpl' 13 | } catch (Throwable t) { 14 | t.printStackTrace() 15 | forward 'nosuchscript.gtpl' 16 | } 17 | } else { 18 | forward 'nosuchscript.gtpl' 19 | } -------------------------------------------------------------------------------- /war/WEB-INF/lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/.DS_Store -------------------------------------------------------------------------------- /war/WEB-INF/lib/antlr4-4.6.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/antlr4-4.6.0.3.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/antlr4-annotations-4.6.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/antlr4-annotations-4.6.0.3.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/antlr4-runtime-4.6.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/antlr4-runtime-4.6.0.3.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/appengine-api-1.0-sdk-1.9.75.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/appengine-api-1.0-sdk-1.9.75.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/appengine-api-labs-1.9.75.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/appengine-api-labs-1.9.75.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/gaelyk-2.1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/gaelyk-2.1.2.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-datetime-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-datetime-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-dateutil-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-dateutil-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-json-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-json-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-json-direct-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-json-direct-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-jsr223-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-jsr223-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-macro-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-macro-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-nio-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-nio-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-servlet-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-servlet-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-templates-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-templates-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/groovy-xml-2.5.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/groovy-xml-2.5.14.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/jsp-api-2.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/jsp-api-2.2.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/prettytime-3.2.5.Final.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/prettytime-3.2.5.Final.jar -------------------------------------------------------------------------------- /war/WEB-INF/lib/servlet-api-2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/WEB-INF/lib/servlet-api-2.5.jar -------------------------------------------------------------------------------- /war/WEB-INF/logging.properties: -------------------------------------------------------------------------------- 1 | # Set the default logging level for all loggers to INFO 2 | .level = INFO 3 | -------------------------------------------------------------------------------- /war/WEB-INF/routes.groovy: -------------------------------------------------------------------------------- 1 | def longPeriod = localMode ? 0 : 1.hour 2 | def shortPeriod = localMode ? 0 : 1.minute 3 | 4 | get "/script/@id", forward: "/view.groovy?id=@id", validate: { id ==~ /\d+/ }, cache: longPeriod 5 | get "/script/@id/", forward: "/view.groovy?id=@id", validate: { id ==~ /\d+/ }, cache: longPeriod 6 | get "/edit/@id", forward: "/editscript.groovy?id=@id", validate: { id ==~ /\d+/ }, cache: longPeriod 7 | get "/raw/@id", forward: "/loadscript.groovy?id=@id", validate: { id ==~ /\d+/ }, cache: longPeriod 8 | 9 | get "/author/@author", forward: "/recentscripts.gtpl?author=@author&limit=100", cache: shortPeriod 10 | 11 | get "/tag/@tag", forward: "/recentscripts.gtpl?tag=@tag&limit=100", cache: shortPeriod 12 | 13 | get "/scripts", forward: "/recentscripts.gtpl?limit=100", cache: shortPeriod 14 | get "/scripts/@limit", forward: "/recentscripts.gtpl?limit=@limit", cache: shortPeriod 15 | 16 | get "/badcaptcha", forward: "/badcaptcha.gtpl", cache: longPeriod 17 | 18 | get "/nosuchscript", forward: "/nosuchscript.gtpl", cache: longPeriod 19 | 20 | -------------------------------------------------------------------------------- /war/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GroovyServlet 5 | groovyx.gaelyk.GaelykServlet 6 | 7 | verbose 8 | 9 | false 10 | 11 | 12 | 13 | 14 | TemplateServlet 15 | groovyx.gaelyk.GaelykTemplateServlet 16 | 17 | 18 | generated.by 19 | false 20 | 21 | 22 | verbose 23 | 24 | false 25 | 26 | 27 | 28 | 29 | RoutesFilter 30 | groovyx.gaelyk.routes.RoutesFilter 31 | 32 | 33 | 34 | GroovyServlet 35 | *.groovy 36 | 37 | 38 | 39 | TemplateServlet 40 | *.gtpl 41 | 42 | 43 | 44 | RoutesFilter 45 | /* 46 | 47 | 48 | 49 | index.html 50 | index.gtpl 51 | 52 | 53 | -------------------------------------------------------------------------------- /war/badcaptcha.gtpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groovy web console - Bad Captcha Result 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Groovy web console

17 | 18 | 19 | 20 | 30 | 31 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
subscribe to the feedSubscribe
to this
site
28 |
29 |
32 | 33 |
34 |

You entered a wrong captcha answer, please try again.

35 | 36 |
37 | Actions  ➤ 38 | Back to console 39 | View all recent scripts 40 |
41 |
42 | 43 | <% include '/WEB-INF/includes/about.gtpl' %> 44 | 45 | -------------------------------------------------------------------------------- /war/css/embed.css: -------------------------------------------------------------------------------- 1 | .syntaxhighlighter { 2 | margin: 0 !important; 3 | width: 90% !important; 4 | } 5 | 6 | .gwcEmbedded { 7 | padding: 10px; 8 | } 9 | 10 | .gwcEmbedded .gwcHeader { 11 | margin-bottom: 10px; 12 | } 13 | 14 | .gwcEmbedded .gwcTitle { 15 | font-weight: bold; 16 | display: block; 17 | font-size: 1.4em; 18 | margin-bottom: 5px; 19 | } 20 | 21 | .gwcEmbedded .gwcPublished { 22 | } 23 | 24 | .gwcEmbedded .gwcAuthor { 25 | } 26 | -------------------------------------------------------------------------------- /war/css/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/help.png -------------------------------------------------------------------------------- /war/css/jscolors.css: -------------------------------------------------------------------------------- 1 | .editbox { 2 | margin: .4em; 3 | padding: 0; 4 | font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; 5 | font-size: 1em; 6 | color: black; 7 | } 8 | 9 | pre.code, .editbox { 10 | color: #666666; 11 | } 12 | 13 | .editbox p { 14 | margin: 0; 15 | } 16 | 17 | span.js-punctuation { 18 | color: #666666; 19 | } 20 | 21 | span.js-operator { 22 | color: #666666; 23 | } 24 | 25 | span.js-keyword { 26 | color: #770088; 27 | } 28 | 29 | span.js-atom { 30 | color: #228811; 31 | } 32 | 33 | span.js-variable { 34 | color: black; 35 | } 36 | 37 | span.js-variabledef { 38 | color: #0000FF; 39 | } 40 | 41 | span.js-localvariable { 42 | color: #004499; 43 | } 44 | 45 | span.js-property { 46 | color: black; 47 | } 48 | 49 | span.js-comment { 50 | color: #AA7700; 51 | } 52 | 53 | span.js-string { 54 | color: #AA2222; 55 | } 56 | -------------------------------------------------------------------------------- /war/css/magnifier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/magnifier.png -------------------------------------------------------------------------------- /war/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial ; 3 | margin: 0px; 4 | } 5 | 6 | h1 { 7 | background: #5C9CCC url('../css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png') repeat-x scroll 50% 50%; 8 | padding: 5px; 9 | margin: 0px; 10 | color: white; 11 | } 12 | 13 | h1 a { 14 | text-decoration: none; 15 | color: white; 16 | } 17 | 18 | h2, #publishedby, .indent { 19 | margin-left: 20px; 20 | } 21 | 22 | pre { 23 | margin-left: 40px; 24 | } 25 | 26 | #publishedby { 27 | font-style: italic; 28 | } 29 | 30 | #actionsBreadcrumb { 31 | padding: 4px 0px 4px 0px; 32 | border: 2px solid #888; 33 | border-right: 0px; 34 | margin: 15px 0px 10px 20px; 35 | display: inline-block; 36 | font-size: 0.8em; 37 | } 38 | 39 | .actionsBreadcrumbHead { 40 | padding: 4px 10px 5px 5px; 41 | font-weight: bold; 42 | color: white; 43 | background-color: #888; 44 | } 45 | 46 | .actionsBreadcrumbChild, .actionsBreadcrumbLastChild { 47 | padding: 4px; 48 | padding-right: 8px; 49 | color: #888; 50 | border-right: 2px dotted #888; 51 | } 52 | 53 | .actionsBreadcrumbLastChild { 54 | border-right: 2px solid #888; 55 | } 56 | 57 | .actionsBreadcrumbChild a, .actionsBreadcrumbLastChild a { 58 | color: #888; 59 | text-decoration: none; 60 | } 61 | 62 | .actionsBreadcrumbChild a:hover, .actionsBreadcrumbLastChild a:hover { 63 | text-decoration: underline; 64 | } 65 | 66 | .redBorder { 67 | border: 1px solid red; 68 | } 69 | 70 | .taglist { 71 | list-style-type: none; 72 | } 73 | 74 | .taglist li { 75 | display: inline; 76 | padding-right: 10px; 77 | } 78 | 79 | .border { 80 | background-color: #FAFAFF; 81 | border: 1px solid darkgray; 82 | } 83 | 84 | .hidden { 85 | display: none; 86 | } 87 | 88 | .smaller { 89 | font-size: small; 90 | color: gray; 91 | } 92 | 93 | #backtoconsole { 94 | margin-left: 20px; 95 | font-family: Arial, sans-serif; 96 | } 97 | 98 | #shareThis { 99 | float: right; 100 | margin: 10px; 101 | } 102 | 103 | #shareThis a { 104 | text-decoration: none; 105 | } 106 | 107 | #embedText, #dialog { 108 | display: none; 109 | } 110 | 111 | #viewAllScripts, #commentsArea { 112 | margin-left: 20px; 113 | } 114 | 115 | #about { 116 | font-family: Arial, sans-serif; 117 | font-size: small; 118 | color: gray; 119 | } 120 | 121 | #textarea-container { 122 | background: url('../images/google-app-engine-groovy.png') no-repeat 98% bottom; 123 | margin-bottom: 10px; 124 | } 125 | 126 | #commentsArea #idc-container h3 { 127 | font-weight: bold; 128 | font-size: 14pt; 129 | } 130 | 131 | #button-bar { 132 | padding: 5px; 133 | margin-bottom: 20px; 134 | } 135 | 136 | #loadingDiv { 137 | position: fixed; 138 | background-color: white; 139 | right: 10px; 140 | top: 12px; 141 | } 142 | 143 | .CodeMirror-line-numbers { 144 | color: gray; 145 | background-color: lightgray; 146 | padding: 5px; 147 | margin-right: 5px; 148 | font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; 149 | font-size: 1em; 150 | } 151 | 152 | .ui-tabs .ui-tabs-hide { 153 | display: none; 154 | } 155 | 156 | .ui-tabs .ui-tabs-panel { 157 | padding: 2px; 158 | } 159 | 160 | .ui-tabs .ui-tabs-nav li a { 161 | padding: 2px 4px 2px 4px; 162 | font-size: smaller; 163 | } -------------------------------------------------------------------------------- /war/css/page_white_code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/page_white_code.png -------------------------------------------------------------------------------- /war/css/page_white_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/page_white_copy.png -------------------------------------------------------------------------------- /war/css/printer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/printer.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_217bc0_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_217bc0_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_469bdd_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_469bdd_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_6da8d5_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_6da8d5_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_d8e7f3_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_d8e7f3_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/images/ui-icons_f9bd01_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/redmond/images/ui-icons_f9bd01_256x240.png -------------------------------------------------------------------------------- /war/css/redmond/jquery-ui-1.7.1.custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI CSS Framework 3 | * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) 4 | * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. 5 | */ 6 | 7 | /* Layout helpers 8 | ----------------------------------*/ 9 | .ui-helper-hidden { display: none; } 10 | .ui-helper-hidden-accessible { position: absolute; left: -99999999px; } 11 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } 12 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } 13 | .ui-helper-clearfix { display: inline-block; } 14 | /* required comment for clearfix to work in Opera \*/ 15 | * html .ui-helper-clearfix { height:1%; } 16 | .ui-helper-clearfix { display:block; } 17 | /* end clearfix */ 18 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } 19 | 20 | 21 | /* Interaction Cues 22 | ----------------------------------*/ 23 | .ui-state-disabled { cursor: default !important; } 24 | 25 | 26 | /* Icons 27 | ----------------------------------*/ 28 | 29 | /* states and images */ 30 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } 31 | 32 | 33 | /* Misc visuals 34 | ----------------------------------*/ 35 | 36 | /* Overlays */ 37 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } 38 | 39 | /* 40 | * jQuery UI CSS Framework 41 | * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) 42 | * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. 43 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px 44 | */ 45 | 46 | 47 | /* Component containers 48 | ----------------------------------*/ 49 | .ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; } 50 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; } 51 | .ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; } 52 | .ui-widget-content a { color: #222222; } 53 | .ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } 54 | .ui-widget-header a { color: #ffffff; } 55 | 56 | /* Interaction states 57 | ----------------------------------*/ 58 | .ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; } 59 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; } 60 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; } 61 | .ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; } 62 | .ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; } 63 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; } 64 | 65 | /* Interaction Cues 66 | ----------------------------------*/ 67 | .ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; } 68 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } 69 | .ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } 70 | .ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; } 71 | .ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } 72 | .ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } 73 | .ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } 74 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } 75 | 76 | /* Icons 77 | ----------------------------------*/ 78 | 79 | /* states and images */ 80 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); } 81 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); } 82 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); } 83 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); } 84 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); } 85 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } 86 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } 87 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } 88 | 89 | /* positioning */ 90 | .ui-icon-carat-1-n { background-position: 0 0; } 91 | .ui-icon-carat-1-ne { background-position: -16px 0; } 92 | .ui-icon-carat-1-e { background-position: -32px 0; } 93 | .ui-icon-carat-1-se { background-position: -48px 0; } 94 | .ui-icon-carat-1-s { background-position: -64px 0; } 95 | .ui-icon-carat-1-sw { background-position: -80px 0; } 96 | .ui-icon-carat-1-w { background-position: -96px 0; } 97 | .ui-icon-carat-1-nw { background-position: -112px 0; } 98 | .ui-icon-carat-2-n-s { background-position: -128px 0; } 99 | .ui-icon-carat-2-e-w { background-position: -144px 0; } 100 | .ui-icon-triangle-1-n { background-position: 0 -16px; } 101 | .ui-icon-triangle-1-ne { background-position: -16px -16px; } 102 | .ui-icon-triangle-1-e { background-position: -32px -16px; } 103 | .ui-icon-triangle-1-se { background-position: -48px -16px; } 104 | .ui-icon-triangle-1-s { background-position: -64px -16px; } 105 | .ui-icon-triangle-1-sw { background-position: -80px -16px; } 106 | .ui-icon-triangle-1-w { background-position: -96px -16px; } 107 | .ui-icon-triangle-1-nw { background-position: -112px -16px; } 108 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; } 109 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; } 110 | .ui-icon-arrow-1-n { background-position: 0 -32px; } 111 | .ui-icon-arrow-1-ne { background-position: -16px -32px; } 112 | .ui-icon-arrow-1-e { background-position: -32px -32px; } 113 | .ui-icon-arrow-1-se { background-position: -48px -32px; } 114 | .ui-icon-arrow-1-s { background-position: -64px -32px; } 115 | .ui-icon-arrow-1-sw { background-position: -80px -32px; } 116 | .ui-icon-arrow-1-w { background-position: -96px -32px; } 117 | .ui-icon-arrow-1-nw { background-position: -112px -32px; } 118 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; } 119 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } 120 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; } 121 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } 122 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; } 123 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; } 124 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; } 125 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; } 126 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; } 127 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } 128 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; } 129 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; } 130 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; } 131 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } 132 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; } 133 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } 134 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } 135 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } 136 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } 137 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } 138 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } 139 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } 140 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } 141 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } 142 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } 143 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } 144 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } 145 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } 146 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } 147 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } 148 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } 149 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } 150 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } 151 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } 152 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } 153 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } 154 | .ui-icon-arrow-4 { background-position: 0 -80px; } 155 | .ui-icon-arrow-4-diag { background-position: -16px -80px; } 156 | .ui-icon-extlink { background-position: -32px -80px; } 157 | .ui-icon-newwin { background-position: -48px -80px; } 158 | .ui-icon-refresh { background-position: -64px -80px; } 159 | .ui-icon-shuffle { background-position: -80px -80px; } 160 | .ui-icon-transfer-e-w { background-position: -96px -80px; } 161 | .ui-icon-transferthick-e-w { background-position: -112px -80px; } 162 | .ui-icon-folder-collapsed { background-position: 0 -96px; } 163 | .ui-icon-folder-open { background-position: -16px -96px; } 164 | .ui-icon-document { background-position: -32px -96px; } 165 | .ui-icon-document-b { background-position: -48px -96px; } 166 | .ui-icon-note { background-position: -64px -96px; } 167 | .ui-icon-mail-closed { background-position: -80px -96px; } 168 | .ui-icon-mail-open { background-position: -96px -96px; } 169 | .ui-icon-suitcase { background-position: -112px -96px; } 170 | .ui-icon-comment { background-position: -128px -96px; } 171 | .ui-icon-person { background-position: -144px -96px; } 172 | .ui-icon-print { background-position: -160px -96px; } 173 | .ui-icon-trash { background-position: -176px -96px; } 174 | .ui-icon-locked { background-position: -192px -96px; } 175 | .ui-icon-unlocked { background-position: -208px -96px; } 176 | .ui-icon-bookmark { background-position: -224px -96px; } 177 | .ui-icon-tag { background-position: -240px -96px; } 178 | .ui-icon-home { background-position: 0 -112px; } 179 | .ui-icon-flag { background-position: -16px -112px; } 180 | .ui-icon-calendar { background-position: -32px -112px; } 181 | .ui-icon-cart { background-position: -48px -112px; } 182 | .ui-icon-pencil { background-position: -64px -112px; } 183 | .ui-icon-clock { background-position: -80px -112px; } 184 | .ui-icon-disk { background-position: -96px -112px; } 185 | .ui-icon-calculator { background-position: -112px -112px; } 186 | .ui-icon-zoomin { background-position: -128px -112px; } 187 | .ui-icon-zoomout { background-position: -144px -112px; } 188 | .ui-icon-search { background-position: -160px -112px; } 189 | .ui-icon-wrench { background-position: -176px -112px; } 190 | .ui-icon-gear { background-position: -192px -112px; } 191 | .ui-icon-heart { background-position: -208px -112px; } 192 | .ui-icon-star { background-position: -224px -112px; } 193 | .ui-icon-link { background-position: -240px -112px; } 194 | .ui-icon-cancel { background-position: 0 -128px; } 195 | .ui-icon-plus { background-position: -16px -128px; } 196 | .ui-icon-plusthick { background-position: -32px -128px; } 197 | .ui-icon-minus { background-position: -48px -128px; } 198 | .ui-icon-minusthick { background-position: -64px -128px; } 199 | .ui-icon-close { background-position: -80px -128px; } 200 | .ui-icon-closethick { background-position: -96px -128px; } 201 | .ui-icon-key { background-position: -112px -128px; } 202 | .ui-icon-lightbulb { background-position: -128px -128px; } 203 | .ui-icon-scissors { background-position: -144px -128px; } 204 | .ui-icon-clipboard { background-position: -160px -128px; } 205 | .ui-icon-copy { background-position: -176px -128px; } 206 | .ui-icon-contact { background-position: -192px -128px; } 207 | .ui-icon-image { background-position: -208px -128px; } 208 | .ui-icon-video { background-position: -224px -128px; } 209 | .ui-icon-script { background-position: -240px -128px; } 210 | .ui-icon-alert { background-position: 0 -144px; } 211 | .ui-icon-info { background-position: -16px -144px; } 212 | .ui-icon-notice { background-position: -32px -144px; } 213 | .ui-icon-help { background-position: -48px -144px; } 214 | .ui-icon-check { background-position: -64px -144px; } 215 | .ui-icon-bullet { background-position: -80px -144px; } 216 | .ui-icon-radio-off { background-position: -96px -144px; } 217 | .ui-icon-radio-on { background-position: -112px -144px; } 218 | .ui-icon-pin-w { background-position: -128px -144px; } 219 | .ui-icon-pin-s { background-position: -144px -144px; } 220 | .ui-icon-play { background-position: 0 -160px; } 221 | .ui-icon-pause { background-position: -16px -160px; } 222 | .ui-icon-seek-next { background-position: -32px -160px; } 223 | .ui-icon-seek-prev { background-position: -48px -160px; } 224 | .ui-icon-seek-end { background-position: -64px -160px; } 225 | .ui-icon-seek-first { background-position: -80px -160px; } 226 | .ui-icon-stop { background-position: -96px -160px; } 227 | .ui-icon-eject { background-position: -112px -160px; } 228 | .ui-icon-volume-off { background-position: -128px -160px; } 229 | .ui-icon-volume-on { background-position: -144px -160px; } 230 | .ui-icon-power { background-position: 0 -176px; } 231 | .ui-icon-signal-diag { background-position: -16px -176px; } 232 | .ui-icon-signal { background-position: -32px -176px; } 233 | .ui-icon-battery-0 { background-position: -48px -176px; } 234 | .ui-icon-battery-1 { background-position: -64px -176px; } 235 | .ui-icon-battery-2 { background-position: -80px -176px; } 236 | .ui-icon-battery-3 { background-position: -96px -176px; } 237 | .ui-icon-circle-plus { background-position: 0 -192px; } 238 | .ui-icon-circle-minus { background-position: -16px -192px; } 239 | .ui-icon-circle-close { background-position: -32px -192px; } 240 | .ui-icon-circle-triangle-e { background-position: -48px -192px; } 241 | .ui-icon-circle-triangle-s { background-position: -64px -192px; } 242 | .ui-icon-circle-triangle-w { background-position: -80px -192px; } 243 | .ui-icon-circle-triangle-n { background-position: -96px -192px; } 244 | .ui-icon-circle-arrow-e { background-position: -112px -192px; } 245 | .ui-icon-circle-arrow-s { background-position: -128px -192px; } 246 | .ui-icon-circle-arrow-w { background-position: -144px -192px; } 247 | .ui-icon-circle-arrow-n { background-position: -160px -192px; } 248 | .ui-icon-circle-zoomin { background-position: -176px -192px; } 249 | .ui-icon-circle-zoomout { background-position: -192px -192px; } 250 | .ui-icon-circle-check { background-position: -208px -192px; } 251 | .ui-icon-circlesmall-plus { background-position: 0 -208px; } 252 | .ui-icon-circlesmall-minus { background-position: -16px -208px; } 253 | .ui-icon-circlesmall-close { background-position: -32px -208px; } 254 | .ui-icon-squaresmall-plus { background-position: -48px -208px; } 255 | .ui-icon-squaresmall-minus { background-position: -64px -208px; } 256 | .ui-icon-squaresmall-close { background-position: -80px -208px; } 257 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } 258 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } 259 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; } 260 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } 261 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } 262 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; } 263 | 264 | 265 | /* Misc visuals 266 | ----------------------------------*/ 267 | 268 | /* Corner radius */ 269 | .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; } 270 | .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } 271 | .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } 272 | .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } 273 | .ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } 274 | .ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } 275 | .ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } 276 | .ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } 277 | .ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; } 278 | 279 | /* Overlays */ 280 | .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } 281 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion 282 | ----------------------------------*/ 283 | .ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } 284 | .ui-accordion .ui-accordion-li-fix { display: inline; } 285 | .ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } 286 | .ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } 287 | .ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } 288 | .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } 289 | .ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker 290 | ----------------------------------*/ 291 | .ui-datepicker { width: 17em; padding: .2em .2em 0; } 292 | .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } 293 | .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } 294 | .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } 295 | .ui-datepicker .ui-datepicker-prev { left:2px; } 296 | .ui-datepicker .ui-datepicker-next { right:2px; } 297 | .ui-datepicker .ui-datepicker-prev-hover { left:1px; } 298 | .ui-datepicker .ui-datepicker-next-hover { right:1px; } 299 | .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } 300 | .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } 301 | .ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } 302 | .ui-datepicker select.ui-datepicker-month-year {width: 100%;} 303 | .ui-datepicker select.ui-datepicker-month, 304 | .ui-datepicker select.ui-datepicker-year { width: 49%;} 305 | .ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } 306 | .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } 307 | .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } 308 | .ui-datepicker td { border: 0; padding: 1px; } 309 | .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } 310 | .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } 311 | .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } 312 | .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } 313 | 314 | /* with multiple calendars */ 315 | .ui-datepicker.ui-datepicker-multi { width:auto; } 316 | .ui-datepicker-multi .ui-datepicker-group { float:left; } 317 | .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } 318 | .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } 319 | .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } 320 | .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } 321 | .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } 322 | .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } 323 | .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } 324 | .ui-datepicker-row-break { clear:both; width:100%; } 325 | 326 | /* RTL support */ 327 | .ui-datepicker-rtl { direction: rtl; } 328 | .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } 329 | .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } 330 | .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } 331 | .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } 332 | .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } 333 | .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } 334 | .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } 335 | .ui-datepicker-rtl .ui-datepicker-group { float:right; } 336 | .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 337 | .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } 338 | 339 | /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ 340 | .ui-datepicker-cover { 341 | display: none; /*sorry for IE5*/ 342 | display/**/: block; /*sorry for IE5*/ 343 | position: absolute; /*must have*/ 344 | z-index: -1; /*must have*/ 345 | filter: mask(); /*must have*/ 346 | top: -4px; /*must have*/ 347 | left: -4px; /*must have*/ 348 | width: 200px; /*must have*/ 349 | height: 200px; /*must have*/ 350 | }/* Dialog 351 | ----------------------------------*/ 352 | .ui-dialog { position: relative; padding: .2em; width: 300px; } 353 | .ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } 354 | .ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 355 | .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } 356 | .ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } 357 | .ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } 358 | .ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } 359 | .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } 360 | .ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } 361 | .ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } 362 | .ui-draggable .ui-dialog-titlebar { cursor: move; } 363 | /* Progressbar 364 | ----------------------------------*/ 365 | .ui-progressbar { height:2em; text-align: left; } 366 | .ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable 367 | ----------------------------------*/ 368 | .ui-resizable { position: relative;} 369 | .ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} 370 | .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } 371 | .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } 372 | .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } 373 | .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } 374 | .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } 375 | .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } 376 | .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } 377 | .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } 378 | .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider 379 | ----------------------------------*/ 380 | .ui-slider { position: relative; text-align: left; } 381 | .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } 382 | .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } 383 | 384 | .ui-slider-horizontal { height: .8em; } 385 | .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } 386 | .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } 387 | .ui-slider-horizontal .ui-slider-range-min { left: 0; } 388 | .ui-slider-horizontal .ui-slider-range-max { right: 0; } 389 | 390 | .ui-slider-vertical { width: .8em; height: 100px; } 391 | .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } 392 | .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } 393 | .ui-slider-vertical .ui-slider-range-min { bottom: 0; } 394 | .ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs 395 | ----------------------------------*/ 396 | .ui-tabs { padding: .2em; zoom: 1; } 397 | .ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } 398 | .ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } 399 | .ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } 400 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } 401 | .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } 402 | .ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ 403 | .ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } 404 | .ui-tabs .ui-tabs-hide { display: none !important; } 405 | -------------------------------------------------------------------------------- /war/css/shCore.css: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | .syntaxhighlighter, 31 | .syntaxhighlighter div, 32 | .syntaxhighlighter code, 33 | .syntaxhighlighter span 34 | { 35 | margin: 0 !important; 36 | padding: 0 !important; 37 | border: 0 !important; 38 | outline: 0 !important; 39 | background: none !important; 40 | text-align: left !important; 41 | float: none !important; 42 | vertical-align: baseline !important; 43 | position: static !important; 44 | left: auto !important; 45 | top: auto !important; 46 | right: auto !important; 47 | bottom: auto !important; 48 | height: auto !important; 49 | width: auto !important; 50 | line-height: 1.2em !important; 51 | font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important; 52 | font-weight: normal !important; 53 | font-style: normal !important; 54 | font-size: 1em !important; 55 | } 56 | 57 | .syntaxhighlighter 58 | { 59 | width: 100% !important; 60 | margin: 1em 0 1em 0 !important; 61 | padding: 1px !important; /* adds a little border on top and bottom */ 62 | position: relative !important; 63 | } 64 | 65 | .syntaxhighlighter code { 66 | display: inline !important; 67 | } 68 | 69 | .syntaxhighlighter .bold { 70 | font-weight: bold !important; 71 | } 72 | 73 | .syntaxhighlighter .italic { 74 | font-style: italic !important; 75 | } 76 | 77 | .syntaxhighlighter .line .number 78 | { 79 | float: left !important; 80 | width: 3em !important; 81 | padding-right: .3em !important; 82 | text-align: right !important; 83 | display: block !important; 84 | } 85 | 86 | /* Disable numbers when no gutter option is set */ 87 | .syntaxhighlighter.nogutter .line .number 88 | { 89 | display: none !important; 90 | } 91 | 92 | .syntaxhighlighter .line .content 93 | { 94 | margin-left: 3.3em !important; 95 | padding-left: .5em !important; 96 | display: block !important; 97 | } 98 | 99 | .syntaxhighlighter .line .content .block 100 | { 101 | display: block !important; 102 | padding-left: 1.5em !important; 103 | text-indent: -1.5em !important; 104 | } 105 | 106 | .syntaxhighlighter .line .content .spaces 107 | { 108 | display: none !important; 109 | } 110 | 111 | /* Disable border and margin on the lines when no gutter option is set */ 112 | .syntaxhighlighter.nogutter .line .content 113 | { 114 | margin-left: 0 !important; 115 | border-left: none !important; 116 | } 117 | 118 | .syntaxhighlighter .bar 119 | { 120 | display: none !important; 121 | } 122 | 123 | .syntaxhighlighter .bar.show 124 | { 125 | display: block !important; 126 | } 127 | 128 | .syntaxhighlighter.collapsed .bar 129 | { 130 | display: block !important; 131 | } 132 | 133 | .syntaxhighlighter.nogutter .ruler 134 | { 135 | margin-left: 0 !important; 136 | padding-left: 0 !important; 137 | } 138 | 139 | .syntaxhighlighter .ruler 140 | { 141 | padding: 0 0 .5em .5em !important; 142 | margin-left: 3.3em !important; 143 | overflow: hidden !important; 144 | } 145 | 146 | /* Adjust some properties when collapsed */ 147 | 148 | .syntaxhighlighter.collapsed .lines, 149 | .syntaxhighlighter.collapsed .ruler 150 | { 151 | display: none !important; 152 | } 153 | 154 | .syntaxhighlighter .lines.no-wrap 155 | { 156 | overflow: auto; 157 | overflow-y: hidden; 158 | } 159 | 160 | /* Styles for the toolbar */ 161 | 162 | .syntaxhighlighter .toolbar 163 | { 164 | position: absolute !important; 165 | right: 0px !important; 166 | top: 0px !important; 167 | font-size: 1px !important; 168 | padding: 8px 8px 8px 0 !important; /* in px because images don't scale with ems */ 169 | } 170 | 171 | .syntaxhighlighter.collapsed .toolbar 172 | { 173 | font-size: 80% !important; 174 | padding: .2em 0 .5em .5em !important; 175 | position: static !important; 176 | } 177 | 178 | .syntaxhighlighter .toolbar a.item, 179 | .syntaxhighlighter .toolbar .item 180 | { 181 | display: block !important; 182 | float: left !important; 183 | margin-left: 8px !important; 184 | background-repeat: no-repeat !important; 185 | overflow: hidden !important; 186 | text-indent: -5000px !important; 187 | } 188 | 189 | .syntaxhighlighter.collapsed .toolbar .item 190 | { 191 | display: none !important; 192 | } 193 | 194 | .syntaxhighlighter.collapsed .toolbar .item.expandSource 195 | { 196 | background-image: url(magnifier.png) !important; 197 | display: inline !important; 198 | text-indent: 0 !important; 199 | width: auto !important; 200 | float: none !important; 201 | height: 16px !important; 202 | padding-left: 20px !important; 203 | } 204 | 205 | .syntaxhighlighter .toolbar .item.viewSource 206 | { 207 | background-image: url(page_white_code.png) !important; 208 | } 209 | 210 | .syntaxhighlighter .toolbar .item.printSource 211 | { 212 | background-image: url(printer.png) !important; 213 | } 214 | 215 | .syntaxhighlighter .toolbar .item.copyToClipboard 216 | { 217 | text-indent: 0 !important; 218 | background: none !important; 219 | overflow: visible !important; 220 | } 221 | 222 | .syntaxhighlighter .toolbar .item.about 223 | { 224 | background-image: url(help.png) !important; 225 | } 226 | 227 | /** 228 | * Print view. 229 | * Colors are based on the default theme without background. 230 | */ 231 | 232 | .syntaxhighlighter.printing, 233 | .syntaxhighlighter.printing .line.alt1 .content, 234 | .syntaxhighlighter.printing .line.alt2 .content, 235 | .syntaxhighlighter.printing .line.highlighted .number, 236 | .syntaxhighlighter.printing .line.highlighted.alt1 .content, 237 | .syntaxhighlighter.printing .line.highlighted.alt2 .content, 238 | .syntaxhighlighter.printing .line .content .block 239 | { 240 | background: none !important; 241 | } 242 | 243 | .syntaxhighlighter .no-wrap .line .content .block 244 | { 245 | white-space: nowrap !important; 246 | } 247 | 248 | /* Gutter line numbers */ 249 | .syntaxhighlighter.printing .line .number 250 | { 251 | color: #bbb !important; 252 | } 253 | 254 | /* Add border to the lines */ 255 | .syntaxhighlighter.printing .line .content 256 | { 257 | color: #000 !important; 258 | } 259 | 260 | /* Toolbar when visible */ 261 | .syntaxhighlighter.printing .toolbar, 262 | .syntaxhighlighter.printing .ruler 263 | { 264 | display: none !important; 265 | } 266 | 267 | .syntaxhighlighter.printing a 268 | { 269 | text-decoration: none !important; 270 | } 271 | 272 | .syntaxhighlighter.printing .plain, 273 | .syntaxhighlighter.printing .plain a 274 | { 275 | color: #000 !important; 276 | } 277 | 278 | .syntaxhighlighter.printing .comments, 279 | .syntaxhighlighter.printing .comments a 280 | { 281 | color: #008200 !important; 282 | } 283 | 284 | .syntaxhighlighter.printing .string, 285 | .syntaxhighlighter.printing .string a 286 | { 287 | color: blue !important; 288 | } 289 | 290 | .syntaxhighlighter.printing .keyword 291 | { 292 | color: #069 !important; 293 | font-weight: bold !important; 294 | } 295 | 296 | .syntaxhighlighter.printing .preprocessor 297 | { 298 | color: gray !important; 299 | } 300 | 301 | .syntaxhighlighter.printing .variable 302 | { 303 | color: #a70 !important; 304 | } 305 | 306 | .syntaxhighlighter.printing .value 307 | { 308 | color: #090 !important; 309 | } 310 | 311 | .syntaxhighlighter.printing .functions 312 | { 313 | color: #ff1493 !important; 314 | } 315 | 316 | .syntaxhighlighter.printing .constants 317 | { 318 | color: #0066CC !important; 319 | } 320 | 321 | .syntaxhighlighter.printing .script 322 | { 323 | font-weight: bold !important; 324 | } 325 | 326 | .syntaxhighlighter.printing .color1, 327 | .syntaxhighlighter.printing .color1 a 328 | { 329 | color: #808080 !important; 330 | } 331 | 332 | .syntaxhighlighter.printing .color2, 333 | .syntaxhighlighter.printing .color2 a 334 | { 335 | color: #ff1493 !important; 336 | } 337 | 338 | .syntaxhighlighter.printing .color3, 339 | .syntaxhighlighter.printing .color3 a 340 | { 341 | color: red !important; 342 | } 343 | -------------------------------------------------------------------------------- /war/css/shThemeDefault.css: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | /************************************ 31 | * Default Syntax Highlighter theme. 32 | * 33 | * Interface elements. 34 | ************************************/ 35 | 36 | .syntaxhighlighter 37 | { 38 | /* background-color: #E7E5DC !important; */ 39 | background-color: #FAFAFA !important; 40 | border-left: 5px solid lightgray !important; 41 | padding: 10px !important; 42 | margin-left: 20px !important; 43 | width: 90% !important; 44 | } 45 | 46 | /* Highlighed line number */ 47 | .syntaxhighlighter .line.highlighted .number 48 | { 49 | background-color: #6CE26C !important; 50 | color: black !important; 51 | } 52 | 53 | /* Highlighed line */ 54 | .syntaxhighlighter .line.highlighted.alt1 .content, 55 | .syntaxhighlighter .line.highlighted.alt2 .content 56 | { 57 | background-color: #6CE26C !important; 58 | } 59 | 60 | /* Gutter line numbers */ 61 | .syntaxhighlighter .line .number 62 | { 63 | color: #888 !important; 64 | } 65 | 66 | /* Add border to the lines */ 67 | .syntaxhighlighter .line .content 68 | { 69 | /* border-left: 3px solid #6CE26C !important; */ 70 | color: #000 !important; 71 | } 72 | 73 | .syntaxhighlighter.printing .line .content 74 | { 75 | border: 0 !important; 76 | } 77 | 78 | /* First line */ 79 | .syntaxhighlighter .line.alt1 .content 80 | { 81 | /* background-color: #fff !important; */ 82 | } 83 | 84 | /* Second line */ 85 | .syntaxhighlighter .line.alt2 .content 86 | { 87 | /* background-color: #F8F8F8 !important; */ 88 | } 89 | 90 | .syntaxhighlighter .line .content .block 91 | { 92 | background: url(wrapping.png) 0 1.1em no-repeat !important; 93 | } 94 | 95 | .syntaxhighlighter .ruler 96 | { 97 | color: silver !important; 98 | background-color: #F8F8F8 !important; 99 | border-left: 3px solid #6CE26C !important; 100 | } 101 | 102 | .syntaxhighlighter.nogutter .ruler 103 | { 104 | border: 0 !important; 105 | } 106 | 107 | .syntaxhighlighter .toolbar 108 | { 109 | background-color: #F8F8F8 !important; 110 | border: #E7E5DC solid 1px !important; 111 | } 112 | 113 | .syntaxhighlighter .toolbar a 114 | { 115 | color: #a0a0a0 !important; 116 | } 117 | 118 | .syntaxhighlighter .toolbar a:hover 119 | { 120 | color: red !important; 121 | } 122 | 123 | /************************************ 124 | * Actual syntax highlighter colors. 125 | ************************************/ 126 | .syntaxhighlighter .plain, 127 | .syntaxhighlighter .plain a 128 | { 129 | color: #000 !important; 130 | } 131 | 132 | .syntaxhighlighter .comments, 133 | .syntaxhighlighter .comments a 134 | { 135 | color: #AA7700 !important; 136 | } 137 | 138 | .syntaxhighlighter .string, 139 | .syntaxhighlighter .string a 140 | { 141 | color: #AA2222 !important; 142 | } 143 | 144 | .syntaxhighlighter .keyword 145 | { 146 | color: #770088 !important; 147 | font-weight: bold !important; 148 | } 149 | 150 | .syntaxhighlighter .preprocessor 151 | { 152 | color: gray !important; 153 | } 154 | 155 | .syntaxhighlighter .variable 156 | { 157 | color: #a70 !important; 158 | } 159 | 160 | .syntaxhighlighter .value 161 | { 162 | color: #090 !important; 163 | } 164 | 165 | .syntaxhighlighter .functions 166 | { 167 | color: black !important; 168 | } 169 | 170 | .syntaxhighlighter .constants 171 | { 172 | color: #228811 !important; 173 | } 174 | 175 | .syntaxhighlighter .script 176 | { 177 | background-color: yellow !important; 178 | } 179 | 180 | .syntaxhighlighter .color1, 181 | .syntaxhighlighter .color1 a 182 | { 183 | color: #770088 !important; 184 | } 185 | 186 | .syntaxhighlighter .color2, 187 | .syntaxhighlighter .color2 a 188 | { 189 | color: #ff1493 !important; 190 | } 191 | 192 | .syntaxhighlighter .color3, 193 | .syntaxhighlighter .color3 a 194 | { 195 | color: red !important; 196 | } 197 | -------------------------------------------------------------------------------- /war/css/wrapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/css/wrapping.png -------------------------------------------------------------------------------- /war/embed.gtpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <% def entity = request.getAttribute('entity') %> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 |
25 |
26 | ${entity.title ?: 'Untitled'} 27 | 28 | 29 | Published ${new org.ocpsoft.prettytime.PrettyTime().format(entity.dateCreated)} 30 | on the Groovy Web Console 31 | 32 | 33 | by 34 | ${entity.author} 35 | 36 |
37 |
${entity.script.value.replaceAll('<', '<')}
38 |
39 | 40 | -------------------------------------------------------------------------------- /war/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/favicon.ico -------------------------------------------------------------------------------- /war/flash/clipboard.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/flash/clipboard.swf -------------------------------------------------------------------------------- /war/images/ajax-spinner-blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/ajax-spinner-blue.gif -------------------------------------------------------------------------------- /war/images/atom-feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/atom-feed.png -------------------------------------------------------------------------------- /war/images/date.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/date.png -------------------------------------------------------------------------------- /war/images/google-app-engine-groovy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/google-app-engine-groovy.png -------------------------------------------------------------------------------- /war/images/people.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/people.jpg -------------------------------------------------------------------------------- /war/images/puzzle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/puzzle.png -------------------------------------------------------------------------------- /war/images/tag_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/tag_blue.png -------------------------------------------------------------------------------- /war/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/twitter.png -------------------------------------------------------------------------------- /war/images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glaforge/groovywebconsole/84256e8533a7e79b57ed16aa9066a24d24fcec51/war/images/user.png -------------------------------------------------------------------------------- /war/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groovy web console 4 | 5 | 10 | 11 | 12 | 13 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | 52 |
53 | 54 |

Groovy web console

55 | 56 |
57 |
58 | 59 |
60 | 61 | 62 | 63 | 73 | 74 |
64 | 65 | 66 | 67 | 68 | 69 | 70 |
subscribe to the feedSubscribe
to this
site
71 |
72 |
75 | 76 |
77 | 78 | 79 | 80 | 81 | 82 |
83 | Actions 84 | Execute script  ▶ 85 | New script 86 | Publish script 87 | View recent scripts 88 |
89 |
90 |
91 | 92 |
93 | 94 |
95 | 96 |
97 |
98 | 99 |
100 | 101 |
102 |
103 | 104 |
105 | 106 |
107 |
108 | 109 |
110 | 111 | 112 |
113 | 114 |
115 | 120 | 121 |
122 | 123 |
124 | 125 |
126 | 127 |
128 | 129 |
130 | 131 |
132 |
133 | 134 |
135 |

Console tips

136 |
    137 |
  • You can hit Alt-Meta-R to execute the current script without using the execute button.
  • 138 |
  • You can resize the script view by sliding down the bottom of the line number gutter.
  • 139 |
140 |

About this site:

141 |
    142 |

    The Groovy Web Console is a website for sharing and executing Groovy programming snippets of code!

    143 |
  • Application deployed on Google App Engine
  • 144 |
  • Developed with the Gaelyk lightweight Groovy toolkit for Google App Engine
  • 145 |
  • Programmed with Groovy
  • 146 |
  • Code hosted on GitHub and managed with Git
  • 147 |
  • Live syntax highlighting provided by CodeMirror
  • 148 |
  • Syntax highlighting for sharing provided by SyntaxHighlighter
  • 149 |
150 |
151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /war/js/codemirror.js: -------------------------------------------------------------------------------- 1 | /* CodeMirror main module 2 | * 3 | * Implements the CodeMirror constructor and prototype, which take care 4 | * of initializing the editor frame, and providing the outside interface. 5 | */ 6 | 7 | // The CodeMirrorConfig object is used to specify a default 8 | // configuration. If you specify such an object before loading this 9 | // file, the values you put into it will override the defaults given 10 | // below. You can also assign to it after loading. 11 | var CodeMirrorConfig = window.CodeMirrorConfig || {}; 12 | 13 | var CodeMirror = (function(){ 14 | function setDefaults(object, defaults) { 15 | for (var option in defaults) { 16 | if (!object.hasOwnProperty(option)) 17 | object[option] = defaults[option]; 18 | } 19 | } 20 | function forEach(array, action) { 21 | for (var i = 0; i < array.length; i++) 22 | action(array[i]); 23 | } 24 | 25 | // These default options can be overridden by passing a set of 26 | // options to a specific CodeMirror constructor. See manual.html for 27 | // their meaning. 28 | setDefaults(CodeMirrorConfig, { 29 | stylesheet: "", 30 | path: "", 31 | parserfile: [], 32 | basefiles: ["util.js", "stringstream.js", "select.js", "undo.js", "editor.js", "tokenize.js"], 33 | linesPerPass: 30, 34 | passDelay: 200, 35 | continuousScanning: false, 36 | saveFunction: null, 37 | submitFunction: null, 38 | onChange: null, 39 | undoDepth: 50, 40 | undoDelay: 800, 41 | disableSpellcheck: true, 42 | textWrapping: true, 43 | readOnly: false, 44 | width: "100%", 45 | height: "300px", 46 | autoMatchParens: false, 47 | parserConfig: null, 48 | tabMode: "indent", // or "spaces", "default", "shift" 49 | activeTokens: null, 50 | cursorActivity: null, 51 | lineNumbers: false, 52 | indentUnit: 2 53 | }); 54 | 55 | function wrapLineNumberDiv(place) { 56 | return function(node) { 57 | var container = document.createElement("DIV"), 58 | nums = document.createElement("DIV"), 59 | scroller = document.createElement("DIV"); 60 | container.style.position = "relative"; 61 | nums.style.position = "absolute"; 62 | nums.style.height = "100%"; 63 | if (nums.style.setExpression) 64 | nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'"); 65 | nums.style.top = "0px"; 66 | nums.style.overflow = "hidden"; 67 | place(container); 68 | container.appendChild(node); 69 | container.appendChild(nums); 70 | scroller.className = "CodeMirror-line-numbers"; 71 | nums.appendChild(scroller); 72 | } 73 | } 74 | 75 | function applyLineNumbers(frame) { 76 | var win = frame.contentWindow, doc = win.document, 77 | nums = frame.nextSibling, scroller = nums.firstChild; 78 | 79 | var nextNum = 1, barWidth = null; 80 | function sizeBar() { 81 | if (nums.offsetWidth != barWidth) { 82 | barWidth = nums.offsetWidth; 83 | nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px"); 84 | } 85 | } 86 | function update() { 87 | var diff = 20 + Math.max(doc.body.offsetHeight, frame.offsetHeight) - scroller.offsetHeight; 88 | for (var n = Math.ceil(diff / 10); n > 0; n--) { 89 | scroller.appendChild(document.createTextNode(nextNum++)); 90 | scroller.appendChild(document.createElement("BR")); 91 | } 92 | nums.scrollTop = doc.body.scrollTop || doc.documentElement.scrollTop || 0; 93 | } 94 | sizeBar(); 95 | update(); 96 | win.addEventHandler(win, "scroll", update); 97 | setInterval(sizeBar, 500); 98 | } 99 | 100 | function CodeMirror(place, options) { 101 | // Backward compatibility for deprecated options. 102 | if (options.dumbTabs) options.tabMode = "spaces"; 103 | else if (options.normalTab) options.tabMode = "default"; 104 | 105 | // Use passed options, if any, to override defaults. 106 | this.options = options = options || {}; 107 | setDefaults(options, CodeMirrorConfig); 108 | 109 | var frame = this.frame = document.createElement("IFRAME"); 110 | frame.frameBorder = 0; 111 | frame.src = "javascript:false;"; 112 | frame.style.border = "0"; 113 | frame.style.width = options.width; 114 | frame.style.height = options.height; 115 | // display: block occasionally suppresses some Firefox bugs, so we 116 | // always add it, redundant as it sounds. 117 | frame.style.display = "block"; 118 | 119 | if (place.appendChild) { 120 | var node = place; 121 | place = function(n){node.appendChild(n);}; 122 | } 123 | if (options.lineNumbers) place = wrapLineNumberDiv(place); 124 | place(frame); 125 | 126 | // Link back to this object, so that the editor can fetch options 127 | // and add a reference to itself. 128 | frame.CodeMirror = this; 129 | this.win = frame.contentWindow; 130 | 131 | if (typeof options.parserfile == "string") 132 | options.parserfile = [options.parserfile]; 133 | if (typeof options.stylesheet == "string") 134 | options.stylesheet = [options.stylesheet]; 135 | 136 | var html = [""]; 137 | forEach(options.stylesheet, function(file) { 138 | html.push(""); 139 | }); 140 | forEach(options.basefiles.concat(options.parserfile), function(file) { 141 | html.push(""); 142 | }); 143 | html.push(""); 145 | 146 | var doc = this.win.document; 147 | doc.open(); 148 | doc.write(html.join("")); 149 | doc.close(); 150 | } 151 | 152 | CodeMirror.prototype = { 153 | init: function() { 154 | if (this.options.initCallback) this.options.initCallback(this); 155 | if (this.options.lineNumbers) applyLineNumbers(this.frame); 156 | }, 157 | 158 | getCode: function() {return this.editor.getCode();}, 159 | setCode: function(code) {this.editor.importCode(code);}, 160 | selection: function() {return this.editor.selectedText();}, 161 | reindent: function() {this.editor.reindent();}, 162 | 163 | focus: function() { 164 | this.win.focus(); 165 | if (this.editor.selectionSnapshot) // IE hack 166 | this.win.select.selectCoords(this.win, this.editor.selectionSnapshot); 167 | }, 168 | replaceSelection: function(text) { 169 | this.focus(); 170 | this.editor.replaceSelection(text); 171 | return true; 172 | }, 173 | replaceChars: function(text, start, end) { 174 | this.editor.replaceChars(text, start, end); 175 | }, 176 | getSearchCursor: function(string, fromCursor) { 177 | return this.editor.getSearchCursor(string, fromCursor); 178 | }, 179 | 180 | undo: function() {this.editor.history.undo();}, 181 | redo: function() {this.editor.history.redo();}, 182 | historySize: function() {return this.editor.history.historySize();}, 183 | 184 | grabKeys: function(callback, filter) {this.editor.grabKeys(callback, filter);}, 185 | ungrabKeys: function() {this.editor.ungrabKeys();}, 186 | 187 | cursorPosition: function(start) { 188 | if (this.win.select.ie_selection) this.focus(); 189 | return this.editor.cursorPosition(start); 190 | }, 191 | firstLine: function() {return this.editor.firstLine();}, 192 | lastLine: function() {return this.editor.lastLine();}, 193 | nextLine: function(line) {return this.editor.nextLine(line);}, 194 | prevLine: function(line) {return this.editor.prevLine(line);}, 195 | lineContent: function(line) {return this.editor.lineContent(line);}, 196 | setLineContent: function(line, content) {this.editor.setLineContent(line, content);}, 197 | insertIntoLine: function(line, position, content) {this.editor.insertIntoLine(line, position, content);}, 198 | selectLines: function(startLine, startOffset, endLine, endOffset) { 199 | this.win.focus(); 200 | this.editor.selectLines(startLine, startOffset, endLine, endOffset); 201 | }, 202 | nthLine: function(n) { 203 | var line = this.firstLine(); 204 | for (; n > 1 && line !== false; n--) 205 | line = this.nextLine(line); 206 | return line; 207 | }, 208 | lineNumber: function(line) { 209 | var num = 0; 210 | while (line !== false) { 211 | num++; 212 | line = this.prevLine(line); 213 | } 214 | return num; 215 | }, 216 | 217 | // Old number-based line interface 218 | jumpToLine: function(n) { 219 | this.selectLines(this.nthLine(n), 0); 220 | this.win.focus(); 221 | }, 222 | currentLine: function() { 223 | return this.lineNumber(this.cursorPosition().line); 224 | } 225 | }; 226 | 227 | CodeMirror.InvalidLineHandle = {toString: function(){return "CodeMirror.InvalidLineHandle";}}; 228 | 229 | CodeMirror.replace = function(element) { 230 | if (typeof element == "string") 231 | element = document.getElementById(element); 232 | return function(newElement) { 233 | element.parentNode.replaceChild(newElement, element); 234 | }; 235 | }; 236 | 237 | CodeMirror.fromTextArea = function(area, options) { 238 | if (typeof area == "string") 239 | area = document.getElementById(area); 240 | 241 | options = options || {}; 242 | if (area.style.width) options.width = area.style.width; 243 | if (area.style.height) options.height = area.style.height; 244 | if (options.content == null) options.content = area.value; 245 | 246 | if (area.form) { 247 | function updateField() { 248 | area.value = mirror.getCode(); 249 | } 250 | if (typeof area.form.addEventListener == "function") 251 | area.form.addEventListener("submit", updateField, false); 252 | else 253 | area.form.attachEvent("onsubmit", updateField); 254 | } 255 | 256 | function insert(frame) { 257 | if (area.nextSibling) 258 | area.parentNode.insertBefore(frame, area.nextSibling); 259 | else 260 | area.parentNode.appendChild(frame); 261 | } 262 | 263 | area.style.display = "none"; 264 | var mirror = new CodeMirror(insert, options); 265 | return mirror; 266 | }; 267 | 268 | CodeMirror.isProbablySupported = function() { 269 | // This is rather awful, but can be useful. 270 | var match; 271 | if (window.opera) 272 | return Number(window.opera.version()) >= 9.52; 273 | else if (/Apple Computers, Inc/.test(navigator.vendor) && (match = navigator.userAgent.match(/Version\/(\d+(?:\.\d+)?)\./))) 274 | return Number(match[1]) >= 3; 275 | else if (document.selection && window.ActiveXObject && (match = navigator.userAgent.match(/MSIE (\d+(?:\.\d*)?)\b/))) 276 | return Number(match[1]) >= 6; 277 | else if (match = navigator.userAgent.match(/gecko\/(\d{8})/i)) 278 | return Number(match[1]) >= 20050901; 279 | else if (match = navigator.userAgent.match(/AppleWebKit\/(\d+)/)) 280 | return Number(match[1]) >= 525; 281 | else 282 | return null; 283 | }; 284 | 285 | return CodeMirror; 286 | })(); 287 | -------------------------------------------------------------------------------- /war/js/embed.js: -------------------------------------------------------------------------------- 1 | var iframe_url = 'http://groovyconsole.appspot.com/view.groovy?id='+gc_id+'&embed=true'; 2 | var html_content = ""; 3 | document.write (html_content); -------------------------------------------------------------------------------- /war/js/main.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $(function() { 3 | $("#tabs").tabs(); 4 | $("#textarea-container").resizable({ handles: 's', alsoResize: 'iframe' }); 5 | 6 | $("#dialog").dialog({ 7 | bgiframe: true, 8 | autoOpen: false, 9 | height: 400, 10 | width: 330, 11 | modal: true, 12 | buttons: { 13 | Submit: function() { 14 | $("#captchaQuestion").val($("#dialogCaptchaQuestion").val()); 15 | $("#captchaAnswer").val($("#dialogCaptchaAnswer").val()); 16 | $("#title").val($("#dialogTitle").val()); 17 | $("#title").val($("#dialogTitle").val()); 18 | $("#author").val($("#dialogAuthor").val()); 19 | $("#tags").val($("#dialogTags").val()); 20 | $("#script").val(editor.getCode()); 21 | $("#publishform").submit(); 22 | } 23 | } 24 | }); 25 | }); 26 | 27 | $("#captchaOperation").load("/captchaquestion.groovy", function(responseText) { 28 | $("#dialogCaptchaQuestion").val(responseText); 29 | }); 30 | 31 | $("#publishButton").click(function(event) { 32 | var code = editor.getCode(); 33 | // better trim() function than JQuery's 34 | if (code.replace(/^\s+|\s+$/g, '').length > 0) { 35 | $('#dialog').dialog('open'); 36 | event.preventDefault(); 37 | } else { 38 | alert("Please enter a script before publishing."); 39 | event.preventDefault(); 40 | } 41 | }); 42 | 43 | $("#executeButton").click(executeScript); 44 | 45 | $('#loadingDiv') 46 | .hide() 47 | .ajaxStart(function() { 48 | $(this).show(); 49 | }) 50 | .ajaxStop(function() { 51 | $(this).hide(); 52 | }); 53 | }); 54 | 55 | function executeScript() { 56 | $.ajax({ 57 | type: "POST", 58 | url: "/executor.groovy", 59 | data: { script: editor.getCode() }, 60 | dataType: "json", 61 | complete: function (xhr, status) { 62 | if (status === 'error' || !xhr.responseText) { 63 | alert("Error interacting with the Groovy web console server: " + status); 64 | } else { 65 | var data; 66 | try { 67 | data = $.parseJSON(xhr.responseText); 68 | } catch (e) { 69 | alert("Impossible to parse JSON response: " + e); 70 | data = {executionResult: "", outputText: "", stacktraceText: ""}; 71 | } 72 | 73 | $('#output').text(data.outputText); 74 | $('#result').text(data.executionResult); 75 | $('#stacktrace').text(data.stacktraceText); 76 | 77 | if (data.outputText.length > 0) { 78 | $("#tabs").tabs('select', 1); 79 | $('#output').text(data.outputText).fadeIn(); 80 | } else { 81 | $('#output').fadeOut(); 82 | } 83 | 84 | if (data.executionResult.length > 0) { 85 | if (data.executionResult != "null") { 86 | $("#tabs").tabs('select', 0); 87 | } 88 | $('#result').text(data.executionResult).fadeIn(); 89 | } else { 90 | $('#result').fadeOut(); 91 | } 92 | 93 | if (data.stacktraceText.length > 0) { 94 | $("#tabs").tabs('select', 2); 95 | $('#stacktrace').text(data.stacktraceText).fadeIn(); 96 | } else { 97 | $('#stacktrace').fadeOut(); 98 | } 99 | } 100 | } 101 | }); 102 | }; -------------------------------------------------------------------------------- /war/js/mirrorframe.js: -------------------------------------------------------------------------------- 1 | /* Demonstration of embedding CodeMirror in a bigger application. The 2 | * interface defined here is a mess of prompts and confirms, and 3 | * should probably not be used in a real project. 4 | */ 5 | 6 | function MirrorFrame(place, options) { 7 | this.home = document.createElement("DIV"); 8 | if (place.appendChild) 9 | place.appendChild(this.home); 10 | else 11 | place(this.home); 12 | 13 | var self = this; 14 | function makeButton(name, action) { 15 | var button = document.createElement("INPUT"); 16 | button.type = "button"; 17 | button.value = name; 18 | self.home.appendChild(button); 19 | button.onclick = function(){self[action].call(self);}; 20 | } 21 | 22 | makeButton("Search", "search"); 23 | makeButton("Replace", "replace"); 24 | makeButton("Current line", "line"); 25 | makeButton("Jump to line", "jump"); 26 | makeButton("Insert constructor", "macro"); 27 | makeButton("Indent all", "reindent"); 28 | 29 | this.mirror = new CodeMirror(this.home, options); 30 | } 31 | 32 | MirrorFrame.prototype = { 33 | search: function() { 34 | var text = prompt("Enter search term:", ""); 35 | if (!text) return; 36 | 37 | var first = true; 38 | do { 39 | var cursor = this.mirror.getSearchCursor(text, first); 40 | first = false; 41 | while (cursor.findNext()) { 42 | cursor.select(); 43 | if (!confirm("Search again?")) 44 | return; 45 | } 46 | } while (confirm("End of document reached. Start over?")); 47 | }, 48 | 49 | replace: function() { 50 | // This is a replace-all, but it is possible to implement a 51 | // prompting replace. 52 | var from = prompt("Enter search string:", ""), to; 53 | if (from) to = prompt("What should it be replaced with?", ""); 54 | if (to == null) return; 55 | 56 | var cursor = this.mirror.getSearchCursor(from, false); 57 | while (cursor.findNext()) 58 | cursor.replace(to); 59 | }, 60 | 61 | jump: function() { 62 | var line = prompt("Jump to line:", ""); 63 | if (line && !isNaN(Number(line))) 64 | this.mirror.jumpToLine(Number(line)); 65 | }, 66 | 67 | line: function() { 68 | alert("The cursor is currently at line " + this.mirror.currentLine()); 69 | this.mirror.focus(); 70 | }, 71 | 72 | macro: function() { 73 | var name = prompt("Name your constructor:", ""); 74 | if (name) 75 | this.mirror.replaceSelection("function " + name + "() {\n \n}\n\n" + name + ".prototype = {\n \n};\n"); 76 | }, 77 | 78 | reindent: function() { 79 | this.mirror.reindent(); 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /war/js/parsejavascript.js: -------------------------------------------------------------------------------- 1 | /* Parse function for JavaScript. Makes use of the tokenizer from 2 | * tokenizejavascript.js. Note that your parsers do not have to be 3 | * this complicated -- if you don't want to recognize local variables, 4 | * in many languages it is enough to just look for braces, semicolons, 5 | * parentheses, etc, and know when you are inside a string or comment. 6 | * 7 | * See manual.html for more info about the parser interface. 8 | */ 9 | 10 | var JSParser = Editor.Parser = (function() { 11 | // Token types that can be considered to be atoms. 12 | var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; 13 | // Constructor for the lexical context objects. 14 | function JSLexical(indented, column, type, align, prev, info) { 15 | // indentation at start of this line 16 | this.indented = indented; 17 | // column at which this scope was opened 18 | this.column = column; 19 | // type of scope ('vardef', 'stat' (statement), 'form' (special form), '[', '{', or '(') 20 | this.type = type; 21 | // '[', '{', or '(' blocks that have any text after their opening 22 | // character are said to be 'aligned' -- any lines below are 23 | // indented all the way to the opening character. 24 | if (align != null) 25 | this.align = align; 26 | // Parent scope, if any. 27 | this.prev = prev; 28 | this.info = info; 29 | } 30 | 31 | // My favourite JavaScript indentation rules. 32 | function indentJS(lexical) { 33 | return function(firstChars) { 34 | // Groovy: no indent at all, as the JavaScript indentation is broken with Groovy 35 | return 0; 36 | 37 | var firstChar = firstChars && firstChars.charAt(0), type = lexical.type; 38 | var closing = firstChar == type; 39 | if (type == "vardef") 40 | return lexical.indented + 4; 41 | else if (type == "form" && firstChar == "{") 42 | return lexical.indented; 43 | else if (type == "stat" || type == "form") 44 | return lexical.indented + indentUnit; 45 | else if (lexical.info == "switch" && !closing) 46 | return lexical.indented + (/^(?:case|default)\b/.test(firstChars) ? indentUnit : 2 * indentUnit); 47 | else if (lexical.align) 48 | return lexical.column - (closing ? 1 : 0); 49 | else 50 | return lexical.indented + (closing ? 0 : indentUnit); 51 | }; 52 | } 53 | 54 | // The parser-iterator-producing function itself. 55 | function parseJS(input, basecolumn) { 56 | // Wrap the input in a token stream 57 | var tokens = tokenizeJavaScript(input); 58 | // The parser state. cc is a stack of actions that have to be 59 | // performed to finish the current statement. For example we might 60 | // know that we still need to find a closing parenthesis and a 61 | // semicolon. Actions at the end of the stack go first. It is 62 | // initialized with an infinitely looping action that consumes 63 | // whole statements. 64 | var cc = [statements]; 65 | // Context contains information about the current local scope, the 66 | // variables defined in that, and the scopes above it. 67 | var context = null; 68 | // The lexical scope, used mostly for indentation. 69 | var lexical = new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false); 70 | // Current column, and the indentation at the start of the current 71 | // line. Used to create lexical scope objects. 72 | var column = 0; 73 | var indented = 0; 74 | // Variables which are used by the mark, cont, and pass functions 75 | // below to communicate with the driver loop in the 'next' 76 | // function. 77 | var consume, marked; 78 | 79 | // The iterator object. 80 | var parser = {next: next, copy: copy}; 81 | 82 | function next(){ 83 | // Start by performing any 'lexical' actions (adjusting the 84 | // lexical variable), or the operations below will be working 85 | // with the wrong lexical state. 86 | while(cc[cc.length - 1].lex) 87 | cc.pop()(); 88 | 89 | // Fetch a token. 90 | var token = tokens.next(); 91 | 92 | // Adjust column and indented. 93 | if (token.type == "whitespace" && column == 0) 94 | indented = token.value.length; 95 | column += token.value.length; 96 | if (token.content == "\n"){ 97 | indented = column = 0; 98 | // If the lexical scope's align property is still undefined at 99 | // the end of the line, it is an un-aligned scope. 100 | if (!("align" in lexical)) 101 | lexical.align = false; 102 | // Newline tokens get an indentation function associated with 103 | // them. 104 | token.indentation = indentJS(lexical); 105 | } 106 | // No more processing for meaningless tokens. 107 | if (token.type == "whitespace" || token.type == "comment") 108 | return token; 109 | // When a meaningful token is found and the lexical scope's 110 | // align is undefined, it is an aligned scope. 111 | if (!("align" in lexical)) 112 | lexical.align = true; 113 | 114 | // Execute actions until one 'consumes' the token and we can 115 | // return it. 116 | while(true) { 117 | consume = marked = false; 118 | // Take and execute the topmost action. 119 | cc.pop()(token.type, token.content); 120 | if (consume){ 121 | // Marked is used to change the style of the current token. 122 | if (marked) 123 | token.style = marked; 124 | // Here we differentiate between local and global variables. 125 | else if (token.type == "variable" && inScope(token.content)) 126 | token.style = "js-localvariable"; 127 | return token; 128 | } 129 | } 130 | } 131 | 132 | // This makes a copy of the parser state. It stores all the 133 | // stateful variables in a closure, and returns a function that 134 | // will restore them when called with a new input stream. Note 135 | // that the cc array has to be copied, because it is contantly 136 | // being modified. Lexical objects are not mutated, and context 137 | // objects are not mutated in a harmful way, so they can be shared 138 | // between runs of the parser. 139 | function copy(){ 140 | var _context = context, _lexical = lexical, _cc = cc.concat([]), _tokenState = tokens.state; 141 | 142 | return function copyParser(input){ 143 | context = _context; 144 | lexical = _lexical; 145 | cc = _cc.concat([]); // copies the array 146 | column = indented = 0; 147 | tokens = tokenizeJavaScript(input, _tokenState); 148 | return parser; 149 | }; 150 | } 151 | 152 | // Helper function for pushing a number of actions onto the cc 153 | // stack in reverse order. 154 | function push(fs){ 155 | for (var i = fs.length - 1; i >= 0; i--) 156 | cc.push(fs[i]); 157 | } 158 | // cont and pass are used by the action functions to add other 159 | // actions to the stack. cont will cause the current token to be 160 | // consumed, pass will leave it for the next action. 161 | function cont(){ 162 | push(arguments); 163 | consume = true; 164 | } 165 | function pass(){ 166 | push(arguments); 167 | consume = false; 168 | } 169 | // Used to change the style of the current token. 170 | function mark(style){ 171 | marked = style; 172 | } 173 | 174 | // Push a new scope. Will automatically link the current scope. 175 | function pushcontext(){ 176 | context = {prev: context, vars: {"this": true, "arguments": true}}; 177 | } 178 | // Pop off the current scope. 179 | function popcontext(){ 180 | context = context.prev; 181 | } 182 | // Register a variable in the current scope. 183 | function register(varname){ 184 | if (context){ 185 | mark("js-variabledef"); 186 | context.vars[varname] = true; 187 | } 188 | } 189 | // Check whether a variable is defined in the current scope. 190 | function inScope(varname){ 191 | var cursor = context; 192 | while (cursor) { 193 | if (cursor.vars[varname]) 194 | return true; 195 | cursor = cursor.prev; 196 | } 197 | return false; 198 | } 199 | 200 | // Push a new lexical context of the given type. 201 | function pushlex(type, info) { 202 | var result = function(){ 203 | lexical = new JSLexical(indented, column, type, null, lexical, info) 204 | }; 205 | result.lex = true; 206 | return result; 207 | } 208 | // Pop off the current lexical context. 209 | function poplex(){ 210 | lexical = lexical.prev; 211 | } 212 | poplex.lex = true; 213 | // The 'lex' flag on these actions is used by the 'next' function 214 | // to know they can (and have to) be ran before moving on to the 215 | // next token. 216 | 217 | // Creates an action that discards tokens until it finds one of 218 | // the given type. 219 | function expect(wanted){ 220 | return function expecting(type){ 221 | if (type == wanted) cont(); 222 | else cont(arguments.callee); 223 | }; 224 | } 225 | 226 | // Looks for a statement, and then calls itself. 227 | function statements(type){ 228 | return pass(statement, statements); 229 | } 230 | // Dispatches various types of statements based on the type of the 231 | // current token. 232 | function statement(type){ 233 | if (type == "var") cont(pushlex("vardef"), vardef1, expect(";"), poplex); 234 | else if (type == "keyword a") cont(pushlex("form"), expression, statement, poplex); 235 | else if (type == "keyword b") cont(pushlex("form"), statement, poplex); 236 | else if (type == "{") cont(pushlex("}"), block, poplex); 237 | else if (type == "function") cont(functiondef); 238 | else if (type == "for") cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex); 239 | else if (type == "variable") cont(pushlex("stat"), maybelabel); 240 | else if (type == "switch") cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); 241 | else if (type == "case") cont(expression, expect(":")); 242 | else if (type == "default") cont(expect(":")); 243 | else if (type == "catch") cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext); 244 | else pass(pushlex("stat"), expression, expect(";"), poplex); 245 | } 246 | // Dispatch expression types. 247 | function expression(type){ 248 | if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator); 249 | else if (type == "function") cont(functiondef); 250 | else if (type == "keyword c") cont(expression); 251 | else if (type == "(") cont(pushlex(")"), expression, expect(")"), poplex, maybeoperator); 252 | else if (type == "operator") cont(expression); 253 | else if (type == "[") cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); 254 | else if (type == "{") cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); 255 | } 256 | // Called for places where operators, function calls, or 257 | // subscripts are valid. Will skip on to the next action if none 258 | // is found. 259 | function maybeoperator(type){ 260 | if (type == "operator") cont(expression); 261 | else if (type == "(") cont(pushlex(")"), expression, commasep(expression, ")"), poplex, maybeoperator); 262 | else if (type == ".") cont(property, maybeoperator); 263 | else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); 264 | } 265 | // When a statement starts with a variable name, it might be a 266 | // label. If no colon follows, it's a regular statement. 267 | function maybelabel(type){ 268 | if (type == ":") cont(poplex, statement); 269 | else pass(maybeoperator, expect(";"), poplex); 270 | } 271 | // Property names need to have their style adjusted -- the 272 | // tokenizer thinks they are variables. 273 | function property(type){ 274 | if (type == "variable") {mark("js-property"); cont();} 275 | } 276 | // This parses a property and its value in an object literal. 277 | function objprop(type){ 278 | if (type == "variable") mark("js-property"); 279 | if (atomicTypes.hasOwnProperty(type)) cont(expect(":"), expression); 280 | } 281 | // Parses a comma-separated list of the things that are recognized 282 | // by the 'what' argument. 283 | function commasep(what, end){ 284 | function proceed(type) { 285 | if (type == ",") cont(what, proceed); 286 | else if (type == end) cont(); 287 | else cont(expect(end)); 288 | }; 289 | return function commaSeparated(type) { 290 | if (type == end) cont(); 291 | else pass(what, proceed); 292 | }; 293 | } 294 | // Look for statements until a closing brace is found. 295 | function block(type){ 296 | if (type == "}") cont(); 297 | else pass(statement, block); 298 | } 299 | // Variable definitions are split into two actions -- 1 looks for 300 | // a name or the end of the definition, 2 looks for an '=' sign or 301 | // a comma. 302 | function vardef1(type, value){ 303 | if (type == "variable"){register(value); cont(vardef2);} 304 | else cont(); 305 | } 306 | function vardef2(type){ 307 | if (type == "operator") cont(expression, vardef2); 308 | else if (type == ",") cont(vardef1); 309 | } 310 | // For loops. 311 | function forspec1(type){ 312 | if (type == "var") cont(vardef1, forspec2); 313 | else if (type == ";") pass(forspec2); 314 | else cont(expression, forspec2); 315 | } 316 | function forspec2(type){ 317 | if (type == ",") cont(forspec1); 318 | else if (type == ";") cont(forspec3); 319 | else cont(expression, expect(";"), forspec3); 320 | } 321 | function forspec3(type) { 322 | if (type == ")") pass(); 323 | else cont(expression); 324 | } 325 | // A function definition creates a new context, and the variables 326 | // in its argument list have to be added to this context. 327 | function functiondef(type, value){ 328 | if (type == "variable"){register(value); cont(functiondef);} 329 | else if (type == "(") cont(pushcontext, commasep(funarg, ")"), statement, popcontext); 330 | } 331 | function funarg(type, value){ 332 | if (type == "variable"){register(value); cont();} 333 | } 334 | 335 | return parser; 336 | } 337 | 338 | return {make: parseJS, electricChars: "{}:"}; 339 | })(); 340 | -------------------------------------------------------------------------------- /war/js/select.js: -------------------------------------------------------------------------------- 1 | /* Functionality for finding, storing, and restoring selections 2 | * 3 | * This does not provide a generic API, just the minimal functionality 4 | * required by the CodeMirror system. 5 | */ 6 | 7 | // Namespace object. 8 | var select = {}; 9 | 10 | (function() { 11 | select.ie_selection = document.selection && document.selection.createRangeCollection; 12 | 13 | // Find the 'top-level' (defined as 'a direct child of the node 14 | // passed as the top argument') node that the given node is 15 | // contained in. Return null if the given node is not inside the top 16 | // node. 17 | function topLevelNodeAt(node, top) { 18 | while (node && node.parentNode != top) 19 | node = node.parentNode; 20 | return node; 21 | } 22 | 23 | // Find the top-level node that contains the node before this one. 24 | function topLevelNodeBefore(node, top) { 25 | while (!node.previousSibling && node.parentNode != top) 26 | node = node.parentNode; 27 | return topLevelNodeAt(node.previousSibling, top); 28 | } 29 | 30 | // Used to prevent restoring a selection when we do not need to. 31 | var currentSelection = null; 32 | 33 | var fourSpaces = "\u00a0\u00a0\u00a0\u00a0"; 34 | 35 | select.snapshotChanged = function() { 36 | if (currentSelection) currentSelection.changed = true; 37 | }; 38 | 39 | // This is called by the code in editor.js whenever it is replacing 40 | // a text node. The function sees whether the given oldNode is part 41 | // of the current selection, and updates this selection if it is. 42 | // Because nodes are often only partially replaced, the length of 43 | // the part that gets replaced has to be taken into account -- the 44 | // selection might stay in the oldNode if the newNode is smaller 45 | // than the selection's offset. The offset argument is needed in 46 | // case the selection does move to the new object, and the given 47 | // length is not the whole length of the new node (part of it might 48 | // have been used to replace another node). 49 | select.snapshotReplaceNode = function(from, to, length, offset) { 50 | if (!currentSelection) return; 51 | currentSelection.changed = true; 52 | 53 | function replace(point) { 54 | if (from == point.node) { 55 | if (length && point.offset > length) { 56 | point.offset -= length; 57 | } 58 | else { 59 | point.node = to; 60 | point.offset += (offset || 0); 61 | } 62 | } 63 | } 64 | replace(currentSelection.start); 65 | replace(currentSelection.end); 66 | }; 67 | 68 | select.snapshotMove = function(from, to, distance, relative, ifAtStart) { 69 | if (!currentSelection) return; 70 | currentSelection.changed = true; 71 | 72 | function move(point) { 73 | if (from == point.node && (!ifAtStart || point.offset == 0)) { 74 | point.node = to; 75 | if (relative) point.offset = Math.max(0, point.offset + distance); 76 | else point.offset = distance; 77 | } 78 | } 79 | move(currentSelection.start); 80 | move(currentSelection.end); 81 | }; 82 | 83 | // Most functions are defined in two ways, one for the IE selection 84 | // model, one for the W3C one. 85 | if (select.ie_selection) { 86 | function selectionNode(win, start) { 87 | var range = win.document.selection.createRange(); 88 | range.collapse(start); 89 | 90 | function nodeAfter(node) { 91 | var found = null; 92 | while (!found && node) { 93 | found = node.nextSibling; 94 | node = node.parentNode; 95 | } 96 | return nodeAtStartOf(found); 97 | } 98 | 99 | function nodeAtStartOf(node) { 100 | while (node && node.firstChild) node = node.firstChild; 101 | return {node: node, offset: 0}; 102 | } 103 | 104 | var containing = range.parentElement(); 105 | if (!isAncestor(win.document.body, containing)) return null; 106 | if (!containing.firstChild) return nodeAtStartOf(containing); 107 | 108 | var working = range.duplicate(); 109 | working.moveToElementText(containing); 110 | working.collapse(true); 111 | for (var cur = containing.firstChild; cur; cur = cur.nextSibling) { 112 | if (cur.nodeType == 3) { 113 | var size = cur.nodeValue.length; 114 | working.move("character", size); 115 | } 116 | else { 117 | working.moveToElementText(cur); 118 | working.collapse(false); 119 | } 120 | 121 | var dir = range.compareEndPoints("StartToStart", working); 122 | if (dir == 0) return nodeAfter(cur); 123 | if (dir == 1) continue; 124 | if (cur.nodeType != 3) return nodeAtStartOf(cur); 125 | 126 | working.setEndPoint("StartToEnd", range); 127 | return {node: cur, offset: size - working.text.length}; 128 | } 129 | return nodeAfter(containing); 130 | } 131 | 132 | select.markSelection = function(win) { 133 | currentSelection = null; 134 | var sel = win.document.selection; 135 | if (!sel) return; 136 | var start = selectionNode(win, true), 137 | end = sel.createRange().text == "" ? start : selectionNode(win, false); 138 | if (!start || !end) return; 139 | currentSelection = {start: start, end: end, window: win, changed: false}; 140 | }; 141 | 142 | select.selectMarked = function() { 143 | if (!currentSelection || !currentSelection.changed) return; 144 | 145 | function makeRange(point) { 146 | var range = currentSelection.window.document.body.createTextRange(); 147 | var node = point.node; 148 | if (!node) { 149 | range.moveToElementText(currentSelection.window.document.body); 150 | range.collapse(false); 151 | } 152 | else if (node.nodeType == 3) { 153 | range.moveToElementText(node.parentNode); 154 | var offset = point.offset; 155 | while (node.previousSibling) { 156 | node = node.previousSibling; 157 | offset += (node.innerText || "").length; 158 | } 159 | range.move("character", offset); 160 | } 161 | else { 162 | range.moveToElementText(node); 163 | range.collapse(true); 164 | } 165 | return range; 166 | } 167 | 168 | var start = makeRange(currentSelection.start), end = makeRange(currentSelection.end); 169 | start.setEndPoint("StartToEnd", end); 170 | start.select(); 171 | }; 172 | 173 | // Get the top-level node that one end of the cursor is inside or 174 | // after. Note that this returns false for 'no cursor', and null 175 | // for 'start of document'. 176 | select.selectionTopNode = function(container, start) { 177 | var selection = container.ownerDocument.selection; 178 | if (!selection) return false; 179 | 180 | var range = selection.createRange(); 181 | range.collapse(start); 182 | var around = range.parentElement(); 183 | if (around && isAncestor(container, around)) { 184 | // Only use this node if the selection is not at its start. 185 | var range2 = range.duplicate(); 186 | range2.moveToElementText(around); 187 | if (range.compareEndPoints("StartToStart", range2) == -1) 188 | return topLevelNodeAt(around, container); 189 | } 190 | // Fall-back hack 191 | try {range.pasteHTML("");} 192 | catch (e) {return false;} 193 | 194 | var temp = container.ownerDocument.getElementById("xxx-temp-xxx"); 195 | if (temp) { 196 | var result = topLevelNodeBefore(temp, container); 197 | removeElement(temp); 198 | return result; 199 | } 200 | return false; 201 | }; 202 | 203 | // Place the cursor after this.start. This is only useful when 204 | // manually moving the cursor instead of restoring it to its old 205 | // position. 206 | select.focusAfterNode = function(node, container) { 207 | var range = container.ownerDocument.body.createTextRange(); 208 | range.moveToElementText(node || container); 209 | range.collapse(!node); 210 | range.select(); 211 | }; 212 | 213 | select.somethingSelected = function(win) { 214 | var sel = win.document.selection; 215 | return sel && (sel.createRange().text != ""); 216 | }; 217 | 218 | function insertAtCursor(window, html) { 219 | var selection = window.document.selection; 220 | if (selection) { 221 | var range = selection.createRange(); 222 | range.pasteHTML(html); 223 | range.collapse(false); 224 | range.select(); 225 | } 226 | } 227 | 228 | // Used to normalize the effect of the enter key, since browsers 229 | // do widely different things when pressing enter in designMode. 230 | select.insertNewlineAtCursor = function(window) { 231 | insertAtCursor(window, "
"); 232 | }; 233 | 234 | select.insertTabAtCursor = function(window) { 235 | insertAtCursor(window, fourSpaces); 236 | }; 237 | 238 | // Get the BR node at the start of the line on which the cursor 239 | // currently is, and the offset into the line. Returns null as 240 | // node if cursor is on first line. 241 | select.cursorPos = function(container, start) { 242 | var selection = container.ownerDocument.selection; 243 | if (!selection) return null; 244 | 245 | var topNode = select.selectionTopNode(container, start); 246 | while (topNode && topNode.nodeName != "BR") 247 | topNode = topNode.previousSibling; 248 | 249 | var range = selection.createRange(), range2 = range.duplicate(); 250 | range.collapse(start); 251 | if (topNode) { 252 | range2.moveToElementText(topNode); 253 | range2.collapse(false); 254 | } 255 | else { 256 | // When nothing is selected, we can get all kinds of funky errors here. 257 | try { range2.moveToElementText(container); } 258 | catch (e) { return null; } 259 | range2.collapse(true); 260 | } 261 | range.setEndPoint("StartToStart", range2); 262 | 263 | return {node: topNode, offset: range.text.length}; 264 | }; 265 | 266 | select.setCursorPos = function(container, from, to) { 267 | function rangeAt(pos) { 268 | var range = container.ownerDocument.body.createTextRange(); 269 | if (!pos.node) { 270 | range.moveToElementText(container); 271 | range.collapse(true); 272 | } 273 | else { 274 | range.moveToElementText(pos.node); 275 | range.collapse(false); 276 | } 277 | range.move("character", pos.offset); 278 | return range; 279 | } 280 | 281 | var range = rangeAt(from); 282 | if (to && to != from) 283 | range.setEndPoint("EndToEnd", rangeAt(to)); 284 | range.select(); 285 | } 286 | 287 | // Make sure the cursor is visible. 288 | select.scrollToCursor = function(container) { 289 | var selection = container.ownerDocument.selection; 290 | if (!selection) return null; 291 | selection.createRange().scrollIntoView(); 292 | }; 293 | 294 | select.scrollToNode = function(node) { 295 | if (!node) return; 296 | node.scrollIntoView(); 297 | }; 298 | 299 | // Some hacks for storing and re-storing the selection when the editor loses and regains focus. 300 | select.selectionCoords = function (win) { 301 | var selection = win.document.selection; 302 | if (!selection) return null; 303 | var start = selection.createRange(), end = start.duplicate(); 304 | start.collapse(true); 305 | end.collapse(false); 306 | 307 | var body = win.document.body; 308 | return {start: {x: start.boundingLeft + body.scrollLeft - 1, 309 | y: start.boundingTop + body.scrollTop}, 310 | end: {x: end.boundingLeft + body.scrollLeft - 1, 311 | y: end.boundingTop + body.scrollTop}}; 312 | }; 313 | 314 | // Restore a stored selection. 315 | select.selectCoords = function(win, coords) { 316 | if (!coords) return; 317 | 318 | var range1 = win.document.body.createTextRange(), range2 = range1.duplicate(); 319 | // This can fail for various hard-to-handle reasons. 320 | try { 321 | range1.moveToPoint(coords.start.x, coords.start.y); 322 | range2.moveToPoint(coords.end.x, coords.end.y); 323 | range1.setEndPoint("EndToStart", range2); 324 | range1.select(); 325 | } catch(e) {alert(e.message);} 326 | }; 327 | } 328 | // W3C model 329 | else { 330 | // Store start and end nodes, and offsets within these, and refer 331 | // back to the selection object from those nodes, so that this 332 | // object can be updated when the nodes are replaced before the 333 | // selection is restored. 334 | select.markSelection = function (win) { 335 | var selection = win.getSelection(); 336 | if (!selection || selection.rangeCount == 0) 337 | return (currentSelection = null); 338 | var range = selection.getRangeAt(0); 339 | 340 | currentSelection = { 341 | start: {node: range.startContainer, offset: range.startOffset}, 342 | end: {node: range.endContainer, offset: range.endOffset}, 343 | window: win, 344 | changed: false 345 | }; 346 | 347 | // We want the nodes right at the cursor, not one of their 348 | // ancestors with a suitable offset. This goes down the DOM tree 349 | // until a 'leaf' is reached (or is it *up* the DOM tree?). 350 | function normalize(point){ 351 | while (point.node.nodeType != 3 && point.node.nodeName != "BR") { 352 | var newNode = point.node.childNodes[point.offset] || point.node.nextSibling; 353 | point.offset = 0; 354 | while (!newNode && point.node.parentNode) { 355 | point.node = point.node.parentNode; 356 | newNode = point.node.nextSibling; 357 | } 358 | point.node = newNode; 359 | if (!newNode) 360 | break; 361 | } 362 | } 363 | 364 | normalize(currentSelection.start); 365 | normalize(currentSelection.end); 366 | }; 367 | 368 | select.selectMarked = function () { 369 | if (!currentSelection || !currentSelection.changed) return; 370 | var win = currentSelection.window, range = win.document.createRange(); 371 | 372 | function setPoint(point, which) { 373 | if (point.node) { 374 | // Some magic to generalize the setting of the start and end 375 | // of a range. 376 | if (point.offset == 0) 377 | range["set" + which + "Before"](point.node); 378 | else 379 | range["set" + which](point.node, point.offset); 380 | } 381 | else { 382 | range.setStartAfter(win.document.body.lastChild || win.document.body); 383 | } 384 | } 385 | 386 | setPoint(currentSelection.end, "End"); 387 | setPoint(currentSelection.start, "Start"); 388 | selectRange(range, win); 389 | }; 390 | 391 | // Helper for selecting a range object. 392 | function selectRange(range, window) { 393 | var selection = window.getSelection(); 394 | selection.removeAllRanges(); 395 | selection.addRange(range); 396 | }; 397 | function selectionRange(window) { 398 | var selection = window.getSelection(); 399 | if (!selection || selection.rangeCount == 0) 400 | return false; 401 | else 402 | return selection.getRangeAt(0); 403 | } 404 | 405 | // Finding the top-level node at the cursor in the W3C is, as you 406 | // can see, quite an involved process. 407 | select.selectionTopNode = function(container, start) { 408 | var range = selectionRange(container.ownerDocument.defaultView); 409 | if (!range) return false; 410 | 411 | var node = start ? range.startContainer : range.endContainer; 412 | var offset = start ? range.startOffset : range.endOffset; 413 | // Work around (yet another) bug in Opera's selection model. 414 | if (window.opera && !start && range.endContainer == container && range.endOffset == range.startOffset + 1 && 415 | container.childNodes[range.startOffset] && container.childNodes[range.startOffset].nodeName == "BR") 416 | offset--; 417 | 418 | // For text nodes, we look at the node itself if the cursor is 419 | // inside, or at the node before it if the cursor is at the 420 | // start. 421 | if (node.nodeType == 3){ 422 | if (offset > 0) 423 | return topLevelNodeAt(node, container); 424 | else 425 | return topLevelNodeBefore(node, container); 426 | } 427 | // Occasionally, browsers will return the HTML node as 428 | // selection. If the offset is 0, we take the start of the frame 429 | // ('after null'), otherwise, we take the last node. 430 | else if (node.nodeName == "HTML") { 431 | return (offset == 1 ? null : container.lastChild); 432 | } 433 | // If the given node is our 'container', we just look up the 434 | // correct node by using the offset. 435 | else if (node == container) { 436 | return (offset == 0) ? null : node.childNodes[offset - 1]; 437 | } 438 | // In any other case, we have a regular node. If the cursor is 439 | // at the end of the node, we use the node itself, if it is at 440 | // the start, we use the node before it, and in any other 441 | // case, we look up the child before the cursor and use that. 442 | else { 443 | if (offset == node.childNodes.length) 444 | return topLevelNodeAt(node, container); 445 | else if (offset == 0) 446 | return topLevelNodeBefore(node, container); 447 | else 448 | return topLevelNodeAt(node.childNodes[offset - 1], container); 449 | } 450 | }; 451 | 452 | select.focusAfterNode = function(node, container) { 453 | var win = container.ownerDocument.defaultView, 454 | range = win.document.createRange(); 455 | range.setStartBefore(container.firstChild || container); 456 | // In Opera, setting the end of a range at the end of a line 457 | // (before a BR) will cause the cursor to appear on the next 458 | // line, so we set the end inside of the start node when 459 | // possible. 460 | if (node && !node.firstChild) 461 | range.setEndAfter(node); 462 | else if (node) 463 | range.setEnd(node, node.childNodes.length); 464 | else 465 | range.setEndBefore(container.firstChild || container); 466 | range.collapse(false); 467 | selectRange(range, win); 468 | }; 469 | 470 | select.somethingSelected = function(win) { 471 | var range = selectionRange(win); 472 | return range && !range.collapsed; 473 | }; 474 | 475 | function insertNodeAtCursor(window, node) { 476 | var range = selectionRange(window); 477 | if (!range) return; 478 | 479 | range.deleteContents(); 480 | range.insertNode(node); 481 | webkitLastLineHack(window.document.body); 482 | range = window.document.createRange(); 483 | range.selectNode(node); 484 | range.collapse(false); 485 | selectRange(range, window); 486 | } 487 | 488 | select.insertNewlineAtCursor = function(window) { 489 | insertNodeAtCursor(window, window.document.createElement("BR")); 490 | }; 491 | 492 | select.insertTabAtCursor = function(window) { 493 | insertNodeAtCursor(window, window.document.createTextNode(fourSpaces)); 494 | }; 495 | 496 | select.cursorPos = function(container, start) { 497 | var range = selectionRange(window); 498 | if (!range) return; 499 | 500 | var topNode = select.selectionTopNode(container, start); 501 | while (topNode && topNode.nodeName != "BR") 502 | topNode = topNode.previousSibling; 503 | 504 | range = range.cloneRange(); 505 | range.collapse(start); 506 | if (topNode) 507 | range.setStartAfter(topNode); 508 | else 509 | range.setStartBefore(container); 510 | return {node: topNode, offset: range.toString().length}; 511 | }; 512 | 513 | select.setCursorPos = function(container, from, to) { 514 | var win = container.ownerDocument.defaultView, 515 | range = win.document.createRange(); 516 | 517 | function setPoint(node, offset, side) { 518 | if (!node) 519 | node = container.firstChild; 520 | else 521 | node = node.nextSibling; 522 | 523 | if (!node) 524 | return; 525 | 526 | if (offset == 0) { 527 | range["set" + side + "Before"](node); 528 | return true; 529 | } 530 | 531 | var backlog = [] 532 | function decompose(node) { 533 | if (node.nodeType == 3) 534 | backlog.push(node); 535 | else 536 | forEach(node.childNodes, decompose); 537 | } 538 | while (true) { 539 | while (node && !backlog.length) { 540 | decompose(node); 541 | node = node.nextSibling; 542 | } 543 | var cur = backlog.shift(); 544 | if (!cur) return false; 545 | 546 | var length = cur.nodeValue.length; 547 | if (length >= offset) { 548 | range["set" + side](cur, offset); 549 | return true; 550 | } 551 | offset -= length; 552 | } 553 | } 554 | 555 | to = to || from; 556 | if (setPoint(to.node, to.offset, "End") && setPoint(from.node, from.offset, "Start")) 557 | selectRange(range, win); 558 | }; 559 | 560 | select.scrollToNode = function(element) { 561 | if (!element) return; 562 | var doc = element.ownerDocument, body = doc.body, win = doc.defaultView, html = doc.documentElement; 563 | 564 | // In Opera, BR elements *always* have a scrollTop property of zero. Go Opera. 565 | while (element && !element.offsetTop) 566 | element = element.previousSibling; 567 | 568 | var y = 0, pos = element; 569 | while (pos && pos.offsetParent) { 570 | y += pos.offsetTop; 571 | pos = pos.offsetParent; 572 | } 573 | 574 | var screen_y = y - (body.scrollTop || html.scrollTop || 0); 575 | if (screen_y < 0 || screen_y > win.innerHeight - 30) 576 | win.scrollTo(body.scrollLeft || html.scrollLeft || 0, y); 577 | }; 578 | 579 | select.scrollToCursor = function(container) { 580 | select.scrollToNode(select.selectionTopNode(container, true) || container.firstChild); 581 | }; 582 | } 583 | })(); 584 | -------------------------------------------------------------------------------- /war/js/shBrushGroovy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | SyntaxHighlighter.brushes.Groovy = function() 31 | { 32 | // Contributed by Andres Almiray 33 | // http://jroller.com/aalmiray/entry/nice_source_code_syntax_highlighter 34 | 35 | var keywords = 'as assert break case catch class continue def default do else extends finally for ' + 36 | 'if in implements import instanceof interface new package property return switch ' + 37 | 'throw throws trait try while public protected private static'; 38 | var types = 'void boolean byte char short int long float double'; 39 | var constants = 'null'; 40 | var methods = 'allProperties count get size '+ 41 | 'collect each eachProperty eachPropertyName eachWithIndex find findAll ' + 42 | 'findIndexOf grep inject max min reverseEach sort ' + 43 | 'asImmutable asSynchronized flatten intersect join pop reverse subMap toList ' + 44 | 'padRight padLeft contains eachMatch toCharacter toLong toUrl tokenize ' + 45 | 'eachFile eachFileRecurse eachByte eachLine readBytes readLine getText ' + 46 | 'splitEachLine withReader append encodeBase64 decodeBase64 filterLine ' + 47 | 'transformChar transformLine withOutputStream withPrintWriter withStream ' + 48 | 'withStreams withWriter withWriterAppend write writeLine '+ 49 | 'dump inspect invokeMethod print println step times upto use waitForOrKill '+ 50 | 'getText'; 51 | 52 | this.regexList = [ 53 | { regex: SyntaxHighlighter.regexLib.singleLineCComments, css: 'comments' }, // one line comments 54 | { regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments 55 | { regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // strings 56 | { regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // strings 57 | { regex: /""".*"""/g, css: 'string' }, // GStrings 58 | { regex: new RegExp('\\b([\\d]+(\\.[\\d]+)?|0x[a-f0-9]+)\\b', 'gi'), css: 'value' }, // numbers 59 | { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' }, // goovy keyword 60 | { regex: new RegExp(this.getKeywords(types), 'gm'), css: 'color1' }, // goovy/java type 61 | { regex: new RegExp(this.getKeywords(constants), 'gm'), css: 'constants' }, // constants 62 | { regex: new RegExp(this.getKeywords(methods), 'gm'), css: 'functions' } // methods 63 | ]; 64 | 65 | this.forHtmlScript(SyntaxHighlighter.regexLib.aspScriptTags); 66 | } 67 | 68 | SyntaxHighlighter.brushes.Groovy.prototype = new SyntaxHighlighter.Highlighter(); 69 | SyntaxHighlighter.brushes.Groovy.aliases = ['groovy']; 70 | -------------------------------------------------------------------------------- /war/js/shBrushXml.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | SyntaxHighlighter.brushes.Xml = function() 31 | { 32 | function process(match, regexInfo) 33 | { 34 | var constructor = SyntaxHighlighter.Match, 35 | code = match[0], 36 | tag = new XRegExp('(<|<)[\\s\\/\\?]*(?[:\\w-\\.]+)', 'xg').exec(code), 37 | result = [] 38 | ; 39 | 40 | if (match.attributes != null) 41 | { 42 | var attributes, 43 | regex = new XRegExp('(? [\\w:\\-\\.]+)' + 44 | '\\s*=\\s*' + 45 | '(? ".*?"|\'.*?\'|\\w+)', 46 | 'xg'); 47 | 48 | while ((attributes = regex.exec(code)) != null) 49 | { 50 | result.push(new constructor(attributes.name, match.index + attributes.index, 'color1')); 51 | result.push(new constructor(attributes.value, match.index + attributes.index + attributes[0].indexOf(attributes.value), 'string')); 52 | } 53 | } 54 | 55 | if (tag != null) 56 | result.push( 57 | new constructor(tag.name, match.index + tag[0].indexOf(tag.name), 'keyword') 58 | ); 59 | 60 | return result; 61 | } 62 | 63 | this.regexList = [ 64 | { regex: new XRegExp('(\\<|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\>|>)', 'gm'), css: 'color2' }, // 65 | { regex: new XRegExp('(\\<|<)!--\\s*.*?\\s*--(\\>|>)', 'gm'), css: 'comments' }, // 66 | { regex: new XRegExp('(<|<)[\\s\\/\\?]*(\\w+)(?.*?)[\\s\\/\\?]*(>|>)', 'sg'), func: process } 67 | ]; 68 | }; 69 | 70 | SyntaxHighlighter.brushes.Xml.prototype = new SyntaxHighlighter.Highlighter(); 71 | SyntaxHighlighter.brushes.Xml.aliases = ['xml', 'xhtml', 'xslt', 'html', 'xhtml']; 72 | -------------------------------------------------------------------------------- /war/js/shCore.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('f(!1q.2E){l 2E=h(){l p={77:{"1e-1f":"","79-2P":1,"1I":u,"6V-70":U,"1C-2A":4,"5f":N,"4Z":U,"1z":U,"56":N,"7G-7F":U,"6Z":N,"4S-1m":U},M:{52:u,5P:16,5S:16,8k:N,8l:N,83:"4R",1k:{3Y:"97 1c",41:"9b 1c",5U:"9O 93 7A",6t:"9B I 9E 23 8w 7A 8o",34:"34",6P:"?",1v:"2E\\n\\n",6F:"8p\'t 8I 87 D: ",7X:"8V 8v\'t bD D 2u-2c bf: ",6H:"<2u ay=\\"2g://6D.6v.6m/as/8r\\"><6l><8T 2g-92=\\"8P-8L\\" 5B=\\"2d/2u; 8E=8s-8\\" /><3B>8C 2E<2L 1n=\\"3N-8x:8Z,9y,9H,9I-9Q;9S-4v:#9K;4v:#9J;3N-2A:9L;2d-6k:6i;\\">2E6f 2.0.9j (9n 9s 6n)2g://6j.4U96 I 94 95.9f 9e-6n 9c 9t."},6T:N},1t:{4D:u,3k:u,3P:u,5K:{}},2B:{},85:{9u:/\\/\\*[\\s\\S]*?\\*\\//4k,9N:/\\/\\/.*$/4k,9M:/#.*$/4k,9P:/"(?:\\.|(\\\\\\")|[^\\""\\n])*"/g,9T:/\'(?:\\.|(\\\\\\\')|[^\\\'\'\\n])*\'/g,9R:/"(?:\\.|(\\\\\\")|[^\\""])*"/g,9z:/\'(?:\\.|(\\\\\\\')|[^\\\'\'])*\'/g,3p:/\\w+:\\/\\/[\\w-.\\/?%&=]*/g,9x:{E:/(&1F;|<)\\?=?/g,13:/\\?(&2o;|>)/g},9v:{E:/(&1F;|<)%=?/g,13:/%(&2o;|>)/g},9w:{E:/(&1F;|<)\\s*2c.*?(&2o;|>)/4x,13:/(&1F;|<)\\/\\s*2c\\s*(&2o;|>)/4x}},1z:{12:h(3s){l 3y=L.1s("3j"),4o=p.1z.65;3y.J="1z";D(l 2Y 23 4o){l 6o=4o[2Y],4J=T 6o(3s),28=4J.12();3s.5I[2Y]=4J;f(28==u){1H}f(9G(28)=="9F"){28=p.1z.6s(28,3s.1g,2Y)}28.J+="5k "+2Y;3y.1G(28)}q 3y},6s:h(4A,6r,4h){l a=L.1s("a"),4Q=a.1n,4P=p.M,4F=4P.5P,48=4P.5S;a.2q="#"+4h;a.3B=4A;a.5M=6r;a.6q=4h;a.1x=4A;f(55(4F)==N){4Q.1S=4F+"5x"}f(55(48)==N){4Q.2t=48+"5x"}a.8t=h(e){8D{p.1z.6p(c,e||1q.6w,c.5M,c.6q)}8m(e){p.B.1v(e.6u)}q N};q a},6p:h(69,68,6h,6g,67){l 3U=p.1t.5K[6h],3X;f(3U==u||(3X=3U.5I[6g])==u){q u}q 3X.2h(69,68,67)},65:{3Y:h(4b){c.12=h(){f(4b.V("56")!=U){q}q p.M.1k.3Y};c.2h=h(42,8X,91){l A=4b.A;42.7T.5a(42);A.J=A.J.C("51","")}},41:h(66){c.12=h(){q p.M.1k.41};c.2h=h(8R,8Q,8J){l 3Q=p.B.3G(66.4W).C(/"+3Q+"");2i.L.5O()}},5U:h(5e){l 3S,8F,5L=5e.1g;c.12=h(){l 2S=p.M;f(2S.52==u){q u}h 1A(5E){l 5s="";D(l 5y 23 5E){5s+="<8S 1f=\'"+5y+"\' 1U=\'"+5E[5y]+"\'/>"}q 5s};h 2v(5t){l 5Q="";D(l 5w 23 5t){5Q+=" "+5w+"=\'"+5t[5w]+"\'"}q 5Q};l 5m={1S:2S.5P,2t:2S.5S,1g:5L+"b8",6N:"b7/x-6a-6b",3B:p.M.1k.5U},5h={b6:"b4",b5:"b9",ba:"5M="+5L,bd:"N"},5g=2S.52,3H;f(/bb/i.1R(5Z.5W)){3H="<6e"+2v({bc:"b3:b2-aU-aT-aS-aQ",aR:"2g://aW.b1.4U/b0/6a/aX/6b/bg.bh#6f=9,0,0,0"})+2v(5m)+">"+1A(5h)+1A({bB:5g})+""}F{3H=""}3S=L.1s("A");3S.1x=3H;q 3S};c.2h=h(bH,bG,5T){l 6d=5T.bE;6z(6d){2N"7u":l 53=p.B.2D(p.B.3G(5e.4W).C(/&1F;/g,"<").C(/&2o;/g,">").C(/&bw;/g,"&"));f(1q.6c){1q.6c.bm("2d",53)}F{q p.B.2D(53)}2N"bk":p.B.1v(p.M.1k.6t);2m;2N"bj":p.B.1v(5T.6u);2m}}},bo:h(58){c.12=h(){q p.M.1k.34};c.2h=h(bu,bt,bs){l 1W=L.1s("bp"),1O=u;f(p.1t.3P!=u){L.2L.5a(p.1t.3P)}p.1t.3P=1W;1W.1n.bq="aP:aO;1S:6L;2t:6L;E:-6K;43:-6K;";L.2L.1G(1W);1O=1W.5c.L;6J(1O,1q.L);1O.3h(""+58.A.1x+"");1O.5O();1W.5c.4d();1W.5c.34();h 6J(6M,64){l 2F=64.82("4Y");D(l i=0;i<2F.v;i++){f(2F[i].6R.ac()=="6Q"&&/aa\\.19$/.1R(2F[i].2q)){6M.3h("<4Y 6N=\\"2d/19\\" 6R=\\"6Q\\" 2q=\\""+2F[i].2q+"\\">")}}}}},af:h(ag){c.12=h(){q p.M.1k.6P};c.2h=h(aj,ah){l 2i=p.B.54("","57",ai,a9,"6O=0"),1O=2i.L;1O.3h(p.M.1k.6H);1O.5O();2i.4d()}}}},B:{5H:h(6G){q 6G+3J.9Y(3J.9W()*9X).2r()},5o:h(5R,5G){l 3m={},1T;D(1T 23 5R){3m[1T]=5R[1T]}D(1T 23 5G){3m[1T]=5G[1T]}q 3m},8d:h(5z){6z(5z){2N"U":q U;2N"N":q N}q 5z},54:h(3p,6x,44,4c,2J){l x=(6y.1S-44)/2,y=(6y.2t-4c)/2;2J+=", E="+x+", 43="+y+", 1S="+44+", 2t="+4c;2J=2J.C(/^,/,"");l 49=1q.a5(3p,6x,2J);49.4d();q 49},7Q:h(1M,25,24){f(1M.6A){1M["e"+25+24]=24;1M[25+24]=h(){1M["e"+25+24](1q.6w)};1M.6A("an"+25,1M[25+24])}F{1M.aG(25,24,N)}},1v:h(z){1v(p.M.1k.1v+z)},4l:h(4M,6B){l 2k=p.1t.4D,3b=u;f(2k==u){2k={};D(l 4G 23 p.2B){l 37=p.2B[4G].aF;f(37==u){1H}D(l i=0;i<37.v;i++){2k[37[i]]=4G}}p.1t.4D=2k}3b=p.2B[2k[4M]];f(3b==u&&6B!=N){p.B.1v(p.M.1k.6F+4M)}q 3b},4n:h(z,6E){l 2U=z.1P("\\n");D(l i=0;i<2U.v;i++){2U[i]=6E(2U[i])}q 2U.5u("\\n")},74:h(){l A=L.1s("A"),3e=L.1s("A"),6C=10,i=1;29(i<=aD){f(i%6C===0){A.1x+=i;i+=(i+"").v}F{A.1x+="&aI;";i++}}3e.J="5f 2P";3e.1G(A);q 3e},6W:h(z){q z.C(/^[ ]*[\\n]+|[\\n]*[ ]*$/g,"")},84:h(z){l 3d,4u={},4p=T R("^\\\\[(?<4q>(.*?))\\\\]$"),6S=T R("(?<1f>[\\\\w-]+)"+"\\\\s*:\\\\s*"+"(?<1U>"+"[\\\\w-%#]+|"+"\\\\[.*?\\\\]|"+"\\".*?\\"|"+"\'.*?\'"+")\\\\s*;?","g");29((3d=6S.Q(z))!=u){l 2f=3d.1U.C(/^[\'"]|[\'"]$/g,"");f(2f!=u&&4p.1R(2f)){l m=4p.Q(2f);2f=m.4q.v>0?m.4q.1P(/\\s*,\\s*/):[]}4u[3d.1f]=2f}q 4u},7g:h(z,19){f(z==u||z.v==0||z=="\\n"){q z}z=z.C(/"+2s+""})}q z},7a:h(61,62){l 2I=61.2r();29(2I.v<62){2I="0"+2I}q 2I},5p:h(){l 3x=L.1s("A"),35,3r=0,5i=L.2L,1g=p.B.5H("5p"),2Q="",4H="";3x.1x=2Q+"7P\\">"+2Q+"1m\\">"+2Q+"2P\\">"+2Q+"5B"+"\\"><1V 1e=\\"7i\\"><1V 1g=\\""+1g+"\\">&1X;"+4H+4H+2V+2V+2V+2V;5i.1G(3x);35=L.ar(1g);f(/aq/i.1R(5Z.5W)){l 63=1q.ao(35,u);3r=7b(63.ap("1S"))}F{3r=35.at}5i.5a(3x);q 3r},76:h(5Y,60){l 1C="";D(l i=0;i<60;i++){1C+=" "}q 5Y.C(/\\t/g,1C)},71:h(2C,4w){l az=2C.1P("\\n"),1C="\\t",40="";D(l i=0;i<50;i++){40+=" "}h 6I(3z,18,5X){q 3z.1Q(0,18)+40.1Q(0,5X)+3z.1Q(18+1,3z.v)};2C=p.B.4n(2C,h(2a){f(2a.1i(1C)==-1){q 2a}l 18=0;29((18=2a.1i(1C))!=-1){l 7r=4w-18%4w;2a=6I(2a,18,7r)}q 2a});q 2C},3G:h(z){l br=/|&1F;br\\s*\\/?&2o;/4x;f(p.M.8k==U){z=z.C(br,"\\n")}f(p.M.8l==U){z=z.C(br,"")}q z},33:h(z){q z.C(/\\s*$/g,"").C(/^\\s*/,"")},2D:h(z){l 21=p.B.3G(z).1P("\\n"),av=T 5V(),8a=/^\\s*/,1Z=ax;D(l i=0;i<21.v&&1Z>0;i++){l 3V=21[i];f(p.B.33(3V).v==0){1H}l 3W=8a.Q(3V);f(3W==u){q z}1Z=3J.1Z(3W[0].v,1Z)}f(1Z>0){D(l i=0;i<21.v;i++){21[i]=21[i].1Q(1Z)}}q 21.5u("\\n")},7d:h(2K,2O){f(2K.G<2O.G){q-1}F{f(2K.G>2O.G){q 1}F{f(2K.v<2O.v){q-1}F{f(2K.v>2O.v){q 1}}}}q 0},30:h(7S,2H){h 7R(4V,7Y){q[T p.4i(4V[0],4V.G,7Y.19)]};l au=0,5N=u,39=[],7Z=2H.4L?2H.4L:7R;29((5N=2H.3q.Q(7S))!=u){39=39.31(7Z(5N,2H))}q 39},7C:h(86){q 86.C(p.85.3p,h(m){q""+m+""})}},1I:h(88,4T){h 81(5j){l 59=[];D(l i=0;i<5j.v;i++){59.K(5j[i])}q 59};l 3g=4T?[4T]:81(L.82(p.M.83)),80="1x",2e=u;f(3g.v===0){q}D(l i=0;i<3g.v;i++){l 2G=3g[i],2l=p.B.84(2G.J),32;2l=p.B.5o(88,2l);32=2l["87"];f(32==u){1H}f(2l["2u-2c"]=="U"){2e=T p.4B(32)}F{l 4O=p.B.4l(32);f(4O){2e=T 4O()}F{1H}}2e.1I(2G[80],2l);l 2p=2e.A;f(p.M.6T){2p=L.1s("aA");2p.1U=2e.A.1x;2p.1n.1S="aB";2p.1n.2t="aK"}2G.7T.aJ(2p,2G)}},aL:h(7U){p.B.7Q(1q,"aM",h(){p.1I(7U)})}};p.4i=h(4j,7V,19){c.1U=4j;c.G=7V;c.v=4j.v;c.19=19};p.4i.Y.2r=h(){q c.1U};p.4B=h(4y){l 1J=p.B.4l(4y),4z=T p.2B.aN(),aH=u;f(1J==u){q}1J=T 1J();c.4E=4z;f(1J.3O==u){p.B.1v(p.M.1k.7X+4y);q}4z.5n.K({3q:1J.3O.I,4L:89});h 3a(4K,7W){D(l j=0;j<4K.v;j++){4K[j].G+=7W}};h 89(17,aC){l 8f=17.I,1L=[],4N=1J.5n,8e=17.G+17.E.v,2Z=1J.3O,1l;D(l i=0;i<4N.v;i++){1l=p.B.30(8f,4N[i]);3a(1l,8e);1L=1L.31(1l)}f(2Z.E!=u&&17.E!=u){1l=p.B.30(17.E,2Z.E);3a(1l,17.G);1L=1L.31(1l)}f(2Z.13!=u&&17.13!=u){1l=p.B.30(17.13,2Z.13);3a(1l,17.G+17[0].aE(17.13));1L=1L.31(1l)}q 1L}};p.4B.Y.1I=h(8h,8i){c.4E.1I(8h,8i);c.A=c.4E.A};p.8b=h(){};p.8b.Y={V:h(8c,8g){l 3Z=c.1A[8c];q p.B.8d(3Z==u?8g:3Z)},12:h(8j){q L.1s(8j)},72:h(38,7O){l 2w=[];f(38!=u){D(l i=0;i<38.v;i++){2w=2w.31(p.B.30(7O,38[i]))}}2w=2w.am(p.B.7d);q 2w},73:h(){l 26=c.2R;D(l i=0;i<26.v;i++){f(26[i]===u){1H}l 2x=26[i],45=2x.G+2x.v;D(l j=i+1;j<26.v&&26[i]!==u;j++){l 20=26[j];f(20===u){1H}F{f(20.G>45){2m}F{f(20.G==2x.G&&20.v>2x.v){c.2R[i]=u}F{f(20.G>=2x.G&&20.G<45){c.2R[j]=u}}}}}}},7m:h(2M){l 36=2M.1P(/\\n/g),3f=7b(c.V("79-2P")),7e=(3f+36.v).2r().v,7f=c.V("1I",[]);2M="";D(l i=0;i<36.v;i++){l 1r=36[i],2y=/^(&1X;|\\s)+/.Q(1r),5A="2P a3"+(i%2==0?1:2),7j=p.B.7a(3f+i,7e),7k=7f.1i((3f+i).2r())!=-1,1E=u;f(2y!=u){1E=2y[0].2r();1r=1r.1Q(1E.v);1E=1E.C(/&1X;/g," ");2y=p.1t.3k*1E.v}F{2y=0}1r=p.B.33(1r);f(1r.v==0){1r="&1X;"}f(7k){5A+=" a6"}2M+=""+""+7j+"."+"<1V 1e=\\"5B\\">"+(1E!=u?""+1E.C(/\\s/g,"&1X;")+"":"")+"<1V 1e=\\"7i\\" 1n=\\"5D-E: "+2y+"5x !78;\\">"+1r+""+""+""}q 2M},7l:h(5v,5r){l 18=0,3o="",3n=p.B.7g;D(l i=0;i<5r.v;i++){l 1N=5r[i];f(1N===u||1N.v===0){1H}3o+=3n(5v.1Q(18,1N.G-18),"7h")+3n(1N.1U,1N.19);18=1N.G+1N.v}3o+=3n(5v.1Q(18),"7h");q 3o},1I:h(1j,6Y){l a1=p.M,3l=p.1t,A,9Z,3i,a0="78";c.1A={};c.A=u;c.1m=u;c.I=u;c.1h=u;c.5I={};c.1g=p.B.5H("a8");3l.5K[c.1g]=c;f(1j===u){1j=""}f(3l.3k===u){3l.3k=p.B.5p()}c.1A=p.B.5o(p.77,6Y||{});f(c.V("6Z")==U){c.1A.1z=c.1A.4Z=N}c.A=A=c.12("3j");c.1m=c.12("3j");c.1m.J="1m";J="7P";A.1g=c.1g;f(c.V("56")){J+=" 51"}f(c.V("4Z")==N){J+=" ak"}f(c.V("4S-1m")==N){c.1m.J+=" al-4S"}J+=" "+c.V("1e-1f");A.J=J;c.4W=1j;c.I=p.B.6W(1j).C(/\\r/g," ");3i=c.V("1C-2A");c.I=c.V("6V-70")==U?p.B.71(c.I,3i):p.B.76(c.I,3i);c.I=p.B.2D(c.I);f(c.V("1z")){c.1h=c.12("3j");c.1h.J="1h";c.1h.1G(p.1z.12(c));A.1G(c.1h);l 1h=c.1h;h 5d(){1h.J=1h.J.C("75","")};A.ab=h(){5d();1h.J+=" 75"};A.ad=h(){5d()}}f(c.V("5f")){A.1G(p.B.74())}A.1G(c.1m);c.2R=c.72(c.5n,c.I);c.73();1j=c.7l(c.I,c.2R);1j=c.7m(p.B.33(1j));f(c.V("7G-7F")){1j=p.B.7C(1j)}c.1m.1x=1j},bn:h(z){z=z.C(/^\\s+|\\s+$/g,"").C(/\\s+/g,"\\\\b|\\\\b");q"\\\\b"+z+"\\\\b"},bl:h(2W){c.3O={E:{3q:2W.E,19:"2c"},13:{3q:2W.13,19:"2c"},I:T R("(?"+2W.E.1c+")"+"(?.*?)"+"(?<13>"+2W.13.1c+")","bv")}}};q p}()}f(!5V.1i){5V.Y.1i=h(7M,3R){3R=3J.bF(3R||0,0);D(l i=3R;i|[7B]{[^}]+})[\\S\\s]?|\\((?=\\?(?!#|<[\\w$]+>)))+|(\\()(?:\\?(?:(#)[^)]*\\)|<([$\\w]+)>))?|\\\\(?:k<([\\w$]+)>|[7B]{([^}]+)})|(\\[\\^?)|([\\S\\s])/g,by:/(?:[^$]+|\\$(?![1-9$&`\']|{[$\\w]+}))+|\\$(?:([1-9]\\d*|[$&`\'])|{([$\\w]+)})/g,3M:/^(?:\\s+|#.*)+/,5F:/^(?:[?*+]|{\\d+(?:,\\d*)?})/,7x:/&&\\[\\^?/g,7v:/]/g},7n=h(5l,5k,4X){D(l i=4X||0;i<5l.v;i++){f(5l[i]===5k){q i}}q-1},7y=/()??/.Q("")[1]!==3K,3w={};R=h(1d,1Y){f(1d 3T 11){f(1Y!==3K){3L 7N("4C\'t 4I bJ 7H aY 7J 11 4X aZ")}q 1d.3C()}l 1Y=1Y||"",7w=1Y.1i("s")>-1,6X=1Y.1i("x")>-1,5q=N,3u=[],14=[],W=1K.W,H,3D,3F,3E,3v;W.O=0;29(H=2z.Q.2n(W,1d)){f(H[2]){f(!1K.5F.1R(1d.15(W.O))){14.K("(?:)")}}F{f(H[1]){3u.K(H[3]||u);f(H[3]){5q=U}14.K("(")}F{f(H[4]){3E=7n(3u,H[4]);14.K(3E>-1?"\\\\"+(3E+1)+(55(1d.5J(W.O))?"":"(?:)"):H[0])}F{f(H[5]){14.K(3w.7t?3w.7t.7u(H[5],H[0].5J(1)==="P"):H[0])}F{f(H[6]){f(1d.5J(W.O)==="]"){14.K(H[6]==="["?"(?!)":"[\\\\S\\\\s]");W.O++}F{3D=R.7q("&&"+1d.15(H.G),1K.7x,1K.7v,"",{7s:"\\\\"})[0];14.K(H[6]+3D+"]");W.O+=3D.v+1}}F{f(H[7]){f(7w&&H[7]==="."){14.K("[\\\\S\\\\s]")}F{f(6X&&1K.3M.1R(H[7])){3F=2z.Q.2n(1K.3M,1d.15(W.O-1))[0].v;f(!1K.5F.1R(1d.15(W.O-1+3F))){14.K("(?:)")}W.O+=3F-1}F{14.K(H[7])}}}F{14.K(H[0])}}}}}}}3v=11(14.5u(""),2z.C.2n(1Y,/[8y]+/g,""));3v.1u={1c:1d,2j:5q?3u:u};q 3v};R.8B=h(1f,o){3w[1f]=o};11.Y.Q=h(z){l 1b=2z.Q.2n(c,z),1f,i,5C;f(1b){f(7y&&1b.v>1){5C=T 11("^"+c.1c+"$(?!\\\\s)",c.4a());2z.C.2n(1b[0],5C,h(){D(i=1;i<7z.v-2;i++){f(7z[i]===3K){1b[i]=3K}}})}f(c.1u&&c.1u.2j){D(i=1;i<1b.v;i++){1f=c.1u.2j[i-1];f(1f){1b[1f]=1b[i]}}}f(c.3A&&c.O>(1b.G+1b[0].v)){c.O--}}q 1b}})()}11.Y.4a=h(){q(c.3A?"g":"")+(c.8M?"i":"")+(c.7D?"m":"")+(c.3M?"x":"")+(c.8Y?"y":"")};11.Y.3C=h(7o){l 4g=T R(c.1c,(7o||"")+c.4a());f(c.1u){4g.1u={1c:c.1u.1c,2j:c.1u.2j?c.1u.2j.15(0):u}}q 4g};11.Y.2n=h(90,z){q c.Q(z)};11.Y.8W=h(8U,7p){q c.Q(7p[0])};R.47=h(4f,4e){l 46="/"+4f+"/"+(4e||"");q R.47[46]||(R.47[46]=T R(4f,4e))};R.3t=h(z){q z.C(/[-[\\]{}()*+?.\\\\^$|,#\\s]/g,"\\\\$&")};R.7q=h(z,E,Z,1a,2T){l 2T=2T||{},2X=2T.7s,X=2T.8A,1a=1a||"",4s=1a.1i("g")>-1,7E=1a.1i("i")>-1,7L=1a.1i("m")>-1,4t=1a.1i("y")>-1,1a=1a.C(/y/g,""),E=E 3T 11?(E.3A?E:E.3C("g")):T R(E,"g"+1a),Z=Z 3T 11?(Z.3A?Z:Z.3C("g")):T R(Z,"g"+1a),1D=[],2b=0,1o=0,1p=0,1y=0,27,22,1w,1B,3I,4m;f(2X){f(2X.v>1){3L 8n("4C\'t 4I 8q 8z 7J 3t 7I")}f(7L){3L 7N("4C\'t 4I 3t 7I 7H 9U 9D 7D 9C")}3I=R.3t(2X);4m=T 11("^(?:"+3I+"[\\\\S\\\\s]|(?:(?!"+E.1c+"|"+Z.1c+")[^"+3I+"])+)+",7E?"i":"")}29(U){E.O=Z.O=1p+(2X?(4m.Q(z.15(1p))||[""])[0].v:0);1w=E.Q(z);1B=Z.Q(z);f(1w&&1B){f(1w.G<=1B.G){1B=u}F{1w=u}}f(1w||1B){1o=(1w||1B).G;1p=(1w?E:Z).O}F{f(!2b){2m}}f(4t&&!2b&&1o>1y){2m}f(1w){f(!2b++){27=1o;22=1p}}F{f(1B&&2b){f(!--2b){f(X){f(X[0]&&27>1y){1D.K([X[0],z.15(1y,27),1y,27])}f(X[1]){1D.K([X[1],z.15(27,22),27,22])}f(X[2]){1D.K([X[2],z.15(22,1o),22,1o])}f(X[3]){1D.K([X[3],z.15(1o,1p),1o,1p])}}F{1D.K(z.15(22,1o))}1y=1p;f(!4s){2m}}}F{E.O=Z.O=0;3L 9q("9A 9i 9a 9d 8u")}}f(1o===1p){1p++}}f(4s&&!4t&&X&&X[0]&&z.v>1y){1D.K([X[0],z.15(1y),1y,z.v])}E.O=Z.O=0;q 1D};',62,728,'||||||||||||this|||if||function||||var||||sh|return||||null|length||||str|div|utils|replace|for|left|else|index|_10f|code|className|push|document|config|false|lastIndex||exec|XRegExp||new|true|getParam|part|vN|prototype|_127||RegExp|create|right|_10d|slice||_c4|pos|css|_128|_117|source|_107|class|name|id|bar|indexOf|_f0|strings|_cb|lines|style|_132|_133|window|_e3|createElement|vars|_x|alert|_137|innerHTML|_134|toolbar|params|_138|tab|_130|_e8|lt|appendChild|continue|highlight|_be|lib|_c7|obj|_ef|doc|split|substr|test|width|_4b|value|span|_3c|nbsp|_108|min|_dc|_98|_136|in|_57|_56|_d7|_135|_8|while|_91|_131|script|text|_b2|_6e|http|execute|wnd|captureNames|_5b|_b5|break|call|gt|_b8|href|toString|_75|height|html|attributes|_d5|_d9|_e4|_fe|size|brushes|_88|unindent|SyntaxHighlighter|_40|_b4|_a2|_7a|_51|m1|body|_dd|case|m2|line|_80|matches|_28|_129|_62|_81|_fa|_12a|_5|_ca|getMatches|concat|_b6|trim|print|_7c|_de|_5e|_d3|_a7|offsetMatches|_5c|_76|_6a|_65|_df|_b0|write|_f6|DIV|spaceWidth|_f3|_4a|_ed|_ec|url|regex|_7d|_2|escape|_10c|_113|_106|_7b|_3|_8e|global|title|addFlags|cc|_112|len|fixInputString|_32|_139|Math|undefined|throw|extended|font|htmlScript|printFrame|_22|_fc|_25|instanceof|_17|_9d|_9e|_18|expandSource|_d1|_8c|viewSource|_1a|top|_4f|_da|key|cache|_10|win|getNativeFlags|_19|_50|focus|_122|_121|_11c|_b|Match|_ba|gm|findBrush|esc|eachLine|_4|_6c|values|_73|_12c|_12f|_6b|color|_89|gi|_bd|_bf|_9|HtmlScript|can|discoveredBrushes|xmlBrush|_f|_5d|_82|supply|_7|_c1|func|_59|_c8|_b7|_e|_d|pre|wrap|_ac|com|_a3|originalCode|from|link|gutter||collapsed|clipboardSwf|_37|popup|isNaN|collapse|_blank|_38|_ae|removeChild|String|contentWindow|hide|_24|ruler|swf|_30|_7e|_ad|item|_101|_2f|regexList|merge|measureSpace|_10b|_ea|_2a|_2c|join|_e9|_2e|px|_2b|_4c|_e5|content|r2|margin|_29|quantifier|_49|guid|toolbarCommands|charAt|highlighters|_27|highlighterId|_a6|close|toolbarItemWidth|_2d|_48|toolbarItemHeight|_35|copyToClipboard|Array|userAgent|_90|_84|navigator|_85|_78|_79|_83|_3f|items|_1e|_16|_13|_12|shockwave|flash|clipboardData|_36|object|version|_15|_14|center|alexgorbatchev|align|head|org|2009|_6|executeCommand|commandName|_a|createButton|copyToClipboardConfirmation|message|w3|event|_4e|screen|switch|attachEvent|_5a|_66|www|_61|noBrush|_47|aboutDialog|insertSpaces|copyStyles|500px|0px|_3e|type|scrollbars|help|stylesheet|rel|_6d|debug|DTD|smart|trimFirstAndLastLines|_10a|_f1|light|tabs|processSmartTabs|findMatches|removeNestedMatches|createRuler|show|processTabs|defaults|important|first|padNumber|parseInt|xhtml1|matchesSortCallback|_e0|_e1|decorate|plain|block|_e6|_e7|processMatches|createDisplayLines|_100|_11b|args|matchRecursive|_93|escapeChar|unicode|get|classRight|_109|classLeft|_105|arguments|clipboard|pP|processUrls|multiline|_12d|links|auto|when|character|one|match|_12e|_fb|TypeError|_d4|syntaxhighlighter|addEvent|defaultAdd|_a1|parentNode|_b9|_bb|_c2|brushNotHtmlScript|_a4|_a8|_b1|toArray|getElementsByTagName|tagName|parseParams|regexLib|_a9|brush|_ab|process|_9a|Highlighter|_cf|toBoolean|_c9|_c6|_d0|_cd|_ce|_d2|bloggerMode|stripBrs|catch|SyntaxError|now|Can|more|xhtml|utf|onclick|delimiters|wasn|your|family|sx|than|valueNames|addPlugin|About|try|charset|_26|400|750|find|_21|location|Type|ignoreCase|menubar|resizable|Content|_20|_1f|param|meta|_11f|Brush|apply|_1b|sticky|Geneva|_11d|_1c|equiv|to|syntax|highlighter|JavaScript|expand|none|3em|contains|view|Alex|unbalanced|2004|Copyright|decoration|0099FF|data|320|4em|bottom|75em|May|large|xx|Error|target|03|Gorbatchev|multiLineCComments|aspScriptTags|scriptScriptTags|phpScriptTags|Arial|multiLineSingleQuotedString|subject|The|flag|the|is|string|typeof|Helvetica|sans|000|fff|1em|singleLinePerlComments|singleLineCComments|copy|doubleQuotedString|serif|multiLineDoubleQuotedString|background|singleQuotedString|using|W3C|random|1000000|round|_f5|_f7|_f2|spaces|alt|transitional|open|highlighted|number|highlighter_|250|shCore|onmouseover|toLowerCase|onmouseout|printing|about|_42|_44|500|_43|nogutter|no|sort|on|getComputedStyle|getPropertyValue|opera|getElementById|1999|offsetWidth|_a5|_99|dtd|1000|xmlns|_8a|textarea|70em|_c5|150|lastIndexOf|aliases|addEventListener|_c0|middot|replaceChild|30em|all|load|Xml|absolute|position|444553540000|codebase|96b8|11cf|ae6d|PUBLIC|download|cabs|constructing|another|pub|macromedia|d27cdb6e|clsid|always|wmode|allowScriptAccess|application|_clipboard|transparent|flashVars|msie|classid|menu|DOCTYPE|option|swflash|cab|TR|error|ok|forHtmlScript|setData|getKeywords|printSource|IFRAME|cssText||_3b|_3a|_39|sgi|amp|Transitional|replaceVar|XHTML|embed|movie|src|configured|command|max|_34|_33|EN|flags'.split('|'),0,{})) 31 | -------------------------------------------------------------------------------- /war/js/shLegacy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/ 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate 7 | * 8 | * @version 9 | * 2.0.320 (May 03 2009) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2009 Alex Gorbatchev. 13 | * 14 | * @license 15 | * This file is part of SyntaxHighlighter. 16 | * 17 | * SyntaxHighlighter is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Lesser General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * SyntaxHighlighter is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with SyntaxHighlighter. If not, see . 29 | */ 30 | eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1 y={d:{}};y.d={F:6(S,l,q,k,m,n){6 J(z,Y){1 V=16 15("^"+Y+"\\\\[(?\\\\w+)\\\\]$","14"),x=2;h(1 i=0;i 0) 53 | throw "End of stringstream reached without emptying buffer ('" + accum + "')."; 54 | else 55 | throw StopIteration; 56 | } 57 | return current.charAt(pos++); 58 | }, 59 | // Return the characters iterated over since the last call to 60 | // .get(). 61 | get: function() { 62 | var temp = accum; 63 | accum = ""; 64 | if (pos > 0){ 65 | temp += current.slice(0, pos); 66 | current = current.slice(pos); 67 | pos = 0; 68 | } 69 | return temp; 70 | }, 71 | // Push a string back into the stream. 72 | push: function(str) { 73 | current = current.slice(0, pos) + str + current.slice(pos); 74 | }, 75 | lookAhead: function(str, consume, skipSpaces, caseInsensitive) { 76 | function cased(str) {return caseInsensitive ? str.toLowerCase() : str;} 77 | str = cased(str); 78 | var found = false; 79 | 80 | var _accum = accum, _pos = pos; 81 | if (skipSpaces) this.nextWhile(matcher(/[\s\u00a0]/)); 82 | 83 | while (true) { 84 | var end = pos + str.length, left = current.length - pos; 85 | if (end <= current.length) { 86 | found = str == cased(current.slice(pos, end)); 87 | pos = end; 88 | break; 89 | } 90 | else if (str.slice(0, left) == cased(current.slice(pos))) { 91 | accum += current; current = ""; 92 | try {current = source.next();} 93 | catch (e) {break;} 94 | pos = 0; 95 | str = str.slice(left); 96 | } 97 | else { 98 | break; 99 | } 100 | } 101 | 102 | if (!(found && consume)) { 103 | current = accum.slice(_accum.length) + current; 104 | pos = _pos; 105 | accum = _accum; 106 | } 107 | 108 | return found; 109 | }, 110 | 111 | // Utils built on top of the above 112 | more: function() { 113 | return this.peek() !== null; 114 | }, 115 | applies: function(test) { 116 | var next = this.peek(); 117 | return (next !== null && test(next)); 118 | }, 119 | nextWhile: function(test) { 120 | while (this.applies(test)) 121 | this.next(); 122 | }, 123 | equals: function(ch) { 124 | return ch === this.peek(); 125 | }, 126 | endOfLine: function() { 127 | var next = this.peek(); 128 | return next == null || next == "\n"; 129 | } 130 | }; 131 | }; 132 | -------------------------------------------------------------------------------- /war/js/tokenize.js: -------------------------------------------------------------------------------- 1 | // A framework for simple tokenizers. Takes care of newlines and 2 | // white-space, and of getting the text from the source stream into 3 | // the token object. A state is a function of two arguments -- a 4 | // string stream and a setState function. The second can be used to 5 | // change the tokenizer's state, and can be ignored for stateless 6 | // tokenizers. This function should advance the stream over a token 7 | // and return a string or object containing information about the next 8 | // token, or null to pass and have the (new) state be called to finish 9 | // the token. When a string is given, it is wrapped in a {style, type} 10 | // object. In the resulting object, the characters consumed are stored 11 | // under the content property. Any whitespace following them is also 12 | // automatically consumed, and added to the value property. (Thus, 13 | // content is the actual meaningful part of the token, while value 14 | // contains all the text it spans.) 15 | 16 | function tokenizer(source, state) { 17 | // Newlines are always a separate token. 18 | function isWhiteSpace(ch) { 19 | // The messy regexp is because IE's regexp matcher is of the 20 | // opinion that non-breaking spaces are no whitespace. 21 | return ch != "\n" && /^[\s\u00a0]*$/.test(ch); 22 | } 23 | 24 | var tokenizer = { 25 | state: state, 26 | 27 | take: function(type) { 28 | if (typeof(type) == "string") 29 | type = {style: type, type: type}; 30 | 31 | type.content = (type.content || "") + source.get(); 32 | if (!/\n$/.test(type.content)) 33 | source.nextWhile(isWhiteSpace); 34 | type.value = type.content + source.get(); 35 | return type; 36 | }, 37 | 38 | next: function () { 39 | if (!source.more()) throw StopIteration; 40 | 41 | var type; 42 | if (source.equals("\n")) { 43 | source.next(); 44 | return this.take("whitespace"); 45 | } 46 | 47 | if (source.applies(isWhiteSpace)) 48 | type = "whitespace"; 49 | else 50 | while (!type) 51 | type = this.state(source, function(s) {tokenizer.state = s;}); 52 | 53 | return this.take(type); 54 | } 55 | }; 56 | return tokenizer; 57 | } 58 | -------------------------------------------------------------------------------- /war/js/tokenizejavascript.js: -------------------------------------------------------------------------------- 1 | /* Tokenizer for JavaScript code */ 2 | 3 | var tokenizeJavaScript = (function() { 4 | // Advance the stream until the given character (not preceded by a 5 | // backslash) is encountered, or the end of the line is reached. 6 | function nextUntilUnescaped(source, end) { 7 | var escaped = false; 8 | var next; 9 | while (!source.endOfLine()) { 10 | var next = source.next(); 11 | if (next == end && !escaped) 12 | return false; 13 | escaped = !escaped && next == "\\"; 14 | } 15 | return escaped; 16 | } 17 | 18 | // A map of JavaScript's keywords. The a/b/c keyword distinction is 19 | // very rough, but it gives the parser enough information to parse 20 | // correct code correctly (we don't care that much how we parse 21 | // incorrect code). The style information included in these objects 22 | // is used by the highlighter to pick the correct CSS style for a 23 | // token. 24 | var keywords = function(){ 25 | function result(type, style){ 26 | return {type: type, style: "js-" + style}; 27 | } 28 | // keywords that take a parenthised expression, and then a 29 | // statement (if) 30 | var keywordA = result("keyword a", "keyword"); 31 | // keywords that take just a statement (else) 32 | var keywordB = result("keyword b", "keyword"); 33 | // keywords that optionally take an expression, and form a 34 | // statement (return) 35 | var keywordC = result("keyword c", "keyword"); 36 | var operator = result("operator", "keyword"); 37 | var atom = result("atom", "atom"); 38 | return { 39 | "if": keywordA, "while": keywordA, "with": keywordA, "import": keywordA, "static": keywordA, "assert": keywordA, "throws": keywordA, 40 | "public": keywordA, "private": keywordA, "protected": keywordA, "final": keywordA, 41 | "trait": keywordA, "class": keywordA, "extends": keywordA, "implements": keywordA, "void": keywordA, "super": keywordA, "this": keywordA, 42 | "int": keywordA, "boolean": keywordA, "float": keywordA, "double": keywordA, "long": keywordA, "byte": keywordA, "short": keywordA, "byte": keywordA, 43 | "else": keywordB, "try": keywordB, "finally": keywordB, 44 | "return": keywordC, "break": keywordC, "continue": keywordC, "new": keywordC, "throw": keywordC, 45 | "in": operator, "as": operator, "instanceof": operator, 46 | "def": result("def", "keyword"), "catch": result("catch", "keyword"), 47 | "for": result("for", "keyword"), "switch": result("switch", "keyword"), 48 | "case": result("case", "keyword"), "default": result("default", "keyword"), 49 | "true": atom, "false": atom, "null": atom 50 | }; 51 | }(); 52 | 53 | // Some helper regexp matchers. 54 | var isOperatorChar = matcher(/[+\-*&%\/=<>!?|]/); 55 | var isDigit = matcher(/[0-9]/); 56 | var isHexDigit = matcher(/[0-9A-Fa-f]/); 57 | var isWordChar = matcher(/[\w\$_]/); 58 | 59 | // Wrapper around jsToken that helps maintain parser state (whether 60 | // we are inside of a multi-line comment and whether the next token 61 | // could be a regular expression). 62 | function jsTokenState(inside, regexp) { 63 | return function(source, setState) { 64 | var newInside = inside; 65 | var type = jsToken(inside, regexp, source, function(c) {newInside = c;}); 66 | var newRegexp = type.type == "operator" || type.type == "keyword c" || type.type.match(/^[\[{}\(,;:]$/); 67 | if (newRegexp != regexp || newInside != inside) 68 | setState(jsTokenState(newInside, newRegexp)); 69 | return type; 70 | }; 71 | } 72 | 73 | // The token reader, inteded to be used by the tokenizer from 74 | // tokenize.js (through jsTokenState). Advances the source stream 75 | // over a token, and returns an object containing the type and style 76 | // of that token. 77 | function jsToken(inside, regexp, source, setInside) { 78 | function readHexNumber(){ 79 | source.next(); // skip the 'x' 80 | source.nextWhile(isHexDigit); 81 | return {type: "number", style: "js-atom"}; 82 | } 83 | 84 | function readNumber() { 85 | source.nextWhile(isDigit); 86 | if (source.equals(".")){ 87 | source.next(); 88 | source.nextWhile(isDigit); 89 | } 90 | if (source.equals("e") || source.equals("E")){ 91 | source.next(); 92 | if (source.equals("-")) 93 | source.next(); 94 | source.nextWhile(isDigit); 95 | } 96 | return {type: "number", style: "js-atom"}; 97 | } 98 | // Read a word, look it up in keywords. If not found, it is a 99 | // variable, otherwise it is a keyword of the type found. 100 | function readWord() { 101 | source.nextWhile(isWordChar); 102 | var word = source.get(); 103 | var known = keywords.hasOwnProperty(word) && keywords.propertyIsEnumerable(word) && keywords[word]; 104 | return known ? {type: known.type, style: known.style, content: word} : 105 | {type: "variable", style: "js-variable", content: word}; 106 | } 107 | function readRegexp() { 108 | nextUntilUnescaped(source, "/"); 109 | source.nextWhile(matcher(/[gi]/)); 110 | return {type: "regexp", style: "js-string"}; 111 | } 112 | // Mutli-line comments are tricky. We want to return the newlines 113 | // embedded in them as regular newline tokens, and then continue 114 | // returning a comment token for every line of the comment. So 115 | // some state has to be saved (inside) to indicate whether we are 116 | // inside a /* */ sequence. 117 | function readMultilineComment(start){ 118 | var newInside = "/*"; 119 | var maybeEnd = (start == "*"); 120 | while (true) { 121 | if (source.endOfLine()) 122 | break; 123 | var next = source.next(); 124 | if (next == "/" && maybeEnd){ 125 | newInside = null; 126 | break; 127 | } 128 | maybeEnd = (next == "*"); 129 | } 130 | setInside(newInside); 131 | return {type: "comment", style: "js-comment"}; 132 | } 133 | function readOperator() { 134 | source.nextWhile(isOperatorChar); 135 | return {type: "operator", style: "js-operator"}; 136 | } 137 | function readString(quote) { 138 | var endBackSlash = nextUntilUnescaped(source, quote); 139 | setInside(endBackSlash ? quote : null); 140 | return {type: "string", style: "js-string"}; 141 | } 142 | 143 | // Fetch the next token. Dispatches on first character in the 144 | // stream, or first two characters when the first is a slash. 145 | if (inside == "\"" || inside == "'") 146 | return readString(inside); 147 | var ch = source.next(); 148 | if (inside == "/*") 149 | return readMultilineComment(ch); 150 | else if (ch == "\"" || ch == "'") 151 | return readString(ch); 152 | // with punctuation, the type of the token is the symbol itself 153 | else if (/[\[\]{}\(\),;\:\.]/.test(ch)) 154 | return {type: ch, style: "js-punctuation"}; 155 | else if (ch == "0" && (source.equals("x") || source.equals("X"))) 156 | return readHexNumber(); 157 | else if (isDigit(ch)) 158 | return readNumber(); 159 | else if (ch == "/"){ 160 | if (source.equals("*")) 161 | { source.next(); return readMultilineComment(ch); } 162 | else if (source.equals("/")) 163 | { nextUntilUnescaped(source, null); return {type: "comment", style: "js-comment"};} 164 | else if (regexp) 165 | return readRegexp(); 166 | else 167 | return readOperator(); 168 | } 169 | else if (isOperatorChar(ch)) 170 | return readOperator(); 171 | else 172 | return readWord(); 173 | } 174 | 175 | // The external interface to the tokenizer. 176 | return function(source, startState) { 177 | return tokenizer(source, startState || jsTokenState(false, true)); 178 | }; 179 | })(); 180 | -------------------------------------------------------------------------------- /war/js/undo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Storage and control for undo information within a CodeMirror 3 | * editor. 'Why on earth is such a complicated mess required for 4 | * that?', I hear you ask. The goal, in implementing this, was to make 5 | * the complexity of storing and reverting undo information depend 6 | * only on the size of the edited or restored content, not on the size 7 | * of the whole document. This makes it necessary to use a kind of 8 | * 'diff' system, which, when applied to a DOM tree, causes some 9 | * complexity and hackery. 10 | * 11 | * In short, the editor 'touches' BR elements as it parses them, and 12 | * the History stores these. When nothing is touched in commitDelay 13 | * milliseconds, the changes are committed: It goes over all touched 14 | * nodes, throws out the ones that did not change since last commit or 15 | * are no longer in the document, and assembles the rest into zero or 16 | * more 'chains' -- arrays of adjacent lines. Links back to these 17 | * chains are added to the BR nodes, while the chain that previously 18 | * spanned these nodes is added to the undo history. Undoing a change 19 | * means taking such a chain off the undo history, restoring its 20 | * content (text is saved per line) and linking it back into the 21 | * document. 22 | */ 23 | 24 | // A history object needs to know about the DOM container holding the 25 | // document, the maximum amount of undo levels it should store, the 26 | // delay (of no input) after which it commits a set of changes, and, 27 | // unfortunately, the 'parent' window -- a window that is not in 28 | // designMode, and on which setTimeout works in every browser. 29 | function History(container, maxDepth, commitDelay, editor, onChange) { 30 | this.container = container; 31 | this.maxDepth = maxDepth; this.commitDelay = commitDelay; 32 | this.editor = editor; this.parent = editor.parent; 33 | this.onChange = onChange; 34 | // This line object represents the initial, empty editor. 35 | var initial = {text: "", from: null, to: null}; 36 | // As the borders between lines are represented by BR elements, the 37 | // start of the first line and the end of the last one are 38 | // represented by null. Since you can not store any properties 39 | // (links to line objects) in null, these properties are used in 40 | // those cases. 41 | this.first = initial; this.last = initial; 42 | // Similarly, a 'historyTouched' property is added to the BR in 43 | // front of lines that have already been touched, and 'firstTouched' 44 | // is used for the first line. 45 | this.firstTouched = false; 46 | // History is the set of committed changes, touched is the set of 47 | // nodes touched since the last commit. 48 | this.history = []; this.redoHistory = []; this.touched = []; 49 | } 50 | 51 | History.prototype = { 52 | // Schedule a commit (if no other touches come in for commitDelay 53 | // milliseconds). 54 | scheduleCommit: function() { 55 | this.parent.clearTimeout(this.commitTimeout); 56 | this.commitTimeout = this.parent.setTimeout(method(this, "tryCommit"), this.commitDelay); 57 | }, 58 | 59 | // Mark a node as touched. Null is a valid argument. 60 | touch: function(node) { 61 | this.setTouched(node); 62 | this.scheduleCommit(); 63 | }, 64 | 65 | // Undo the last change. 66 | undo: function() { 67 | // Make sure pending changes have been committed. 68 | this.commit(); 69 | 70 | if (this.history.length) { 71 | // Take the top diff from the history, apply it, and store its 72 | // shadow in the redo history. 73 | var item = this.history.pop(); 74 | this.redoHistory.push(this.updateTo(item, "applyChain")); 75 | if (this.onChange) this.onChange(); 76 | return this.chainNode(item); 77 | } 78 | }, 79 | 80 | // Redo the last undone change. 81 | redo: function() { 82 | this.commit(); 83 | if (this.redoHistory.length) { 84 | // The inverse of undo, basically. 85 | var item = this.redoHistory.pop(); 86 | this.addUndoLevel(this.updateTo(item, "applyChain")); 87 | if (this.onChange) this.onChange(); 88 | return this.chainNode(item); 89 | } 90 | }, 91 | 92 | // Ask for the size of the un/redo histories. 93 | historySize: function() { 94 | return {undo: this.history.length, redo: this.redoHistory.length}; 95 | }, 96 | 97 | // Push a changeset into the document. 98 | push: function(from, to, lines) { 99 | var chain = []; 100 | for (var i = 0; i < lines.length; i++) { 101 | var end = (i == lines.length - 1) ? to : this.container.ownerDocument.createElement("BR"); 102 | chain.push({from: from, to: end, text: cleanText(lines[i])}); 103 | from = end; 104 | } 105 | this.pushChains([chain], from == null && to == null); 106 | }, 107 | 108 | pushChains: function(chains, doNotHighlight) { 109 | this.commit(doNotHighlight); 110 | this.addUndoLevel(this.updateTo(chains, "applyChain")); 111 | this.redoHistory = []; 112 | }, 113 | 114 | // Retrieve a DOM node from a chain (for scrolling to it after undo/redo). 115 | chainNode: function(chains) { 116 | for (var i = 0; i < chains.length; i++) { 117 | var start = chains[i][0], node = start && (start.from || start.to); 118 | if (node) return node; 119 | } 120 | }, 121 | 122 | // Clear the undo history, make the current document the start 123 | // position. 124 | reset: function() { 125 | this.history = []; this.redoHistory = []; 126 | }, 127 | 128 | textAfter: function(br) { 129 | return this.after(br).text; 130 | }, 131 | 132 | nodeAfter: function(br) { 133 | return this.after(br).to; 134 | }, 135 | 136 | nodeBefore: function(br) { 137 | return this.before(br).from; 138 | }, 139 | 140 | // Commit unless there are pending dirty nodes. 141 | tryCommit: function() { 142 | if (this.editor.highlightDirty()) this.commit(); 143 | else this.scheduleCommit(); 144 | }, 145 | 146 | // Check whether the touched nodes hold any changes, if so, commit 147 | // them. 148 | commit: function(doNotHighlight) { 149 | this.parent.clearTimeout(this.commitTimeout); 150 | // Make sure there are no pending dirty nodes. 151 | if (!doNotHighlight) this.editor.highlightDirty(true); 152 | // Build set of chains. 153 | var chains = this.touchedChains(), self = this; 154 | 155 | if (chains.length) { 156 | this.addUndoLevel(this.updateTo(chains, "linkChain")); 157 | this.redoHistory = []; 158 | if (this.onChange) this.onChange(); 159 | } 160 | }, 161 | 162 | // [ end of public interface ] 163 | 164 | // Update the document with a given set of chains, return its 165 | // shadow. updateFunc should be "applyChain" or "linkChain". In the 166 | // second case, the chains are taken to correspond the the current 167 | // document, and only the state of the line data is updated. In the 168 | // first case, the content of the chains is also pushed iinto the 169 | // document. 170 | updateTo: function(chains, updateFunc) { 171 | var shadows = [], dirty = []; 172 | for (var i = 0; i < chains.length; i++) { 173 | shadows.push(this.shadowChain(chains[i])); 174 | dirty.push(this[updateFunc](chains[i])); 175 | } 176 | if (updateFunc == "applyChain") 177 | this.notifyDirty(dirty); 178 | return shadows; 179 | }, 180 | 181 | // Notify the editor that some nodes have changed. 182 | notifyDirty: function(nodes) { 183 | forEach(nodes, method(this.editor, "addDirtyNode")) 184 | this.editor.scheduleHighlight(); 185 | }, 186 | 187 | // Link a chain into the DOM nodes (or the first/last links for null 188 | // nodes). 189 | linkChain: function(chain) { 190 | for (var i = 0; i < chain.length; i++) { 191 | var line = chain[i]; 192 | if (line.from) line.from.historyAfter = line; 193 | else this.first = line; 194 | if (line.to) line.to.historyBefore = line; 195 | else this.last = line; 196 | } 197 | }, 198 | 199 | // Get the line object after/before a given node. 200 | after: function(node) { 201 | return node ? node.historyAfter : this.first; 202 | }, 203 | before: function(node) { 204 | return node ? node.historyBefore : this.last; 205 | }, 206 | 207 | // Mark a node as touched if it has not already been marked. 208 | setTouched: function(node) { 209 | if (node) { 210 | if (!node.historyTouched) { 211 | this.touched.push(node); 212 | node.historyTouched = true; 213 | } 214 | } 215 | else { 216 | this.firstTouched = true; 217 | } 218 | }, 219 | 220 | // Store a new set of undo info, throw away info if there is more of 221 | // it than allowed. 222 | addUndoLevel: function(diffs) { 223 | this.history.push(diffs); 224 | if (this.history.length > this.maxDepth) 225 | this.history.shift(); 226 | }, 227 | 228 | // Build chains from a set of touched nodes. 229 | touchedChains: function() { 230 | var self = this; 231 | 232 | // The temp system is a crummy hack to speed up determining 233 | // whether a (currently touched) node has a line object associated 234 | // with it. nullTemp is used to store the object for the first 235 | // line, other nodes get it stored in their historyTemp property. 236 | var nullTemp = null; 237 | function temp(node) {return node ? node.historyTemp : nullTemp;} 238 | function setTemp(node, line) { 239 | if (node) node.historyTemp = line; 240 | else nullTemp = line; 241 | } 242 | 243 | function buildLine(node) { 244 | var text = []; 245 | for (var cur = node ? node.nextSibling : self.container.firstChild; 246 | cur && cur.nodeName != "BR"; cur = cur.nextSibling) 247 | if (cur.currentText) text.push(cur.currentText); 248 | return {from: node, to: cur, text: cleanText(text.join(""))}; 249 | } 250 | 251 | // Filter out unchanged lines and nodes that are no longer in the 252 | // document. Build up line objects for remaining nodes. 253 | var lines = []; 254 | if (self.firstTouched) self.touched.push(null); 255 | forEach(self.touched, function(node) { 256 | if (node && node.parentNode != self.container) return; 257 | 258 | if (node) node.historyTouched = false; 259 | else self.firstTouched = false; 260 | 261 | var line = buildLine(node), shadow = self.after(node); 262 | if (!shadow || shadow.text != line.text || shadow.to != line.to) { 263 | lines.push(line); 264 | setTemp(node, line); 265 | } 266 | }); 267 | 268 | // Get the BR element after/before the given node. 269 | function nextBR(node, dir) { 270 | var link = dir + "Sibling", search = node[link]; 271 | while (search && search.nodeName != "BR") 272 | search = search[link]; 273 | return search; 274 | } 275 | 276 | // Assemble line objects into chains by scanning the DOM tree 277 | // around them. 278 | var chains = []; self.touched = []; 279 | forEach(lines, function(line) { 280 | // Note that this makes the loop skip line objects that have 281 | // been pulled into chains by lines before them. 282 | if (!temp(line.from)) return; 283 | 284 | var chain = [], curNode = line.from, safe = true; 285 | // Put any line objects (referred to by temp info) before this 286 | // one on the front of the array. 287 | while (true) { 288 | var curLine = temp(curNode); 289 | if (!curLine) { 290 | if (safe) break; 291 | else curLine = buildLine(curNode); 292 | } 293 | chain.unshift(curLine); 294 | setTemp(curNode, null); 295 | if (!curNode) break; 296 | safe = self.after(curNode); 297 | curNode = nextBR(curNode, "previous"); 298 | } 299 | curNode = line.to; safe = self.before(line.from); 300 | // Add lines after this one at end of array. 301 | while (true) { 302 | if (!curNode) break; 303 | var curLine = temp(curNode); 304 | if (!curLine) { 305 | if (safe) break; 306 | else curLine = buildLine(curNode); 307 | } 308 | chain.push(curLine); 309 | setTemp(curNode, null); 310 | safe = self.before(curNode); 311 | curNode = nextBR(curNode, "next"); 312 | } 313 | chains.push(chain); 314 | }); 315 | 316 | return chains; 317 | }, 318 | 319 | // Find the 'shadow' of a given chain by following the links in the 320 | // DOM nodes at its start and end. 321 | shadowChain: function(chain) { 322 | var shadows = [], next = this.after(chain[0].from), end = chain[chain.length - 1].to; 323 | while (true) { 324 | shadows.push(next); 325 | var nextNode = next.to; 326 | if (!nextNode || nextNode == end) 327 | break; 328 | else 329 | next = nextNode.historyAfter || this.before(end); 330 | // (The this.before(end) is a hack -- FF sometimes removes 331 | // properties from BR nodes, in which case the best we can hope 332 | // for is to not break.) 333 | } 334 | return shadows; 335 | }, 336 | 337 | // Update the DOM tree to contain the lines specified in a given 338 | // chain, link this chain into the DOM nodes. 339 | applyChain: function(chain) { 340 | // Some attempt is made to prevent the cursor from jumping 341 | // randomly when an undo or redo happens. It still behaves a bit 342 | // strange sometimes. 343 | var cursor = select.cursorPos(this.container, false), self = this; 344 | 345 | // Remove all nodes in the DOM tree between from and to (null for 346 | // start/end of container). 347 | function removeRange(from, to) { 348 | var pos = from ? from.nextSibling : self.container.firstChild; 349 | while (pos != to) { 350 | var temp = pos.nextSibling; 351 | removeElement(pos); 352 | pos = temp; 353 | } 354 | } 355 | 356 | var start = chain[0].from, end = chain[chain.length - 1].to; 357 | // Clear the space where this change has to be made. 358 | removeRange(start, end); 359 | 360 | // Insert the content specified by the chain into the DOM tree. 361 | for (var i = 0; i < chain.length; i++) { 362 | var line = chain[i]; 363 | // The start and end of the space are already correct, but BR 364 | // tags inside it have to be put back. 365 | if (i > 0) 366 | self.container.insertBefore(line.from, end); 367 | 368 | // Add the text. 369 | var node = makePartSpan(fixSpaces(line.text), this.container.ownerDocument); 370 | self.container.insertBefore(node, end); 371 | // See if the cursor was on this line. Put it back, adjusting 372 | // for changed line length, if it was. 373 | if (cursor && cursor.node == line.from) { 374 | var cursordiff = 0; 375 | var prev = this.after(line.from); 376 | if (prev && i == chain.length - 1) { 377 | // Only adjust if the cursor is after the unchanged part of 378 | // the line. 379 | for (var match = 0; match < cursor.offset && 380 | line.text.charAt(match) == prev.text.charAt(match); match++); 381 | if (cursor.offset > match) 382 | cursordiff = line.text.length - prev.text.length; 383 | } 384 | select.setCursorPos(this.container, {node: line.from, offset: Math.max(0, cursor.offset + cursordiff)}); 385 | } 386 | // Cursor was in removed line, this is last new line. 387 | else if (cursor && (i == chain.length - 1) && cursor.node && cursor.node.parentNode != this.container) { 388 | select.setCursorPos(this.container, {node: line.from, offset: line.text.length}); 389 | } 390 | } 391 | 392 | // Anchor the chain in the DOM tree. 393 | this.linkChain(chain); 394 | return start; 395 | } 396 | }; 397 | -------------------------------------------------------------------------------- /war/js/util.js: -------------------------------------------------------------------------------- 1 | /* A few useful utility functions. */ 2 | 3 | var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent); 4 | var webkit = /AppleWebKit/.test(navigator.userAgent); 5 | 6 | // Capture a method on an object. 7 | function method(obj, name) { 8 | return function() {obj[name].apply(obj, arguments);}; 9 | } 10 | 11 | // The value used to signal the end of a sequence in iterators. 12 | var StopIteration = {toString: function() {return "StopIteration"}}; 13 | 14 | // Checks whether the argument is an iterator or a regular sequence, 15 | // turns it into an iterator. 16 | function iter(seq) { 17 | var i = 0; 18 | if (seq.next) return seq; 19 | else return { 20 | next: function() { 21 | if (i >= seq.length) throw StopIteration; 22 | else return seq[i++]; 23 | } 24 | }; 25 | } 26 | 27 | // Apply a function to each element in a sequence. 28 | function forEach(iter, f) { 29 | if (iter.next) { 30 | try {while (true) f(iter.next());} 31 | catch (e) {if (e != StopIteration) throw e;} 32 | } 33 | else { 34 | for (var i = 0; i < iter.length; i++) 35 | f(iter[i]); 36 | } 37 | } 38 | 39 | // Map a function over a sequence, producing an array of results. 40 | function map(iter, f) { 41 | var accum = []; 42 | forEach(iter, function(val) {accum.push(f(val));}); 43 | return accum; 44 | } 45 | 46 | // Create a predicate function that tests a string againsts a given 47 | // regular expression. 48 | function matcher(regexp){ 49 | return function(value){return regexp.test(value);}; 50 | } 51 | 52 | // Test whether a DOM node has a certain CSS class. Much faster than 53 | // the MochiKit equivalent, for some reason. 54 | function hasClass(element, className){ 55 | var classes = element.className; 56 | return classes && new RegExp("(^| )" + className + "($| )").test(classes); 57 | } 58 | 59 | // Insert a DOM node after another node. 60 | function insertAfter(newNode, oldNode) { 61 | var parent = oldNode.parentNode; 62 | parent.insertBefore(newNode, oldNode.nextSibling); 63 | return newNode; 64 | } 65 | 66 | function removeElement(node) { 67 | if (node.parentNode) 68 | node.parentNode.removeChild(node); 69 | } 70 | 71 | function clearElement(node) { 72 | while (node.firstChild) 73 | node.removeChild(node.firstChild); 74 | } 75 | 76 | // Check whether a node is contained in another one. 77 | function isAncestor(node, child) { 78 | while (child = child.parentNode) { 79 | if (node == child) 80 | return true; 81 | } 82 | return false; 83 | } 84 | 85 | // The non-breaking space character. 86 | var nbsp = "\u00a0"; 87 | var matching = {"{": "}", "[": "]", "(": ")", 88 | "}": "{", "]": "[", ")": "("}; 89 | 90 | // Standardize a few unportable event properties. 91 | function normalizeEvent(event) { 92 | if (!event.stopPropagation) { 93 | event.stopPropagation = function() {this.cancelBubble = true;}; 94 | event.preventDefault = function() {this.returnValue = false;}; 95 | } 96 | if (!event.stop) { 97 | event.stop = function() { 98 | this.stopPropagation(); 99 | this.preventDefault(); 100 | }; 101 | } 102 | 103 | if (event.type == "keypress") { 104 | event.code = (event.charCode == null) ? event.keyCode : event.charCode; 105 | event.character = String.fromCharCode(event.code); 106 | } 107 | return event; 108 | } 109 | 110 | // Portably register event handlers. 111 | function addEventHandler(node, type, handler, removeFunc) { 112 | function wrapHandler(event) { 113 | handler(normalizeEvent(event || window.event)); 114 | } 115 | if (typeof node.addEventListener == "function") { 116 | node.addEventListener(type, wrapHandler, false); 117 | if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);}; 118 | } 119 | else { 120 | node.attachEvent("on" + type, wrapHandler); 121 | if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);}; 122 | } 123 | } 124 | 125 | function nodeText(node) { 126 | return node.innerText || node.textContent || node.nodeValue || ""; 127 | } 128 | -------------------------------------------------------------------------------- /war/js/view.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $(function() { 3 | $("#embedText").dialog({ 4 | bgiframe: true, 5 | autoOpen: false, 6 | width: 700, 7 | height: 450, 8 | modal: true 9 | }); 10 | }); 11 | 12 | $("#embedLink").click(function(event) { 13 | $("#embedText").dialog('open'); 14 | }); 15 | 16 | $("#toggleLineNumbers").click(function(event) { 17 | if ($(".syntaxhighlighter").hasClass("nogutter")) { 18 | $(".syntaxhighlighter").removeClass("nogutter"); 19 | } else { 20 | $(".syntaxhighlighter").addClass("nogutter"); 21 | } 22 | }); 23 | }); -------------------------------------------------------------------------------- /war/nosuchscript.gtpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groovy web console - Script 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Groovy web console

17 | 18 | 19 | 20 | 30 | 31 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
subscribe to the feedSubscribe
to this
site
28 |
29 |
32 | 33 |
34 |

No such script!

35 | 36 |
37 | Actions 38 | Back to console 39 | View all recent scripts 40 |
41 |
42 | 43 | <% include '/WEB-INF/includes/about.gtpl' %> 44 | 45 | -------------------------------------------------------------------------------- /war/recentscripts.gtpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | Groovy web console - Recent scripts ${params.author ? "by " + params.author : ""} 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Groovy web console

17 | 18 | 19 | 20 | 30 | 31 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
subscribe to the feedSubscribe
to this
site
28 |
29 |
32 | 33 |

Recent scripts ${params.author ? "by " + params.author : ""} ${params.tag ? " with tag '" + params.tag + "'" : ""}

34 | 35 |
36 | Actions 37 | Back to console 38 | <% if (params.author || params.tag) { %> 39 | View all recent scripts 40 | <% } %> 41 |
42 | 43 | <% include "/recentscripts.groovy" %> 44 | 45 | -------------------------------------------------------------------------------- /war/view.gtpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | <% 4 | def script = request.script 5 | %> 6 | 7 | Groovy web console - ${script?.title ?: 'Untitled script'} 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 |

Groovy web console

39 | 40 |
41 | 42 | 43 | 53 | 54 |
44 | 45 | 46 | 47 | 48 | 49 | 50 |
subscribe to the feedSubscribe
to this
site
51 |
52 |
55 |
56 | 57 |

${script?.title ?: 'Untitled script'}

58 |
59 | 60 | Published ${new org.ocpsoft.prettytime.PrettyTime().format(script.dateCreated)} 61 | by 62 | <% 63 | if (script.author && script.author != 'Anonymous') { 64 | %> 65 | 66 | ${script.author} 67 | <% 68 | } else { 69 | %> 70 | Anonymous 71 | <% 72 | } 73 | if (script?.tags?.join()) { 74 | %> 75 | with tags 76 | <% 77 | script.tags.each { tag -> 78 | %> 79 | 80 | ${tag} 81 | <% 82 | } 83 | } 84 | %> 85 |
86 | 87 | 95 | 96 |
${script.script.replaceAll('<', '<')}
97 | 98 |
99 | 104 | 105 | 106 |
107 | 108 | --------------------------------------------------------------------------------