├── samples ├── doc ├── pages │ ├── doc │ ├── bar.op │ ├── img │ │ ├── test.jpg │ │ └── keplerproject.gif │ ├── foo.op │ ├── index.op │ ├── css │ │ └── doc.css │ └── test.op ├── blog │ ├── blog.ws │ ├── blog.db │ ├── head.jpg │ ├── header.xcf │ ├── blog_schema.mysql │ ├── blog_schema.sql │ ├── .htaccess │ ├── dump.lua │ ├── style.css │ └── blog_config.lua ├── hello │ ├── hello.ws │ └── hello.lua ├── songs │ ├── songs.ws │ ├── songs.cgi │ ├── songs.fcgi │ └── songs.lua ├── toycms │ ├── toycms.ws │ ├── templates │ │ ├── lablua │ │ │ ├── simple_post.html │ │ │ ├── index_short_info.html │ │ │ ├── layout.html │ │ │ ├── images │ │ │ │ ├── header.jpg │ │ │ │ └── xavante.png │ │ │ ├── list_pubs.html │ │ │ ├── section_menu-projects.html │ │ │ ├── section_menu-people.html │ │ │ ├── post.html │ │ │ ├── section_menu-publications.html │ │ │ ├── home.html │ │ │ └── styles │ │ │ │ ├── print.css │ │ │ │ ├── stylesheet2.css │ │ │ │ └── stylesheet1.css │ │ ├── blog │ │ │ ├── post_pages.html │ │ │ ├── images │ │ │ │ └── head.jpg │ │ │ ├── home.html │ │ │ ├── archive.html │ │ │ ├── home.xml │ │ │ ├── post.html │ │ │ ├── layout.html │ │ │ └── style.css │ │ └── aboutanything │ │ │ ├── images │ │ │ ├── head.jpg │ │ │ └── orbit.png │ │ │ ├── archive.html │ │ │ ├── home.html │ │ │ ├── home.xml │ │ │ ├── post.html │ │ │ ├── layout.html │ │ │ └── style.css │ ├── blog.db │ ├── lablua.db │ ├── toycms.db │ ├── index.lua │ ├── toycms_config.lua │ ├── populate_mysql_lablua.lua │ ├── toycms.cgi │ ├── toycms.fcgi │ ├── toycms_schema.sql │ ├── toycms_schema.mysql │ ├── dump.lua │ ├── .htaccess │ ├── admin_style.css │ ├── toycms_plugins.lua │ └── cached.diff ├── todo │ ├── todo.db │ ├── todo.sql │ ├── items.op │ ├── todo.op │ └── todo.ws ├── sproutcore │ ├── todo.db │ ├── static │ │ ├── sproutcore │ │ │ ├── datastore │ │ │ │ └── en │ │ │ │ │ └── 59bda761d63639cc5f5a4342ee678fada0d577cc │ │ │ │ │ └── stylesheet-packed.css │ │ │ ├── empty_theme │ │ │ │ └── en │ │ │ │ │ └── 21c3b7b16d7ef39d60d2651975590828812f3ad9 │ │ │ │ │ ├── javascript-packed.js │ │ │ │ │ └── stylesheet-packed.css │ │ │ ├── runtime │ │ │ │ └── en │ │ │ │ │ └── d9e5073e5a6d48c7c3c4e53ef7bf433a6f6ac61b │ │ │ │ │ └── stylesheet-packed.css │ │ │ ├── standard_theme │ │ │ │ └── en │ │ │ │ │ └── 52366532814d7f12ca549445e2e2a07c4b5f73d6 │ │ │ │ │ ├── javascript-packed.js │ │ │ │ │ ├── panels │ │ │ │ │ ├── overlay.png │ │ │ │ │ ├── left-edge.png │ │ │ │ │ ├── top-edge.png │ │ │ │ │ ├── bottom-edge.png │ │ │ │ │ ├── right-edge.png │ │ │ │ │ ├── background-fat.jpg │ │ │ │ │ ├── background-thin.jpg │ │ │ │ │ ├── top-left-corner.png │ │ │ │ │ ├── top-right-corner.png │ │ │ │ │ ├── bottom-left-corner.png │ │ │ │ │ └── bottom-right-corner.png │ │ │ │ │ └── images │ │ │ │ │ ├── sc-theme-repeat-x.png │ │ │ │ │ ├── sc-theme-ysprite.png │ │ │ │ │ └── sc-toolbar-view.png │ │ │ ├── bootstrap │ │ │ │ └── en │ │ │ │ │ └── fd3ef3775313919c9d16dc2f2129aae8549dcbfa │ │ │ │ │ ├── setup_body_class_names.js │ │ │ │ │ └── javascript.js │ │ │ ├── foundation │ │ │ │ └── en │ │ │ │ │ └── bcfdf5ca1125ccb312799938d8f09a81676f5db0 │ │ │ │ │ ├── blank.gif │ │ │ │ │ ├── images │ │ │ │ │ └── sproutcore-logo.png │ │ │ │ │ ├── stylesheet.css │ │ │ │ │ └── stylesheet-packed.css │ │ │ ├── desktop │ │ │ │ └── en │ │ │ │ │ └── 1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66 │ │ │ │ │ └── images │ │ │ │ │ ├── icons │ │ │ │ │ ├── shared.png │ │ │ │ │ ├── mini_222222.png │ │ │ │ │ ├── mini_454545.png │ │ │ │ │ ├── mini_888888.png │ │ │ │ │ └── mini_ffffff.png │ │ │ │ │ ├── panels │ │ │ │ │ ├── sprite-x.png │ │ │ │ │ └── sprite-y.png │ │ │ │ │ └── standard_fade │ │ │ │ │ ├── 000000.png │ │ │ │ │ └── ffffff.png │ │ │ └── en │ │ │ │ └── 160fa25cc6d7adb0a0a201d11668361e03d8e9cc │ │ │ │ └── javascript.js │ │ └── todos │ │ │ └── en │ │ │ └── ee972277c11ed2d7cf0765e9c5b9738575b9248d │ │ │ ├── index.html │ │ │ └── javascript.js │ ├── todo.sql │ └── todo.lua ├── op.ws ├── routes │ └── hello.lua └── README ├── test ├── books.db ├── test_model.lua ├── books.sql ├── test_sql.lua └── test_routes.lua ├── doc └── us │ ├── orbit.png │ ├── license.md │ ├── makedoc.lua │ ├── pages.md │ ├── license.html │ ├── doc.css │ └── pages.html ├── src ├── launchers │ ├── op.cgi │ ├── op.fcgi │ └── orbit └── orbit │ ├── ophandler.lua │ ├── cache.lua │ ├── pages.lua │ └── routes.lua ├── Makefile ├── rockspec ├── orbit-2.0rc1-1.rockspec ├── orbit-2.0-1.rockspec ├── orbit-2.0.1-1.rockspec ├── orbit-cvs-1.rockspec ├── orbit-2.0.2-1.rockspec ├── orbit-2.1.0-1.rockspec ├── orbit-cvs-2.rockspec ├── orbit-2.2.0-1.rockspec ├── orbit-2.2.1-1.rockspec ├── orbit-2.2.2-1.rockspec ├── orbit-2.2.3-1.rockspec └── orbit-2.2.4-1.rockspec ├── Makefile.win ├── configure └── README /samples/doc: -------------------------------------------------------------------------------- 1 | ../doc -------------------------------------------------------------------------------- /samples/pages/doc: -------------------------------------------------------------------------------- 1 | ../../doc -------------------------------------------------------------------------------- /samples/blog/blog.ws: -------------------------------------------------------------------------------- 1 | return require "blog" 2 | 3 | -------------------------------------------------------------------------------- /samples/hello/hello.ws: -------------------------------------------------------------------------------- 1 | return require("hello") 2 | -------------------------------------------------------------------------------- /samples/songs/songs.ws: -------------------------------------------------------------------------------- 1 | return require("songs") 2 | -------------------------------------------------------------------------------- /samples/toycms/toycms.ws: -------------------------------------------------------------------------------- 1 | return require("toycms") 2 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/simple_post.html: -------------------------------------------------------------------------------- 1 | $body 2 | 3 | -------------------------------------------------------------------------------- /test/books.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/test/books.db -------------------------------------------------------------------------------- /doc/us/orbit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/doc/us/orbit.png -------------------------------------------------------------------------------- /samples/blog/blog.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/blog/blog.db -------------------------------------------------------------------------------- /samples/blog/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/blog/head.jpg -------------------------------------------------------------------------------- /samples/todo/todo.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/todo/todo.db -------------------------------------------------------------------------------- /samples/blog/header.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/blog/header.xcf -------------------------------------------------------------------------------- /samples/toycms/blog.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/blog.db -------------------------------------------------------------------------------- /samples/toycms/lablua.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/lablua.db -------------------------------------------------------------------------------- /samples/toycms/toycms.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/toycms.db -------------------------------------------------------------------------------- /samples/pages/bar.op: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env op.cgi 2 | 3 |

This is bar, and you passed $web|input|msg!

4 | -------------------------------------------------------------------------------- /samples/pages/img/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/pages/img/test.jpg -------------------------------------------------------------------------------- /samples/sproutcore/todo.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/todo.db -------------------------------------------------------------------------------- /samples/toycms/templates/blog/post_pages.html: -------------------------------------------------------------------------------- 1 |
2 | $markdown_body 3 |
4 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/index_short_info.html: -------------------------------------------------------------------------------- 1 |

$title

2 | $abstract -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/datastore/en/59bda761d63639cc5f5a4342ee678fada0d577cc/stylesheet-packed.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/empty_theme/en/21c3b7b16d7ef39d60d2651975590828812f3ad9/javascript-packed.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/runtime/en/d9e5073e5a6d48c7c3c4e53ef7bf433a6f6ac61b/stylesheet-packed.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/empty_theme/en/21c3b7b16d7ef39d60d2651975590828812f3ad9/stylesheet-packed.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/javascript-packed.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/toycms/index.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local toycms = require "toycms" 4 | 5 | return toycms.run 6 | -------------------------------------------------------------------------------- /samples/toycms/toycms_config.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/toycms_config.lua -------------------------------------------------------------------------------- /samples/pages/img/keplerproject.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/pages/img/keplerproject.gif -------------------------------------------------------------------------------- /samples/toycms/populate_mysql_lablua.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/populate_mysql_lablua.lua -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/layout.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/lablua/layout.html -------------------------------------------------------------------------------- /samples/toycms/templates/blog/images/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/blog/images/head.jpg -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/lablua/images/header.jpg -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/images/xavante.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/lablua/images/xavante.png -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/list_pubs.html: -------------------------------------------------------------------------------- 1 | $import{ "index_view" } 2 | 3 |

$title

4 | 5 | $show_posts{ template = "simple_post.html" } 6 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/images/head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/aboutanything/images/head.jpg -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/images/orbit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/toycms/templates/aboutanything/images/orbit.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/bootstrap/en/fd3ef3775313919c9d16dc2f2129aae8549dcbfa/setup_body_class_names.js: -------------------------------------------------------------------------------- 1 | if(SC.setupBodyClassNames){SC.setupBodyClassNames()}; -------------------------------------------------------------------------------- /samples/todo/todo.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE todo_list 2 | ("id" INTEGER PRIMARY KEY NOT NULL, 3 | "title" VARCHAR(255) DEFAULT "", 4 | "done" BOOLEAN DEFAULT "f", 5 | "created_at" DATETIME); 6 | -------------------------------------------------------------------------------- /samples/sproutcore/todo.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE todo_list 2 | ("id" INTEGER PRIMARY KEY NOT NULL, 3 | "description" VARCHAR(255) DEFAULT "", 4 | "is_done" BOOLEAN DEFAULT "f", 5 | "created_at" DATETIME); 6 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/blank.gif -------------------------------------------------------------------------------- /samples/toycms/toycms.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua51 2 | 3 | local lfs = require "lfs" 4 | 5 | lfs.chdir("/path/to/toycms") 6 | 7 | local wscgi = require "wsapi.cgi" 8 | 9 | local toycms = require "toycms" 10 | 11 | wscgi.run(toycms.run) 12 | 13 | -------------------------------------------------------------------------------- /samples/toycms/toycms.fcgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua51 2 | 3 | local lfs = require "lfs" 4 | 5 | lfs.chdir("/path/to/toycms") 6 | 7 | local wsfcgi = require "wsapi.fastcgi" 8 | 9 | local toycms = require"toycms" 10 | 11 | wsfcgi.run(toycms.run) 12 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/section_menu-projects.html: -------------------------------------------------------------------------------- 1 | $import{ "index_view" } 2 | 4 |
5 |
6 |

$title

7 | 8 | $show_posts 9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /samples/songs/songs.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local lfs = require "lfs" 4 | 5 | lfs.chdir("/home/mascarenhas/work/orbit/samples/songs") 6 | 7 | local wscgi = require "wsapi.cgi" 8 | 9 | local songs = require "songs" 10 | 11 | wscgi.run(songs.run) 12 | 13 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/shared.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/shared.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/overlay.png -------------------------------------------------------------------------------- /samples/songs/songs.fcgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local lfs = require "lfs" 4 | 5 | lfs.chdir("/home/mascarenhas/work/orbit/samples/songs") 6 | 7 | local wsfcgi = require "wsapi.fastcgi" 8 | 9 | local sontgs = require "songs" 10 | 11 | wsfcgi.run(songs.run) 12 | 13 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/panels/sprite-x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/panels/sprite-x.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/panels/sprite-y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/panels/sprite-y.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/left-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/left-edge.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-edge.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_222222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_222222.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_454545.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_454545.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_888888.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_888888.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_ffffff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/icons/mini_ffffff.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/images/sproutcore-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/images/sproutcore-logo.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-edge.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/right-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/right-edge.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/standard_fade/000000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/standard_fade/000000.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/standard_fade/ffffff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/desktop/en/1425eba6eeb45c8823b8dc7cdfcea8aeffe59a66/images/standard_fade/ffffff.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/background-fat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/background-fat.jpg -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-theme-repeat-x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-theme-repeat-x.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-theme-ysprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-theme-ysprite.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-toolbar-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/images/sc-toolbar-view.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/background-thin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/background-thin.jpg -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-left-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-left-corner.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-right-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/top-right-corner.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-left-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-left-corner.png -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-right-corner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keplerproject/orbit/HEAD/samples/sproutcore/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/panels/bottom-right-corner.png -------------------------------------------------------------------------------- /samples/todo/items.op: -------------------------------------------------------------------------------- 1 | $lua{[[ 2 | items = todo_list:find_all{ order = "created_at desc" } 3 | ]]} 4 | $if{$items|1}[==[ 5 | $items[[ 6 |
  • $title 7 | Remove
  • 8 | ]] 9 | ]==],[==[Nothing to do!]==] 10 | -------------------------------------------------------------------------------- /samples/pages/foo.op: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env op.cgi 2 | 3 | 4 | 5 |

    Hello Cosmo!

    6 |

    I am in $web|real_path, and the script is 7 | $web|script_name.

    8 | $lua{[[ 9 | if not web.input.msg then 10 | web.input.msg = "nothing" 11 | end 12 | ]]} 13 |

    You passed: $web|input|msg.

    14 | $include{ "bar.op" } 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/section_menu-people.html: -------------------------------------------------------------------------------- 1 | $import{ "section_list" } 2 | 3 | 5 |
    6 |
    7 |

    $title

    8 | 9 | $section_list{ include_tags = { "people-%" }, 10 | template = "list_pubs.html" } 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/post.html: -------------------------------------------------------------------------------- 1 | $import{ "index_view" } 2 | 3 | 9 |
    10 |
    11 | 12 | $body 13 | 14 |
    15 |
    16 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/section_menu-publications.html: -------------------------------------------------------------------------------- 1 | $import{ "section_list" } 2 | 3 | 5 |
    6 |
    7 |

    $title

    8 | 9 | $section_list{ include_tags = { "pubs-%" }, 10 | template = "list_pubs.html" } 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /samples/op.ws: -------------------------------------------------------------------------------- 1 | -- Orbit pages launcher, extracts script to launch 2 | 3 | local common = require "wsapi.common" 4 | 5 | local function op_loader(wsapi_env) 6 | common.normalize_paths(wsapi_env, nil, "op.ws") 7 | local app = wsapi.common.load_isolated_launcher(wsapi_env.PATH_TRANSLATED, "orbit.pages") 8 | return app(wsapi_env) 9 | end 10 | 11 | return op_loader 12 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/home.html: -------------------------------------------------------------------------------- 1 | $import{"index_view"} 2 | 3 | $show_posts{ include_tags = {"blog-%"}, count = 7 }[[ 4 |
    5 | $if_new_date[=[

    $date_string

    ]=] 6 |

    $title

    7 | $markdown_body 8 |

    Published at $hour_padded:$minute_padded | Comments ($n_comments)

    9 |
    10 | ]] 11 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/archive.html: -------------------------------------------------------------------------------- 1 | $import{"index_view"} 2 | 3 | $show_posts{ archive = true, include_tags = {"blog-%"}, count = 7 }[[ 4 |
    5 | $if_new_date[=[

    $date_string

    ]=] 6 |

    $title

    7 | $markdown_body 8 |

    Published at $hour_padded:$minute_padded | Comments ($n_comments)

    9 |
    10 | ]] 11 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/home.html: -------------------------------------------------------------------------------- 1 | $import{ "index_view" } 2 | 3 | 9 |
    10 |
    11 | 12 | $show_posts{ include_tags = { "home" }, count = 1, template = "simple_post.html" } 13 | 14 |
    15 |
    16 | -------------------------------------------------------------------------------- /src/launchers/op.cgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/lua 2 | 3 | -- Orbit pages launcher, extracts script to launch 4 | -- from SCRIPT_FILENAME/PATH_TRANSLATED 5 | 6 | local common = require "wsapi.common" 7 | local cgi = require "wsapi.cgi" 8 | 9 | local ok, err = pcall(require, "cosmo") 10 | 11 | if not ok then 12 | io.stderr:write("Cosmo not loaded:\n" .. err .. "\n\nPlease install cosmo with LuaRocks\n") 13 | os.exit(1) 14 | end 15 | 16 | local op = require "orbit.pages" 17 | 18 | local arg_filename = (...) 19 | 20 | local function op_loader(wsapi_env) 21 | common.normalize_paths(wsapi_env, arg_filename, "op.cgi", { "SCRIPT_FILENAME", "PATH_TRANSLATED" }) 22 | return op.run(wsapi_env) 23 | end 24 | 25 | cgi.run(op_loader) 26 | -------------------------------------------------------------------------------- /samples/routes/hello.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local orbit = require "orbit" 4 | local R = require "orbit.routes" 5 | 6 | local hello = orbit.new() 7 | 8 | hello:dispatch_get(function (web) 9 | return string.format('

    Welcome to %s!

    ', web.real_path) 10 | end, R'/') 11 | 12 | hello:dispatch_get(function(web, params) 13 | return string.format('Hello %s!', params.name) 14 | end, R'/hello/:name') 15 | 16 | hello:dispatch_get(function(web, params) 17 | return string.format('Hi %s!', params.splat[1]) 18 | end, R'/hi/*') 19 | 20 | hello:dispatch_get(function(web, params) 21 | return string.format('Hey %s!', params.name or "stranger") 22 | end, R'/hey/?:name?') 23 | 24 | return hello 25 | -------------------------------------------------------------------------------- /samples/blog/blog_schema.mysql: -------------------------------------------------------------------------------- 1 | CREATE TABLE blog_post 2 | (`id` INTEGER PRIMARY KEY NOT NULL, 3 | `title` VARCHAR(255) DEFAULT NULL, 4 | `body` TEXT DEFAULT NULL, 5 | `n_comments` INTEGER DEFAULT NULL, 6 | `published_at` DATETIME DEFAULT NULL); 7 | 8 | CREATE TABLE blog_comment 9 | (`id` INTEGER PRIMARY KEY NOT NULL, 10 | `post_id` INTEGER DEFAULT NULL, 11 | `author` VARCHAR(255) DEFAULT NULL, 12 | `email` VARCHAR(255) DEFAULT NULL, 13 | `url` VARCHAR(255) DEFAULT NULL, 14 | `body` TEXT DEFAULT NULL, 15 | `created_at` DATETIME DEFAULT NULL); 16 | 17 | CREATE TABLE blog_page 18 | (`id` INTEGER PRIMARY KEY NOT NULL, 19 | `title` VARCHAR(30) DEFAULT NULL, 20 | `body` TEXT DEFAULT NULL); 21 | -------------------------------------------------------------------------------- /samples/blog/blog_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE blog_post 2 | ("id" INTEGER PRIMARY KEY NOT NULL, 3 | "title" VARCHAR(255) DEFAULT NULL, 4 | "body" TEXT DEFAULT NULL, 5 | "n_comments" INTEGER DEFAULT NULL, 6 | "published_at" DATETIME DEFAULT NULL); 7 | 8 | CREATE TABLE blog_comment 9 | ("id" INTEGER PRIMARY KEY NOT NULL, 10 | "post_id" INTEGER DEFAULT NULL, 11 | "author" VARCHAR(255) DEFAULT NULL, 12 | "email" VARCHAR(255) DEFAULT NULL, 13 | "url" VARCHAR(255) DEFAULT NULL, 14 | "body" TEXT DEFAULT NULL, 15 | "created_at" DATETIME DEFAULT NULL); 16 | 17 | CREATE TABLE blog_page 18 | ("id" INTEGER PRIMARY KEY NOT NULL, 19 | "title" VARCHAR(30) DEFAULT NULL, 20 | "body" TEXT DEFAULT NULL); 21 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/archive.html: -------------------------------------------------------------------------------- 1 | $import{"index_view"} 2 | 3 | $show_posts{ include_tags = {"blog-%"}, count = 7 }[[ 4 |

    $date_string

    5 |
    6 |

    $title

    7 |
    8 |
    9 | $markdown_body 10 |
    11 |
    12 |
    13 | 16 | | 17 | | Comments ($n_comments) 18 |
    19 |
    20 | ]] 21 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/home.html: -------------------------------------------------------------------------------- 1 | $import{"index_view"} 2 | 3 | $show_posts{ include_tags = {"blog-%"}, count = 7 }[[ 4 |

    $date_string

    5 |
    6 |

    $title

    7 |
    8 |
    9 | $markdown_body 10 |
    11 |
    12 |
    13 | 16 | | 17 | | Comments ($n_comments) 18 |
    19 |
    20 | ]] 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # $Id: Makefile,v 1.4 2008/04/04 19:52:07 mascarenhas Exp $ 2 | 3 | include config 4 | 5 | all: 6 | 7 | config: 8 | touch config 9 | 10 | install: 11 | mkdir -p $(LUA_DIR) 12 | cp src/orbit.lua $(LUA_DIR) 13 | mkdir -p $(LUA_DIR)/orbit 14 | cp src/orbit/model.lua $(LUA_DIR)/orbit 15 | cp src/orbit/cache.lua $(LUA_DIR)/orbit 16 | cp src/orbit/pages.lua $(LUA_DIR)/orbit 17 | cp src/orbit/ophandler.lua $(LUA_DIR)/orbit 18 | mkdir -p $(BIN_DIR) 19 | cp src/launchers/orbit $(BIN_DIR) 20 | if [ -f ./wsapi/Makefile ]; then \ 21 | cd wsapi && make install; \ 22 | fi 23 | 24 | install-rocks: install 25 | mkdir -p $(PREFIX)/samples 26 | cp -r samples/* $(PREFIX)/samples 27 | mkdir -p $(PREFIX)/doc 28 | cp -r doc/* $(PREFIX)/doc 29 | mkdir -p $(PREFIX)/test 30 | cp -r test/* $(PREFIX)/test 31 | 32 | clean: 33 | -------------------------------------------------------------------------------- /rockspec/orbit-2.0rc1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.0rc1-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 'wsapi 1.0rc1', 'luafilesystem 1.4.1rc1', 'cosmo 8.04.14' } 16 | 17 | source = { 18 | url = "http://orbit.luaforge.net/orbit-2.0rc1.tar.gz", 19 | } 20 | 21 | build = { 22 | type = "make", 23 | build_pass = true, 24 | install_target = "install-rocks", 25 | install_variables = { 26 | PREFIX = "$(PREFIX)", 27 | LUA_BIN = "/usr/bin/env lua", 28 | LUA_DIR = "$(LUADIR)", 29 | BIN_DIR = "$(BINDIR)" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Makefile.win: -------------------------------------------------------------------------------- 1 | # $Id: Makefile.win,v 1.7 2008/07/31 18:55:46 mascarenhas Exp $ 2 | 3 | LUA_DIR= c:\lua5.1\lua 4 | BIN_DIR= c:\lua5.1\bin 5 | 6 | all: 7 | 8 | install: 9 | IF NOT EXIST "$(LUA_DIR)\orbit" mkdir "$(LUA_DIR)\orbit" 10 | copy src\orbit.lua "$(LUA_DIR)" 11 | copy src\model.lua "$(LUA_DIR)\orbit" 12 | copy src\cache.lua "$(LUA_DIR)\orbit" 13 | copy src\pages.lua "$(LUA_DIR)\orbit" 14 | copy src\ophandler.lua "$(LUA_DIR)\orbit" 15 | IF NOT EXIST "$(BIN_DIR)" mkdir "$(BIN_DIR)" 16 | copy src\orbit "$(BIN_DIR)" 17 | 18 | install-rocks: install 19 | IF NOT EXIST "$(PREFIX)\samples" mkdir "$(PREFIX)\samples" 20 | IF NOT EXIST "$(PREFIX)\doc" mkdir "$(PREFIX)\doc" 21 | IF NOT EXIST "$(PREFIX)\test" mkdir "$(PREFIX)\test" 22 | xcopy /E samples "$(PREFIX)\samples\" 23 | xcopy /E doc "$(PREFIX)\doc\" 24 | xcopy /E test "$(PREFIX)\test\" 25 | 26 | clean: 27 | -------------------------------------------------------------------------------- /rockspec/orbit-2.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.0-1" 4 | 5 | source = { 6 | url = "http://luaforge.net/frs/download.php/3451/orbit-2.0.0.tar.gz", 7 | } 8 | 9 | description = { 10 | summary = "MVC for Lua Web Development", 11 | detailed = [[ 12 | Orbit is a library for developing web applications according to 13 | the Model-View-Controller paradigm in Lua. 14 | ]], 15 | license = "MIT/X11", 16 | homepage = "http://www.keplerproject.org/orbit" 17 | } 18 | 19 | dependencies = { 'wsapi >= 1.0', 'luafilesystem >= 1.4.1', 'cosmo >= 8.04.14' } 20 | 21 | build = { 22 | type = "make", 23 | build_pass = true, 24 | install_target = "install-rocks", 25 | install_variables = { 26 | PREFIX = "$(PREFIX)", 27 | LUA_BIN = "/usr/bin/env lua", 28 | LUA_DIR = "$(LUADIR)", 29 | BIN_DIR = "$(BINDIR)" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rockspec/orbit-2.0.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.0.1-1" 4 | 5 | source = { 6 | url = "http://luaforge.net/frs/download.php/3458/orbit-2.0.1.tar.gz", 7 | } 8 | 9 | description = { 10 | summary = "MVC for Lua Web Development", 11 | detailed = [[ 12 | Orbit is a library for developing web applications according to 13 | the Model-View-Controller paradigm in Lua. 14 | ]], 15 | license = "MIT/X11", 16 | homepage = "http://www.keplerproject.org/orbit" 17 | } 18 | 19 | dependencies = { 'wsapi >= 1.0', 'luafilesystem >= 1.4.1', 'cosmo >= 8.04.14' } 20 | 21 | build = { 22 | type = "make", 23 | build_pass = true, 24 | install_target = "install-rocks", 25 | install_variables = { 26 | PREFIX = "$(PREFIX)", 27 | LUA_BIN = "/usr/bin/env lua", 28 | LUA_DIR = "$(LUADIR)", 29 | BIN_DIR = "$(BINDIR)" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rockspec/orbit-cvs-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "cvs-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 'wsapi cvs', 'luafilesystem cvs', 'cosmo current' } 16 | 17 | source = { 18 | url = "cvs://:pserver:anonymous@cvs.luaforge.net:/cvsroot/orbit", 19 | cvs_tag = "HEAD" 20 | } 21 | 22 | build = { 23 | type = "make", 24 | build_pass = true, 25 | install_target = "install-rocks", 26 | install_variables = { 27 | PREFIX = "$(PREFIX)", 28 | LUA_BIN = "/usr/bin/env lua", 29 | LUA_DIR = "$(LUADIR)", 30 | BIN_DIR = "$(BINDIR)" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /samples/README: -------------------------------------------------------------------------------- 1 | This folder contains several sample Orbit applications, from trivial 2 | to quite sophisticated: 3 | 4 | hello The traditional "Hello World" 5 | songs A simple song list formatted with Cosmo 6 | todo An AJAX todo list, using both straight Orbit (todo.ws) 7 | and Orbit Pages (todo.op) 8 | pages Simple Orbit Pages examples 9 | blog A simple blog with comments 10 | toycms A simple CMS with posts, categories, moderated comments, 11 | and an admin interface 12 | 13 | It also has a op.ws Orbit pages launcher that can be used to 14 | launch .op files without having this extension configured in 15 | your web server. For example, if you put op.ws in your document 16 | root and go to http://server/op.ws/foo/bar.op op.ws will look 17 | for a file foo/bar.op in your document root and process it using 18 | Orbit Pages. 19 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/home.xml: -------------------------------------------------------------------------------- 1 | 2 | $import{"index_view"} 3 | 4 | Orbit Blog 5 | tag:orbit-blog 6 | 7 | 8 | $show_posts{ include_tags = {"blog-%"}, count = 10 }[=[ 9 | 10 | $title 11 | 12 | tag:orbit-blog,$id 13 | 14 | $year-$month_padded-$day_padded{}T$hour_padded:$minute_padded:00Z 15 | $year-$month_padded-$day_padded{}T$hour_padded:$minute_padded:00Z 16 | 17 | 18 | 19 | 20 | 21 | 22 | ]=] 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/home.xml: -------------------------------------------------------------------------------- 1 | 2 | $import{"index_view"} 3 | 4 | Orbit Blog 5 | tag:orbit-blog 6 | 7 | 8 | $show_posts{ include_tags = {"blog-%"}, count = 10 }[=[ 9 | 10 | $title 11 | 12 | tag:orbit-blog,$id 13 | 14 | $year-$month_padded-$day_padded{}T$hour_padded:$minute_padded:00Z 15 | $year-$month_padded-$day_padded{}T$hour_padded:$minute_padded:00Z 16 | 17 | 18 | 19 | 20 | 21 | 22 | ]=] 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/orbit/ophandler.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- Xavante Orbit pages handler 3 | -- 4 | -- Author: Fabio Mascarenhas 5 | -- 6 | ----------------------------------------------------------------------------- 7 | 8 | local wsapi = require "wsapi" 9 | local wsxav = require "wsapi.xavante" 10 | local wscom = require "wsapi.common" 11 | 12 | ------------------------------------------------------------------------------- 13 | -- Returns the Orbit Pages handler 14 | ------------------------------------------------------------------------------- 15 | local function makeHandler (diskpath, params) 16 | params = setmetatable({ modname = params.modname or "orbit.pages" }, { __index = params or {} }) 17 | local op_loader = wscom.make_isolated_launcher(params) 18 | return wsxav.makeHandler(op_loader, nil, diskpath) 19 | end 20 | 21 | return { makeHandler = makeHandler } 22 | -------------------------------------------------------------------------------- /rockspec/orbit-2.0.2-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.0.2-1" 4 | 5 | source = { 6 | url = "http://luaforge.net/frs/download.php/3975/orbit-2.0.2.tar.gz", 7 | } 8 | 9 | description = { 10 | summary = "MVC for Lua Web Development", 11 | detailed = [[ 12 | Orbit is a library for developing web applications according to 13 | the Model-View-Controller paradigm in Lua. 14 | ]], 15 | license = "MIT/X11", 16 | homepage = "http://www.keplerproject.org/orbit" 17 | } 18 | 19 | dependencies = { 'wsapi >= 1.1', 'luafilesystem >= 1.4.2', 'cosmo >= 8.04.14' } 20 | 21 | build = { 22 | type = "module", 23 | modules = { 24 | orbit = "src/orbit.lua", 25 | ["orbit.model"] = "src/model.lua", 26 | ["orbit.pages"] = "src/pages.lua", 27 | ["orbit.cache"] = "src/cache.lua", 28 | ["orbit.ophandler"] = "src/ophandler.lua", 29 | }, 30 | copy_directories = { "doc", "samples", "test" } 31 | } 32 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $1 = "--help" ]; then 4 | echo "Usage: configure lua51" 5 | echo "where lua51 is the name of your Lua executable" 6 | exit 0 7 | fi 8 | 9 | echo "Trying to find where you installed Lua..." 10 | 11 | if [ $1 != "" ]; then 12 | lua=$1 13 | else 14 | lua="lua51" 15 | fi 16 | 17 | lua_bin=`which $lua` 18 | lua_bin_dir=`dirname $lua_bin` 19 | 20 | lua_root=`dirname $lua_bin_dir` 21 | 22 | if [ $lua_root != "" ]; then 23 | echo "Lua is in $lua_root" 24 | echo "Writing config" 25 | lua_share=$lua_root/share/lua/5.1 26 | lua_lib=$lua_root/lib/lua/5.1 27 | bin_dir=$lua_root/bin 28 | echo "LUA_DIR= $lua_share" > config 29 | echo "BIN_DIR= $bin_dir" >> config 30 | echo "LUA_LIBDIR= $lua_lib" >> config 31 | echo "Now run 'make && sudo make install'" 32 | else 33 | echo "Lua not found, please install Lua 5.1 (and put in your PATH)" 34 | fi 35 | 36 | if [ -f ./wsapi/configure ]; then 37 | echo "Configuring wsapi..." 38 | cd wsapi 39 | ./configure $1 40 | fi 41 | -------------------------------------------------------------------------------- /rockspec/orbit-2.1.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.1.0-1" 4 | 5 | source = { 6 | url = "http://cloud.github.com/downloads/keplerproject/orbit/orbit-2.1.0.tar.gz", 7 | } 8 | 9 | description = { 10 | summary = "MVC for Lua Web Development", 11 | detailed = [[ 12 | Orbit is a library for developing web applications according to 13 | the Model-View-Controller paradigm in Lua. 14 | ]], 15 | license = "MIT/X11", 16 | homepage = "http://www.keplerproject.org/orbit" 17 | } 18 | 19 | dependencies = { 'luafilesystem >= 1.5.0' } 20 | 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | orbit = "src/orbit.lua", 25 | ["orbit.model"] = "src/orbit/model.lua", 26 | ["orbit.pages"] = "src/orbit/pages.lua", 27 | ["orbit.cache"] = "src/orbit/cache.lua", 28 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 29 | }, 30 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 31 | copy_directories = { "doc", "samples", "test" } 32 | } 33 | -------------------------------------------------------------------------------- /rockspec/orbit-cvs-2.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "cvs-2" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 'luafilesystem >= 1.5.0', 'lpeg >= 0.9' } 16 | 17 | source = { 18 | url = "git://github.com/keplerproject/orbit.git" 19 | } 20 | 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | orbit = "src/orbit.lua", 25 | ["orbit.model"] = "src/orbit/model.lua", 26 | ["orbit.pages"] = "src/orbit/pages.lua", 27 | ["orbit.cache"] = "src/orbit/cache.lua", 28 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 29 | ["orbit.routes"] = "src/orbit/routes.lua", 30 | }, 31 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 32 | copy_directories = { "doc", "samples", "test" } 33 | } 34 | -------------------------------------------------------------------------------- /rockspec/orbit-2.2.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.2.0-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 'luafilesystem >= 1.5.0', 'lpeg >= 0.9' } 16 | 17 | source = { 18 | url = "http://github.com/downloads/keplerproject/orbit/orbit-2.2.0.tar.gz" 19 | } 20 | 21 | build = { 22 | type = "builtin", 23 | modules = { 24 | orbit = "src/orbit.lua", 25 | ["orbit.model"] = "src/orbit/model.lua", 26 | ["orbit.pages"] = "src/orbit/pages.lua", 27 | ["orbit.cache"] = "src/orbit/cache.lua", 28 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 29 | ["orbit.routes"] = "src/orbit/routes.lua", 30 | }, 31 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 32 | copy_directories = { "doc", "samples", "test" } 33 | } 34 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/post.html: -------------------------------------------------------------------------------- 1 |
    2 |

    $title

    3 |

    $date_string

    4 | $markdown_body 5 |

    Published at $hour_padded:$minute_padded | Comments ($n_comments)

    6 | 7 | $if_comments[[ 8 |

    Comments

    9 | $comments[=[ 10 | $markdown_body 11 |

    Written by $author_link at $time_string

    12 |

    13 | ]=] 14 | ]] 15 | $if_comment_open[[ 16 |
    17 |

    18 | Name:
    19 |

    20 | Email:
    21 |

    22 | Site:
    23 |

    24 | Comments:
    25 | $if_error_comment[=[You must write something!]=] 26 |
    27 | *italics* **bold** [link](http://url)

    28 | 29 |

    30 |
    31 | ]] 32 |
    33 | -------------------------------------------------------------------------------- /rockspec/orbit-2.2.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.2.1-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 16 | 'luafilesystem >= 1.6.2', 17 | 'lpeg >= 0.12', 18 | 'wsapi-xavante >= 1.6', 19 | 'cosmo >= 13.01.30', 20 | 'lua >= 5.1, < 5.2', 21 | } 22 | 23 | source = { 24 | url = "git://github.com/keplerproject/orbit.git", 25 | tag = "v2.2.1", 26 | } 27 | 28 | build = { 29 | type = "builtin", 30 | modules = { 31 | orbit = "src/orbit.lua", 32 | ["orbit.model"] = "src/orbit/model.lua", 33 | ["orbit.pages"] = "src/orbit/pages.lua", 34 | ["orbit.cache"] = "src/orbit/cache.lua", 35 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 36 | ["orbit.routes"] = "src/orbit/routes.lua", 37 | }, 38 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 39 | copy_directories = { "doc", "samples", "test" } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /rockspec/orbit-2.2.2-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.2.2-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 16 | 'luafilesystem >= 1.6.2', 17 | 'lpeg >= 0.12', 18 | 'wsapi-xavante >= 1.6', 19 | 'cosmo >= 13.01.30', 20 | 'lua >= 5.1, < 5.2', 21 | } 22 | 23 | source = { 24 | url = "git://github.com/keplerproject/orbit.git", 25 | tag = "v2.2.2", 26 | } 27 | 28 | build = { 29 | type = "builtin", 30 | modules = { 31 | orbit = "src/orbit.lua", 32 | ["orbit.model"] = "src/orbit/model.lua", 33 | ["orbit.pages"] = "src/orbit/pages.lua", 34 | ["orbit.cache"] = "src/orbit/cache.lua", 35 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 36 | ["orbit.routes"] = "src/orbit/routes.lua", 37 | }, 38 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 39 | copy_directories = { "doc", "samples", "test" } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /rockspec/orbit-2.2.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.2.3-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 16 | 'luafilesystem >= 1.6.2', 17 | 'lpeg >= 0.12', 18 | 'wsapi-xavante >= 1.6', 19 | 'cosmo >= 13.01.30', 20 | 'lua >= 5.1, < 5.2', 21 | } 22 | 23 | source = { 24 | url = "git://github.com/keplerproject/orbit.git", 25 | tag = "v2.2.3", 26 | } 27 | 28 | build = { 29 | type = "builtin", 30 | modules = { 31 | orbit = "src/orbit.lua", 32 | ["orbit.model"] = "src/orbit/model.lua", 33 | ["orbit.pages"] = "src/orbit/pages.lua", 34 | ["orbit.cache"] = "src/orbit/cache.lua", 35 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 36 | ["orbit.routes"] = "src/orbit/routes.lua", 37 | }, 38 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 39 | copy_directories = { "doc", "samples", "test" } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /rockspec/orbit-2.2.4-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "Orbit" 2 | 3 | version = "2.2.4-1" 4 | 5 | description = { 6 | summary = "MVC for Lua Web Development", 7 | detailed = [[ 8 | Orbit is a library for developing web applications according to 9 | the Model-View-Controller paradigm in Lua. 10 | ]], 11 | license = "MIT/X11", 12 | homepage = "http://www.keplerproject.org/orbit" 13 | } 14 | 15 | dependencies = { 16 | 'luafilesystem >= 1.6.2', 17 | 'lpeg >= 0.12', 18 | 'wsapi-xavante >= 1.6', 19 | 'cosmo >= 13.01.30', 20 | 'lua >= 5.1, < 5.2', 21 | } 22 | 23 | source = { 24 | url = "git://github.com/keplerproject/orbit.git", 25 | tag = "v2.2.4", 26 | } 27 | 28 | build = { 29 | type = "builtin", 30 | modules = { 31 | orbit = "src/orbit.lua", 32 | ["orbit.model"] = "src/orbit/model.lua", 33 | ["orbit.pages"] = "src/orbit/pages.lua", 34 | ["orbit.cache"] = "src/orbit/cache.lua", 35 | ["orbit.ophandler"] = "src/orbit/ophandler.lua", 36 | ["orbit.routes"] = "src/orbit/routes.lua", 37 | }, 38 | install = { bin = { "src/launchers/orbit", "src/launchers/op.cgi", "src/launchers/op.fcgi" } }, 39 | copy_directories = { "doc", "samples", "test" } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /samples/songs/songs.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local orbit = require"orbit" 4 | local cosmo = require"cosmo" 5 | 6 | local songs = orbit.new() 7 | 8 | function songs.index(web) 9 | local songlist = { 10 | "Sgt. Pepper's Lonely Hearts Club Band", 11 | "With a Little Help from My Friends", 12 | "Lucy in the Sky with Diamonds", 13 | "Getting Better", 14 | "Fixing a Hole", 15 | "She's Leaving Home", 16 | "Being for the Benefit of Mr. Kite!", 17 | "Within You Without You", 18 | "When I'm Sixty-Four", 19 | "Lovely Rita", 20 | "Good Morning Good Morning", 21 | "Sgt. Pepper's Lonely Hearts Club Band (Reprise)", 22 | "A Day in the Life" 23 | } 24 | return songs.layout(songs.render_index({ songs = songlist })) 25 | end 26 | 27 | songs:dispatch_get(songs.index, "/") 28 | 29 | function songs.layout(inner_html) 30 | return html{ 31 | head{ title"Song List" }, 32 | body{ inner_html } 33 | } 34 | end 35 | 36 | orbit.htmlify(songs, "layout") 37 | 38 | songs.render_index = cosmo.compile[[ 39 |

    Songs

    40 | 41 | $songs[=[]=] 42 |
    $it
    43 | ]] 44 | 45 | return songs.run 46 | -------------------------------------------------------------------------------- /src/launchers/op.fcgi: -------------------------------------------------------------------------------- 1 | #!/usr/bin/lua 2 | 3 | -- Orbit pages launcher, extracts script to launch 4 | 5 | local common = require "wsapi.common" 6 | 7 | local ok, err = pcall(require, "wsapi.fastcgi") 8 | 9 | if not ok then 10 | io.stderr:write("WSAPI FastCGI not loaded:\n" .. err .. "\n\nPlease install wsapi-fcgi with LuaRocks\n") 11 | os.exit(1) 12 | end 13 | 14 | local ok, err = pcall(require, "cosmo") 15 | 16 | if not ok then 17 | io.stderr:write("Cosmo not loaded:\n" .. err .. "\n\nPlease install cosmo with LuaRocks\n") 18 | os.exit(1) 19 | end 20 | 21 | local ONE_HOUR = 60 * 60 22 | local ONE_DAY = 24 * ONE_HOUR 23 | 24 | local op_loader = common.make_isolated_launcher{ 25 | filename = nil, -- if you want to force the launch of a single script 26 | launcher = "op.fcgi", -- the name of this launcher 27 | modname = "orbit.pages", -- WSAPI application that processes the script 28 | reload = false, -- if you want to reload the application on every request 29 | period = ONE_HOUR, -- frequency of Lua state staleness checks 30 | ttl = ONE_DAY, -- time-to-live for Lua states 31 | vars = -- order of checking for the path of the script 32 | { "SCRIPT_FILENAME", 33 | "PATH_TRANSLATED" } 34 | } 35 | 36 | wsapi.fastcgi.run(op_loader) 37 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/styles/print.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | margin: 2em; 4 | padding: 0; 5 | font: 100% arial, hevetica, sans-serif; 6 | color: #000; 7 | background-color: #fff; 8 | } 9 | 10 | a { color: #000; text-decoration: none;} 11 | 12 | #header 13 | { 14 | border-bottom: 1px solid #999; 15 | } 16 | 17 | #header h1 18 | { 19 | color: #000; 20 | } 21 | 22 | #mainnav 23 | { 24 | display: none; 25 | } 26 | 27 | 28 | #menu 29 | { 30 | display: none; 31 | } 32 | 33 | #menu ul 34 | { 35 | margin-left: 0; 36 | padding-left: 0; 37 | list-style-type: none; 38 | line-height: 165%; 39 | } 40 | 41 | #contents p { line-height: 165%; } 42 | .blogentry { border-bottom: 1px solid #999; } 43 | 44 | .blogentry ul 45 | { 46 | list-style-type: none; 47 | text-align: right; 48 | margin: 1em 0; 49 | padding: 0; 50 | font-size: 95%; 51 | } 52 | 53 | .blogentry li 54 | { 55 | display: inline; 56 | padding: 0 0 0 7px; 57 | } 58 | 59 | .imagefloat 60 | { 61 | display: none; 62 | } 63 | 64 | #footer 65 | { 66 | clear: both; 67 | color: #000; 68 | text-align: right; 69 | padding: 5px; 70 | font-size: 90%; 71 | border-top: 1px solid #999; 72 | margin-top: 2em; 73 | } 74 | 75 | #skipmenu 76 | { 77 | display: none; 78 | } 79 | -------------------------------------------------------------------------------- /samples/blog/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AddHandler cgi-script .lua 5 | 6 | 7 | 8 | 9 | AddHandler fcgid-script .lua 10 | FCGIWrapper "/usr/bin/env wsapi.fcgi" .lua 11 | 12 | 13 | 14 | Deny from all 15 | Allow from none 16 | 17 | 18 | 19 | Allow from all 20 | Deny from none 21 | 22 | XSendFile on 23 | 24 | 25 | 26 | 27 | RewriteEngine on 28 | 29 | RewriteCond %{REQUEST_FILENAME} ^(.*)/blog\.lua$ 30 | RewriteCond %1/page_cache/index.html -f 31 | RewriteRule ^blog\.lua/?$ page_cache/index.html [L] 32 | 33 | RewriteCond %{REQUEST_FILENAME} ^(.*)/blog\.lua$ 34 | RewriteCond %1/page_cache/post-$1.html -f 35 | RewriteRule ^blog\.lua/post/(.+)$ page_cache/post-$1.html [L] 36 | 37 | RewriteCond %{REQUEST_FILENAME} ^(.*)/blog\.lua$ 38 | RewriteCond %1/page_cache/archive-$1-$2.html -f 39 | RewriteRule ^blog\.lua/archive/([^/]+)/([^/]+)$ page_cache/archive-$1-$2.html [L] 40 | 41 | RewriteCond %{REQUEST_FILENAME} ^(.*)/blog\.lua$ 42 | RewriteCond %1/page_cache/page-$1.html -f 43 | RewriteRule ^blog\.lua/page/(.+)$ page_cache/page-$1.html [L] 44 | 45 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/styles/stylesheet2.css: -------------------------------------------------------------------------------- 1 | #container 2 | { 3 | border: 1px solid #0000CC; 4 | } 5 | 6 | #mainnav 7 | { 8 | background-color: #0000CC; 9 | color: #CCCCFF; 10 | padding: 2px 0; 11 | margin-bottom: 22px; 12 | } 13 | 14 | #mainnav ul 15 | { 16 | margin: 0 0 0 20px; 17 | padding: 0; 18 | list-style-type: none; 19 | border-left: 1px solid #CCCCFF; 20 | } 21 | 22 | #mainnav li 23 | { 24 | display: inline; 25 | padding: 0 10px; 26 | border-right: 1px solid #CCCCFF; 27 | } 28 | 29 | #mainnav li a 30 | { 31 | text-decoration: none; 32 | color: #CCCCFF; 33 | } 34 | 35 | #mainnav li a:hover 36 | { 37 | text-decoration: none; 38 | color: #0000CC; 39 | background-color: #CCCCFF; 40 | } 41 | 42 | #menu ul 43 | { 44 | margin-left: 0; 45 | padding-left: 0; 46 | list-style-type: none; 47 | line-height: 165%; 48 | } 49 | 50 | .imagefloat 51 | { 52 | padding: 2px; 53 | border: 1px solid #0000CC; 54 | margin: 0 0 10px 10px; 55 | } 56 | 57 | .blogentry ul 58 | { 59 | list-style-type: none; 60 | text-align: right; 61 | margin: 1em 0; 62 | padding: 0; 63 | font-size: 95%; 64 | } 65 | 66 | .blogentry li 67 | { 68 | display: inline; 69 | padding: 0 0 0 7px; 70 | } 71 | 72 | #footer 73 | { 74 | background-color: #0000CC; 75 | padding: 5px; 76 | font-size: 90%; 77 | } 78 | 79 | 80 | -------------------------------------------------------------------------------- /samples/blog/dump.lua: -------------------------------------------------------------------------------- 1 | local luasql = require "luasql.sqlite3" 2 | local orm = require "orbit.model" 3 | 4 | local env = luasql() 5 | local conn = env:connect("blog.db") 6 | 7 | local mapper = orm.new("blog_", conn, "sqlite3") 8 | 9 | local tables = { "post", "comment", "page" } 10 | 11 | print [[ 12 | 13 | local luasql = require "luasql.mysql" 14 | local orm = require "orbit.model" 15 | 16 | local env = luasql() 17 | local conn = env:connect("blog", "root", "password") 18 | 19 | local mapper = orm.new("blog_", conn, "mysql") 20 | 21 | ]] 22 | 23 | local function serialize_prim(v) 24 | local type = type(v) 25 | if type == "string" then 26 | return string.format("%q", v) 27 | else 28 | return tostring(v) 29 | end 30 | end 31 | 32 | local function serialize(t) 33 | local fields = {} 34 | for k, v in pairs(t) do 35 | table.insert(fields, " [" .. string.format("%q", k) .. "] = " .. 36 | serialize_prim(v)) 37 | end 38 | return "{\n" .. table.concat(fields, ",\n") .. "}" 39 | end 40 | 41 | for _, tn in ipairs(tables) do 42 | print("\n -- Table " .. tn .. "\n") 43 | local t = mapper:new(tn) 44 | print("local t = mapper:new('" .. tn .. "')") 45 | local recs = t:find_all() 46 | for i, rec in ipairs(recs) do 47 | print("\n-- Record " .. i .. "\n") 48 | print("local rec = " .. serialize(rec)) 49 | print("rec = t:new(rec)") 50 | print("rec:save(true)") 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /samples/toycms/toycms_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE toycms_post 2 | ("id" INTEGER PRIMARY KEY NOT NULL, 3 | "title" VARCHAR(255) DEFAULT "", 4 | "body" TEXT DEFAULT "", 5 | "abstract" TEXT DEFAULT "", 6 | "image" VARCHAR(255) DEFAULT "", 7 | "external_url" VARCHAR(255) DEFAULT "", 8 | "comment_status" VARCHAR(30) DEFAULT "closed", 9 | "n_comments" INTEGER DEFAULT 0, 10 | "section_id" INTEGER DEFAULT NULL, 11 | "user_id" INTEGER DEFAULT NULL, 12 | "in_home" BOOLEAN DEFAULT "f", 13 | "published" BOOLEAN DEFAULT "f", 14 | "published_at" DATETIME DEFAULT NULL); 15 | 16 | CREATE TABLE toycms_comment 17 | ("id" INTEGER PRIMARY KEY NOT NULL, 18 | "post_id" INTEGER DEFAULT NULL, 19 | "author" VARCHAR(255) DEFAULT "", 20 | "email" VARCHAR(255) DEFAULT "", 21 | "url" VARCHAR(255) DEFAULT "", 22 | "body" TEXT DEFAULT "", 23 | "approved" BOOLEAN DEFAULT "f", 24 | "created_at" DATETIME DEFAULT NULL); 25 | 26 | CREATE TABLE toycms_section 27 | ("id" INTEGER PRIMARY KEY NOT NULL, 28 | "title" VARCHAR(255) DEFAULT "", 29 | "description" TEXT DEFAULT "", 30 | "tag" VARCHAR(255) DEFAULT ""); 31 | 32 | CREATE TABLE toycms_user 33 | ("id" INTEGER PRIMARY KEY NOT NULL, 34 | "login" VARCHAR(255) DEFAULT "", 35 | "password" VARCHAR(30) DEFAULT "", 36 | "name" VARCHAR(255) DEFAULT ""); 37 | -------------------------------------------------------------------------------- /samples/toycms/toycms_schema.mysql: -------------------------------------------------------------------------------- 1 | CREATE TABLE toycms_post 2 | (`id` INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, 3 | `title` VARCHAR(255) DEFAULT '', 4 | `body` TEXT DEFAULT '', 5 | `abstract` TEXT DEFAULT '', 6 | `image` VARCHAR(255) DEFAULT '', 7 | `external_url` VARCHAR(255) DEFAULT '', 8 | `comment_status` VARCHAR(30) DEFAULT 'closed', 9 | `n_comments` INTEGER DEFAULT 0, 10 | `section_id` INTEGER DEFAULT NULL, 11 | `user_id` INTEGER DEFAULT NULL, 12 | `in_home` BOOLEAN DEFAULT FALSE, 13 | `published` BOOLEAN DEFAULT FALSE, 14 | `published_at` DATETIME DEFAULT NULL); 15 | 16 | CREATE TABLE toycms_comment 17 | (`id` INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, 18 | `post_id` INTEGER DEFAULT NULL, 19 | `author` VARCHAR(255) DEFAULT '', 20 | `email` VARCHAR(255) DEFAULT '', 21 | `url` VARCHAR(255) DEFAULT '', 22 | `body` TEXT DEFAULT '', 23 | `approved` BOOLEAN DEFAULT FALSE, 24 | `created_at` DATETIME DEFAULT NULL); 25 | 26 | CREATE TABLE toycms_section 27 | (`id` INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, 28 | `title` VARCHAR(255) DEFAULT '', 29 | `description` TEXT DEFAULT '', 30 | `tag` VARCHAR(255) DEFAULT ''); 31 | 32 | CREATE TABLE toycms_user 33 | (`id` INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT, 34 | `login` VARCHAR(255) DEFAULT '', 35 | `password` VARCHAR(30) DEFAULT '', 36 | `name` VARCHAR(255) DEFAULT ''); 37 | -------------------------------------------------------------------------------- /samples/toycms/dump.lua: -------------------------------------------------------------------------------- 1 | local luasql = require "luasql.sqlite3" 2 | local orm = require "orbit.model" 3 | 4 | local args = { ... } 5 | 6 | local env = luasql() 7 | local conn = env:connect(args[1] .. ".db") 8 | 9 | local mapper = orm.new("toycms_", conn, "sqlite3") 10 | 11 | local tables = { "post", "comment", "user", "section" } 12 | 13 | print("local db = '" .. args[1] .. "'") 14 | 15 | print [[ 16 | 17 | local luasql = require "luasql.mysql" 18 | local orm = require "orbit.model" 19 | 20 | local env = luasql() 21 | local conn = env:connect(db, "root", "password") 22 | 23 | local mapper = orm.new("toycms_", conn, "mysql") 24 | 25 | ]] 26 | 27 | local function serialize_prim(v) 28 | local type = type(v) 29 | if type == "string" then 30 | return string.format("%q", v) 31 | else 32 | return tostring(v) 33 | end 34 | end 35 | 36 | local function serialize(t) 37 | local fields = {} 38 | for k, v in pairs(t) do 39 | table.insert(fields, " [" .. string.format("%q", k) .. "] = " .. 40 | serialize_prim(v)) 41 | end 42 | return "{\n" .. table.concat(fields, ",\n") .. "}" 43 | end 44 | 45 | for _, tn in ipairs(tables) do 46 | print("\n-- Table " .. tn .. "\n") 47 | local t = mapper:new(tn) 48 | print("local t = mapper:new('" .. tn .. "')") 49 | local recs = t:find_all() 50 | for i, rec in ipairs(recs) do 51 | print("\n-- Record " .. i .. "\n") 52 | print("local rec = " .. serialize(rec)) 53 | print("rec = t:new(rec)") 54 | print("rec:save(true)") 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/en/160fa25cc6d7adb0a0a201d11668361e03d8e9cc/javascript.js: -------------------------------------------------------------------------------- 1 | /* @license 2 | ========================================================================== 3 | SproutCore -- JavaScript Application Framework 4 | copyright 2006-2008, Sprout Systems, Inc. and contributors. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | DEALINGS IN THE SOFTWARE. 23 | 24 | For more information about SproutCore, visit http://www.sproutcore.com 25 | 26 | 27 | ========================================================================== 28 | @license */ 29 | if((typeof SC!=="undefined")&&SC&&SC.bundleDidLoad){SC.bundleDidLoad("sproutcore") 30 | }; -------------------------------------------------------------------------------- /test/test_model.lua: -------------------------------------------------------------------------------- 1 | #! /usr/bin lua 2 | -- Tests the examples from the Orbit reference 3 | local orbit = require "orbit" 4 | local luasql = require "luasql.sqlite3" 5 | module("test_model", package.seeall, orbit.new) 6 | 7 | mapper.conn = luasql.sqlite3():connect("books.db") 8 | mapper.driver = "sqlite3"; mapper.table_prefix = "" 9 | mapper.logging = false 10 | local books = test_model:model "books" 11 | 12 | local res = {} 13 | local count = books:find_all("", { fields = {"count(*)" } })[1]["count(*)"] 14 | print("There are " .. count .. " books in the database.") 15 | 16 | local example = [[ books:find(2) ]] 17 | print("Testing: " .. example) 18 | res = books:find(2) 19 | assert(res.title == "Gardens for dry climates") 20 | print("OK") 21 | 22 | example = [[ books:find_first("author = ? and year_pub > ?", { "John Doe", 1995, order = "year_pub asc" }) ]] 23 | print("Testing: " .. example) 24 | res = books:find_first("author = ? and year_pub > ?", { "John Doe", 1995, order = "year_pub asc" }) 25 | assert(res.title == "Halfway to nowhere") 26 | print("OK") 27 | 28 | example = [[ books:find_all("author = ? and year_pub > ?", { "John Doe", 1995, order = "year_pub asc", count = 5, fields = {"id", "title" } }) ]] 29 | print("Testing: " .. example) 30 | res = books:find_all("author = ? and year_pub > ?", { "John Doe", 1995, order = "year_pub asc", count = 5, fields = {"id", "title" } }) 31 | assert(#res == 5) 32 | print("OK") 33 | 34 | example = [[ books:find_all_by_author_or_author{ "John Doe", "Jane Doe", order = "year_pub asc" } ]] 35 | print("Testing: " .. example) 36 | res = books:find_all_by_author_or_author{ "John Doe", "Jane Doe", order = "year_pub asc" } 37 | assert(#res == 8) 38 | print("OK") 39 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/layout.html: -------------------------------------------------------------------------------- 1 | $import{"archive"} 2 | $import{"index_view"} 3 | 4 | 5 | 6 | 7 | Orbit Blog 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 | 23 | 48 |
    49 | $view 50 |
    51 | 54 |
    55 | 56 | 57 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/bootstrap/en/fd3ef3775313919c9d16dc2f2129aae8549dcbfa/javascript.js: -------------------------------------------------------------------------------- 1 | var SC=SC||{BUNDLE_INFO:{}};SC.browser=(function(){var c=navigator.userAgent.toLowerCase(); 2 | var a=(c.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1];var b={version:a,safari:(/webkit/).test(c)?a:0,opera:(/opera/).test(c)?a:0,msie:(/msie/).test(c)&&!(/opera/).test(c)?a:0,mozilla:(/mozilla/).test(c)&&!(/(compatible|webkit)/).test(c)?a:0,mobileSafari:(/apple.*mobile.*safari/).test(c)?a:0,windows:!!(/(windows)/).test(c),mac:!!((/(macintosh)/).test(c)||(/(mac os x)/).test(c)),language:((navigator.language||navigator.browserLanguage).split("-",1)[0])}; 3 | b.current=(b.msie)?"msie":(b.mozilla)?"mozilla":(b.safari)?"safari":(b.opera)?"opera":"unknown"; 4 | return b})();SC.bundleDidLoad=function(a){var b=this.BUNDLE_INFO[a];if(!b){b=this.BUNDLE_INFO[a]={} 5 | }b.loaded=true};SC.bundleIsLoaded=function(a){var b=this.BUNDLE_INFO[a];return b?!!b.loaded:false 6 | };SC.loadBundle=function(){throw"SC.loadBundle(): SproutCore is not loaded."};SC.setupBodyClassNames=function(){var d=document.body; 7 | var c,a,e,b,f;if(!d){return}c=SC.browser.current;a=(SC.browser.windows)?"windows":(SC.browser.mac)?"mac":"other-platform"; 8 | e=(document.documentElement.style.MozBoxShadow!==undefined)||(document.documentElement.style.webkitBoxShadow!==undefined)||(document.documentElement.style.oBoxShadow!==undefined)||(document.documentElement.style.boxShadow!==undefined); 9 | b=(document.documentElement.style.MozBorderRadius!==undefined)||(document.documentElement.style.webkitBorderRadius!==undefined)||(document.documentElement.style.oBorderRadius!==undefined)||(document.documentElement.style.borderRadius!==undefined); 10 | f=(d.className)?d.className.split(" "):[];if(e){f.push("box-shadow")}if(b){f.push("border-rad") 11 | }f.push(c);f.push(a);if(SC.browser.mobileSafari){f.push("mobile-safari")}d.className=f.join(" ") 12 | };if((typeof SC!=="undefined")&&SC&&SC.bundleDidLoad){SC.bundleDidLoad("sproutcore/bootstrap") 13 | }; -------------------------------------------------------------------------------- /samples/toycms/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AddHandler cgi-script .lua 5 | 6 | 7 | 8 | 9 | AddHandler fcgid-script .lua 10 | FCGIWrapper "/usr/bin/env wsapi.fcgi" .lua 11 | 12 | 13 | 14 | Deny from all 15 | Allow from none 16 | 17 | 18 | 19 | Allow from all 20 | Deny from none 21 | 22 | XSendFile on 23 | 24 | 25 | 26 | 27 | RewriteEngine on 28 | 29 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 30 | RewriteCond %1/page_cache/index.html -f 31 | RewriteRule ^(toycms|index)\.lua/?$ page_cache/index.html [L] 32 | 33 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 34 | RewriteCond %1/page_cache/post-$2.html -f 35 | RewriteRule ^(toycms|index)\.lua/post/(.+)$ page_cache/post-$2.html [L] 36 | 37 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 38 | RewriteCond %1/page_cache/archive-$2-$3.html -f 39 | RewriteRule ^(toycms|index)\.lua/archive/([^/]+)/([^/]+)$ page_cache/archive-$2-$3.html [L] 40 | 41 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 42 | RewriteCond %1/page_cache/section-$2.html -f 43 | RewriteRule ^(toycms|index)\.lua/section/(.+)$ page_cache/section-$2.html [L] 44 | 45 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 46 | RewriteCond %1/page_cache/index.xml -f 47 | RewriteRule ^(toycms|index)\.lua/xml$ page_cache/index.xml [L] 48 | 49 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 50 | RewriteCond %1/page_cache/post-$2.xml -f 51 | RewriteRule ^(toycms|index)\.lua/post/([^/]+)/xml$ page_cache/post-$2.xml [L] 52 | 53 | RewriteCond %{REQUEST_FILENAME} ^(.*)/(toycms|index)\.lua$ 54 | RewriteCond %1/page_cache/section-$2.xml -f 55 | RewriteRule ^(toycms|index)\.lua/section/([^/]+)$ page_cache/section-$2.xml [L] 56 | 57 | -------------------------------------------------------------------------------- /test/books.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "books" ( 2 | "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 3 | "title" TEXT, 4 | "author" TEXT, 5 | "year_pub" INTEGER, 6 | "created_at" TEXT, 7 | "updated_at" TEXT 8 | ); 9 | 10 | 11 | BEGIN TRANSACTION; 12 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('The secret diaries', 'John Doe', '2010', NULL, NULL); 13 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('Gardens for dry climates', 'Jane Doe', '1999', NULL, NULL); 14 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('DoeScript: a primer', 'O''Reilly', '2013', NULL, NULL); 15 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('There''s no life on Venus', 'Fred Bloggs', '2010', NULL, NULL); 16 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('Letters from Paris', 'Ann Onymous', '2011', NULL, NULL); 17 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('Halfway to nowhere', 'John Doe', '1996', NULL, NULL); 18 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('A test too far', 'John Doe', '1996', NULL, NULL); 19 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('The 1995 diaries', 'John Doe', '1996', NULL, NULL); 20 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('Counting sheep', 'John Doe', '1996', NULL, NULL); 21 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('An estranged husband', 'Jane Doe', '1996', NULL, NULL); 22 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('This year of plenty', 'Fred Bloggs', '1996', NULL, NULL); 23 | insert into books ("title", "author", "year_pub", "created_at", "updated_at") values ('A recursive glance', 'John Doe', '2012', NULL, NULL); 24 | COMMIT; 25 | 26 | -------------------------------------------------------------------------------- /test/test_sql.lua: -------------------------------------------------------------------------------- 1 | 2 | local model = require "orbit.model" 3 | 4 | local function build_query(sql, values) 5 | return model.condition_parser:match(sql, 1, function (field, op) 6 | return field .. op .. values[field] 7 | end) 8 | end 9 | 10 | local queries = { 11 | { 12 | from = [[node_term.term = term.id and term.vocabulary = vocabulary.id and term.name = ? and 13 | vocabulary.name = ?]], 14 | to = [[node_term.term = term.id and term.vocabulary = vocabulary.id and term.name = visibility and vocabulary.name = home]], 15 | values = { ["vocabulary.name"] = "home", ["term.name"] = "visibility" } 16 | }, 17 | { 18 | from = [[node_term.term = term.id and term.vocabulary = vocabulary.id and term.name = ? and 19 | vocabulary.name = ? and term.display_name is not null]], 20 | to = [[node_term.term = term.id and term.vocabulary = vocabulary.id and term.name = visibility and vocabulary.name = home and term.display_name is not null]], 21 | values = { ["vocabulary.name"] = "home", ["term.name"] = "visibility" } 22 | }, 23 | { 24 | from = [[node in ?]], 25 | to = [[node in foo]], 26 | values = { node = "foo" } 27 | }, 28 | { 29 | from = [[node_term.term!=term and term.vocabulary = vocabulary.id and term.name = ? and 30 | vocabulary.name = ? and term.display_name is not null]], 31 | to = [[node_term.term!=term and term.vocabulary = vocabulary.id and term.name = visibility and vocabulary.name = home and term.display_name is not null]], 32 | values = { ["vocabulary.name"] = "home", ["term.name"] = "visibility" } 33 | }, 34 | { 35 | from = [[node_term.term!=term and term.vocabulary = vocabulary.id and term.name =? and 36 | vocabulary.name = ? and term.display_name is not null]], 37 | to = [[node_term.term!=term and term.vocabulary = vocabulary.id and term.name =visibility and vocabulary.name = home and term.display_name is not null]], 38 | values = { ["vocabulary.name"] = "home", ["term.name"] = "visibility" } 39 | }, 40 | } 41 | 42 | for _, q in ipairs(queries) do 43 | if not (build_query(q.from, q.values) == q.to) then 44 | print(build_query(q.from, q.values)) 45 | end 46 | end 47 | 48 | -------------------------------------------------------------------------------- /samples/hello/hello.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local orbit = require "orbit" 4 | 5 | -- Orbit applications are usually modules, 6 | -- orbit.new does the necessary initialization 7 | 8 | module("hello", package.seeall, orbit.new) 9 | 10 | -- These are the controllers, each receives a web object 11 | -- that is the request/response, plus any extra captures from the 12 | -- dispatch pattern. The controller sets any extra headers and/or 13 | -- the status if it's not 200, then return the response. It's 14 | -- good form to delegate the generation of the response to a view 15 | -- function 16 | 17 | function index(web) 18 | return render_index() 19 | end 20 | 21 | function say(web, name) 22 | return render_say(web, name) 23 | end 24 | 25 | -- Builds the application's dispatch table, you can 26 | -- pass multiple patterns, and any captures get passed to 27 | -- the controller 28 | 29 | hello:dispatch_get(index, "/", "/index") 30 | hello:dispatch_get(say, "/say/(%a+)") 31 | 32 | -- These are the view functions referenced by the controllers. 33 | -- orbit.htmlify does through the functions in the table passed 34 | -- as the first argument and tries to match their name against 35 | -- the provided patterns (with an implicit ^ and $ surrounding 36 | -- the pattern. Each function that matches gets an environment 37 | -- where HTML functions are created on demand. They either take 38 | -- nil (empty tags), a string (text between opening and 39 | -- closing tags), or a table with attributes and a list 40 | -- of strings that will be the text. The indexing the 41 | -- functions adds a class attribute to the tag. Functions 42 | -- are cached. 43 | -- 44 | 45 | -- This is a convenience function for the common parts of a page 46 | 47 | function render_layout(inner_html) 48 | return html{ 49 | head{ title"Hello" }, 50 | body{ inner_html } 51 | } 52 | end 53 | 54 | function render_hello() 55 | return p.hello"Hello World!" 56 | end 57 | 58 | function render_index() 59 | return render_layout(render_hello()) 60 | end 61 | 62 | function render_say(web, name) 63 | return render_layout(render_hello() .. 64 | p.hello((web.input.greeting or "Hello ") .. name .. "!")) 65 | end 66 | 67 | orbit.htmlify(hello, "render_.+") 68 | -------------------------------------------------------------------------------- /samples/todo/todo.op: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env op.cgi 2 | 3 | $lua{[[ 4 | local luasql = require "luasql.sqlite3" 5 | app.conn = app.conn or recycle(function () return luasql.sqlite3():connect(web.real_path .. "/todo.db") end, 20) 6 | mapper.conn = app.conn 7 | todo_list = model("todo_list") 8 | if web.method == "post" then 9 | if web.input.id then 10 | local item = todo_list:find(tonumber(web.input.id)) 11 | if web.input.toggle then 12 | item.done = not item.done 13 | item:save() 14 | elseif web.input.remove then 15 | item:delete() 16 | forward("items.op") 17 | end 18 | finish() 19 | else 20 | local item = todo_list:new() 21 | item.title = web.input.item or "" 22 | item:save() 23 | forward("items.op") 24 | end 25 | end 26 | ]]} 27 | 28 | 29 | 30 | To-do List 31 | 32 | 55 | 60 | 61 | 62 |

    To-do

    63 | 66 |
    67 | 68 | 69 |
    70 | 71 | 72 | -------------------------------------------------------------------------------- /doc/us/license.md: -------------------------------------------------------------------------------- 1 |

    License

    2 | 3 |

    4 | Orbit is free software: it can be used for both academic 5 | and commercial purposes at absolutely no cost. There are no 6 | royalties or GNU-like "copyleft" restrictions. Orbit 7 | qualifies as 8 | Open Source 9 | software. 10 | Its licenses are compatible with 11 | GPL. 12 | Orbit is not in the public domain and the 13 | 14 | Kepler Project 15 | keep its copyright. 16 | The legal details are below. 17 |

    18 | 19 |

    The spirit of the license is that you are free to use 20 | Orbit for any purpose at no cost without having to ask us. 21 | The only requirement is that if you do use Orbit, then you 22 | should give us credit by including the appropriate copyright notice 23 | somewhere in your product or its documentation.

    24 | 25 |

    The Orbit library is designed and implemented by Fabio Mascarenhas, 26 | André Carregal and Tomás Guisasola. 27 | The implementation is not derived from licensed software.

    28 | 29 |
    30 |

    Copyright © 2007-2008 The Kepler Project.

    31 | 32 |

    Permission is hereby granted, free of charge, to any person 33 | obtaining a copy of this software and associated documentation 34 | files (the "Software"), to deal in the Software without 35 | restriction, including without limitation the rights to use, copy, 36 | modify, merge, publish, distribute, sublicense, and/or sell copies 37 | of the Software, and to permit persons to whom the Software is 38 | furnished to do so, subject to the following conditions:

    39 | 40 |

    The above copyright notice and this permission notice shall be 41 | included in all copies or substantial portions of the Software.

    42 | 43 |

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 44 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 45 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 46 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 47 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 48 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 49 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 50 | SOFTWARE.

    51 | 52 | -------------------------------------------------------------------------------- /samples/toycms/templates/lablua/styles/stylesheet1.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | margin: 0; 4 | padding: 0; 5 | font: 85% arial, hevetica, sans-serif; 6 | text-align: center; 7 | color: #000066; 8 | background-color: #FFFFFF; 9 | // background-image: url(../images/img_39.gif); 10 | } 11 | 12 | a:link { color: #000066; } 13 | a:visited { color: #0000CC; } 14 | 15 | a:hover, a:active 16 | { 17 | color: #CCCCFF; 18 | background-color: #000066; 19 | } 20 | 21 | h2 22 | { 23 | color: #000066; 24 | font: 140% georgia, times, "times new roman", serif; 25 | font-weight: bold; 26 | margin: 0 0 10px 0; 27 | } 28 | 29 | //h2 a { text-decoration: none; } 30 | 31 | h3 32 | { 33 | color: #000066; 34 | font: 106% georgia, times, "times new roman", serif; 35 | font-weight: bold; 36 | margin-top: 0; 37 | } 38 | 39 | #container 40 | { 41 | margin: 1em auto; 42 | width: 720px; 43 | text-align: left; 44 | background-color: #FFFFFF; 45 | border: 1px none #0000CC; 46 | } 47 | 48 | #header 49 | { 50 | height: 45px; 51 | width: 100%; 52 | background-image: url(../images/header.jpg); 53 | background-repeat: no-repeat; 54 | background-position: 0 0; 55 | border-bottom: 1px solid #0000CC; 56 | position: relative; 57 | border: 1px none #0000CC; 58 | border-bottom: 1px solid #0000CC; 59 | } 60 | 61 | #header h1 62 | { 63 | font-size: 1px; 64 | text-align: right; 65 | color: #000066; 66 | margin: 0; 67 | padding: 0; 68 | display: none; 69 | } 70 | 71 | #mainnav ul { list-style-type: none; } 72 | #mainnav li { display: inline; } 73 | 74 | #menu 75 | { 76 | float: right; 77 | width: 165px; 78 | border-left: 1px solid #0000CC; 79 | padding-left: 15px; 80 | } 81 | 82 | #contents { margin: 0 200px 40px 20px; } 83 | #contents p { line-height: 165%; } 84 | //.blogentry { border-bottom: 1px solid #0000CC; } 85 | .imagefloat { float: right; } 86 | 87 | #footer 88 | { 89 | clear: both; 90 | color: #CCCCFF; 91 | background-color: #0000CC; 92 | text-align: right; 93 | font-size: 90%; 94 | } 95 | 96 | #footer img 97 | { 98 | vertical-align: middle; 99 | } 100 | 101 | #skipmenu 102 | { 103 | position: absolute; 104 | left: 0; 105 | top: 5px; 106 | width: 645px; 107 | text-align: right; 108 | } 109 | 110 | #skipmenu a 111 | { 112 | color: #666; 113 | text-decoration: none; 114 | } 115 | 116 | #skipmenu a:hover 117 | { 118 | color: #fff; 119 | background-color: #666; 120 | text-decoration: none; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /samples/sproutcore/todo.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local orbit = require "orbit" 4 | orbit.cache = require "orbit.cache" 5 | local luasql = require "luasql.sqlite3" 6 | 7 | local json = require "json" 8 | local encode = json.encode 9 | local decode = json.decode 10 | 11 | local todo = orbit.new() 12 | todo.mapper.conn = luasql.sqlite3():connect(todo.real_path .. "/todo.db") 13 | local todo_list = todo:model("todo_list") 14 | local cache = orbit.cache.new(todo) 15 | 16 | function todo_list:url() 17 | return "/tasks/" .. self.id 18 | end 19 | 20 | function todo_list:to_json() 21 | return { guid = self:url(), description = self.description, isDone = self.is_done, order = self.id } 22 | end 23 | 24 | function todo.index(web) 25 | return todo:serve_static(web, todo.real_path .. "/static/todos/en/ee972277c11ed2d7cf0765e9c5b9738575b9248d/index.html") 26 | end 27 | 28 | todo:dispatch_get(todo.index, "/") 29 | 30 | function todo.get_tasks(web) 31 | web:content_type("application/json") 32 | local tasks, json = todo_list:find_all{ order = "id asc" }, {} 33 | for i, task in ipairs(tasks) do json[i] = task:to_json() end 34 | return encode{ content = json } 35 | end 36 | 37 | todo:dispatch_get(cache(todo.get_tasks), "/tasks") 38 | 39 | function todo.add_task(web) 40 | local opt = decode(web.input.post_data) 41 | local task = todo_list:new(opt) 42 | task:save() 43 | web.headers["Location"] = task:url() 44 | web.status = "201 Created" 45 | web:content_type("application/json") 46 | cache:invalidate("/tasks") 47 | return encode{ content = task:to_json() } 48 | end 49 | 50 | todo:dispatch_post(todo.add_task, "/tasks") 51 | 52 | function todo.get_task(web, id) 53 | local task = todo_list:find(tonumber(id)) 54 | if not task then return todo.not_found(web) end 55 | web:content_type("application/json") 56 | return encode{ content = task:to_json() } 57 | end 58 | 59 | todo:dispatch_get(cache(todo.get_task), "/tasks/(%d+)") 60 | 61 | function todo.put_task(web, id) 62 | local task = todo_list:find(tonumber(id)) 63 | if not task then return todo.not_found(web) end 64 | local opt = decode(web.input.post_data) 65 | task.description = opt.description 66 | task.is_done = opt.isDone 67 | task:save() 68 | cache:invalidate(task:url()) 69 | cache:invalidate("/tasks") 70 | web:content_type("application/json") 71 | return encode{ content = task:to_json() } 72 | end 73 | 74 | todo:dispatch_put(todo.put_task, "/tasks/(%d+)") 75 | 76 | function todo.delete_task(web, id) 77 | local task = todo_list:find(tonumber(id)) 78 | if not task then return todo.not_found(web) end 79 | task:delete() 80 | cache:invalidate("/tasks") 81 | end 82 | 83 | todo:dispatch_delete(todo.delete_task, "/tasks/(%d+)") 84 | 85 | todo:dispatch_static("/static/.*") 86 | 87 | return todo 88 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/post.html: -------------------------------------------------------------------------------- 1 |

    $title

    2 | 3 |
    4 |
    5 |
    6 | $markdown_body 7 |
    8 |
    9 |
    10 | 13 | | $if_comment_open[[ 14 | | Comments ($n_comments)]] 15 |
    16 |
    17 | 18 | $if_comments[[ 19 |
    20 |
    21 |

    $n_comments Comments

    22 | 23 | $comments[=[ 24 |
    25 |
    26 |
    27 | $author_link said: 28 |
    29 |
    30 | $markdown_body 31 |
    32 | 35 |
    36 |
    37 | ]=] 38 |
    39 |
    ]] 40 | $if_comment_open[[ 41 |
    42 |

    Post a comment

    43 |
    44 |
    45 |
    46 |
    47 | 48 | 49 |
    50 |
    51 | 52 | 53 |
    54 |
    55 | 56 | 57 |
    58 |
    59 |
    60 | 62 | 63 |
    64 |
     
    65 | 68 |
    69 |
    70 |
    71 | ]] -------------------------------------------------------------------------------- /samples/pages/index.op: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env op.cgi 2 | 3 | 5 | 6 | 7 | Welcome to Kepler! 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 |
    17 | 20 |
    21 |
    Welcome page
    22 |
    23 | 24 |
    25 | 26 | 52 | 53 |
    54 | 55 |

    Congratulations!

    56 | 57 |

    58 | If you are reading this page, 59 | $web|vars|SERVER_SOFTWARE 60 | has been successfully configured for Orbit Pages on your system. 61 |

    62 | 63 |

    64 | This is a page generated by CGILua that points to the installed modules documentation. 65 | It serves both as a documentation index and as a simple example of a dynamic Lua Page. 66 |

    67 | 68 |

    What now?

    69 |

    70 | From here you can also run some tests. 71 |

    72 | 73 |

    Contact us

    74 | 75 |

    76 | For more information on Kepler modules please 77 | contact us. 78 | Comments are welcome! 79 |

    80 | 81 |

    82 | You can also reach other Kepler developers and users on the Kepler 83 | Project mailing list. 84 |

    85 | 86 |

    87 | Copyright 2004-2007 - Kepler Project 88 |

    89 | 90 |
    91 | 92 |
    93 | 94 |
    95 |

    Valid XHTML 1.0

    96 |

    $Id: index.op,v 1.1 2008/06/30 14:29:59 carregal Exp $

    97 |
    98 | 99 |
    100 | 101 | 102 | -------------------------------------------------------------------------------- /src/launchers/orbit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | ------------------------------------------------------------------------------- 4 | -- 5 | -- Starts the orbit server 6 | -- 7 | -- 8 | ------------------------------------------------------------------------------- 9 | 10 | local ok, err = pcall(require, "wsapi.xavante") 11 | if not ok then 12 | io.stderr:write("WSAPI Xavante support not loaded:\n" .. err .. "\n\nPlease install wsapi-xavante with LuaRocks\n") 13 | os.exit(1) 14 | end 15 | 16 | local lfs = require "lfs" 17 | local xavante = require "xavante" 18 | local httpd = require "xavante.httpd" 19 | local vhostshandler = require "xavante.vhostshandler" 20 | local urlhandler = require "xavante.urlhandler" 21 | local util = require "wsapi.util" 22 | local wsapi = require "wsapi" 23 | local wsx = require "wsapi.xavante" 24 | 25 | local usage = [[ 26 | Usage: orbit [options] 27 | 28 | Starts a Xavante instance to serve a single Orbit application. Adds the 29 | application's path to LUA_PATH. 30 | 31 | Options: 32 | 33 | -l, --log= Logs all output to the file (default stdout 34 | and stderr) 35 | -p, --port= Binds to the specified port (default 8080) 36 | -h, --help Shows this help screen 37 | 38 | ]] 39 | 40 | local opts, args = util.getopt({ ... }, "lp") 41 | 42 | local app, app_args = args[1], { select(2, unpack(args)) } 43 | 44 | if not app or opts.h or opts.help then 45 | print(usage) 46 | os.exit(1) 47 | end 48 | 49 | if opts.l or opts.log then 50 | local logfile = opts.l or opts.log 51 | local tostring = tostring 52 | local log = io.open(logfile, "a+") 53 | if not log then 54 | error("Could not open log file. Please check the write permissions for: " .. logfile) 55 | end 56 | io.stdout = log 57 | io.stderr = log 58 | print = function (...) 59 | local nargs = select('#', ...) 60 | for i = 1, nargs-1 do 61 | log:write(tostring((select(i, ...)))) 62 | log:write("\t") 63 | end 64 | log:write(tostring(select(nargs, ...))) 65 | log:write("\n") 66 | log:flush() 67 | end 68 | end 69 | 70 | local path, name = app:match("^(.+[/\\])?([%w%._%- ]+)$") 71 | 72 | if not path then 73 | path, name = "", app 74 | end 75 | 76 | if app:sub(1, 1) ~= "/" and app:sub(1, 1) ~= "\\" and not app:match("^%a:\\") then 77 | path = lfs.currentdir() .. "/" .. path 78 | end 79 | 80 | package.path = package.path .. ";" .. path .. "?.lua;" .. path .. "?/?.lua" 81 | 82 | wsapi.app_path = path 83 | 84 | local app_func, err = loadfile(path .. name) 85 | if not app_func then error(err) end 86 | 87 | local app = app_func(unpack(app_args)) 88 | 89 | if not app then app = _G[name:match("(.+)%.")] end 90 | 91 | if type(app) == "table" then app = app.run end 92 | 93 | httpd.handle_request = vhostshandler { 94 | [""] = urlhandler { 95 | ["/"] = wsx.makeHandler (app, nil, path, path), 96 | } 97 | } 98 | 99 | httpd.register ("*", tonumber(opts.p or opts.port) or 8080, "Xavante 2.3") 100 | 101 | xavante.start_message(function (ports) 102 | print(string.format("Starting Orbit server at port %s", 103 | table.concat(ports, ", "))) 104 | end) 105 | 106 | xavante.start() 107 | -------------------------------------------------------------------------------- /samples/todo/todo.ws: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env wsapi.cgi 2 | 3 | local orbit = require "orbit" 4 | local cosmo = require "cosmo" 5 | local luasql = require "luasql.sqlite3" 6 | 7 | local todo = orbit.new() 8 | 9 | todo.mapper.logging = true 10 | todo.mapper.conn = luasql.sqlite3():connect(todo.real_path .. "/todo.db") 11 | 12 | todo.list = todo:model("todo_list") 13 | 14 | local function item_list() 15 | return todo.list:find_all{ order = "created_at desc" } 16 | end 17 | 18 | local function index(web) 19 | local list = web:page_inline(todo.items, { items = item_list() }) 20 | return web:page_inline(todo.index, { items = list }) 21 | end 22 | 23 | todo:dispatch_get(index, "/") 24 | 25 | local function add(web) 26 | local item = todo.list:new() 27 | item.title = web.input.item or "" 28 | item:save() 29 | return web:page_inline(todo.items, { items = item_list() }) 30 | end 31 | 32 | todo:dispatch_post(add, "/add") 33 | 34 | local function remove(web, id) 35 | local item = todo.list:find(tonumber(id)) 36 | item:delete() 37 | return web:page_inline(todo.items, { items = item_list() }) 38 | end 39 | 40 | todo:dispatch_post(remove, "/remove/(%d+)") 41 | 42 | local function toggle(web, id) 43 | local item = todo.list:find(tonumber(id)) 44 | item.done = not item.done 45 | item:save() 46 | return "toggle" 47 | end 48 | 49 | todo:dispatch_post(toggle, "/toggle/(%d+)") 50 | 51 | todo:dispatch_static(".+%.js") 52 | 53 | todo.index = [===[ 54 | 55 | 56 | 57 | To-do List 58 | 59 | 82 | 87 | 88 | 89 |

    To-do

    90 |
      91 | $items 92 |
    93 |
    94 | 95 | 96 |
    97 | 98 | 99 | ]===] 100 | 101 | todo.items = [===[ 102 | $if{$items|1}[==[ 103 | $items[[ 104 |
  • $title 105 | Remove
  • 106 | ]] 107 | ]==],[==[Nothing to do!]==] 108 | ]===] 109 | 110 | return todo 111 | -------------------------------------------------------------------------------- /samples/sproutcore/static/todos/en/ee972277c11ed2d7cf0765e9c5b9738575b9248d/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | Todos 9 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 |
    38 |

    Loading...

    39 | 40 | 41 |

    42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/orbit/cache.lua: -------------------------------------------------------------------------------- 1 | local lfs = require "lfs" 2 | 3 | module("orbit.cache", package.seeall) 4 | 5 | local function pathinfo_to_file(path_info) 6 | local atom = path_info:find("/xml$") 7 | if atom then 8 | path_info = path_info:sub(2, atom - 1) 9 | else 10 | path_info = path_info:sub(2, #path_info) 11 | end 12 | path_info = string.gsub(path_info, "/", "-") 13 | if path_info == "" then path_info = "index" end 14 | if atom then 15 | return path_info .. '.xml' 16 | else 17 | return path_info .. '.html' 18 | end 19 | end 20 | 21 | function get(cache, key) 22 | if not cache.base_path then 23 | local headers = {} 24 | if key:find("/xml$") then 25 | headers["Content-Type"] = "text/xml" 26 | else 27 | headers["Content-Type"] = "text/html" 28 | end 29 | return cache.values[key], headers 30 | else 31 | local filename = cache.base_path .. "/" .. pathinfo_to_file(key) 32 | local web = { headers = {} } 33 | if lfs.attributes(filename, "mode") == "file" then 34 | local response = cache.app:serve_static(web, filename) 35 | return response, web.headers 36 | end 37 | end 38 | end 39 | 40 | local function writefile(filename, contents) 41 | local file = assert(io.open(filename, "wb")) 42 | if lfs.lock(file, "w") then 43 | file:write(contents) 44 | lfs.unlock(file) 45 | file:close() 46 | else 47 | file:close() 48 | end 49 | end 50 | 51 | function set(cache, key, value) 52 | if not cache.base_path then 53 | cache.values[key] = value 54 | else 55 | local filename = cache.base_path .. "/" .. pathinfo_to_file(key) 56 | writefile(filename, value) 57 | end 58 | end 59 | 60 | local function cached(cache, f) 61 | return function (web, ...) 62 | local body, headers = cache:get(web.path_info) 63 | if body then 64 | for k, v in pairs(headers) do 65 | web.headers[k] = v 66 | end 67 | return body 68 | else 69 | local key = web.path_info 70 | local body = f(web, ...) 71 | cache:set(key, body) 72 | return body 73 | end 74 | end 75 | end 76 | 77 | function invalidate(cache, ...) 78 | for _, key in ipairs{...} do 79 | if not cache.base_path then 80 | cache.values[key] = nil 81 | else 82 | local filename = cache.base_path .. "/" .. pathinfo_to_file(key) 83 | os.remove(filename) 84 | end 85 | end 86 | end 87 | 88 | function nuke(cache) 89 | if not cache.base_path then 90 | cache.values = {} 91 | else 92 | for file in lfs.dir(cache.base_path) do 93 | if file ~= "." and file ~= ".." then 94 | os.remove(cache.base_path .. "/" .. file) 95 | end 96 | end 97 | end 98 | end 99 | 100 | function new(app, base_path) 101 | local values 102 | if not base_path then 103 | values = {} 104 | else 105 | local dir = lfs.attributes(base_path, "mode") 106 | if not dir then 107 | assert(lfs.mkdir(base_path)) 108 | elseif dir ~= "directory" then 109 | error("base path of cache " .. base_path .. " not a directory") 110 | end 111 | end 112 | local cache = { app = app, values = values, 113 | base_path = base_path } 114 | setmetatable(cache, { __index = _M, __call = function (tab, f) 115 | return cached(tab, f) 116 | end }) 117 | return cache 118 | end 119 | -------------------------------------------------------------------------------- /doc/us/makedoc.lua: -------------------------------------------------------------------------------- 1 | local cosmo = require "cosmo" 2 | local markdown = require "markdown" 3 | 4 | local pages = { 5 | { name = "Home", file = "index", sections = {} }, 6 | { name = "Pages", file = "pages", sections = {} }, 7 | { name = "Reference", file = "reference", sections = {} }, 8 | { name = "Tutorial", file = "example", sections = {} }, 9 | { name = "License", file = "license", sections = {} } 10 | } 11 | 12 | local project = { 13 | name = "Orbit", 14 | blurb = "MVC for Lua Web Development", 15 | logo = "orbit.png", 16 | } 17 | 18 | local template = [==[ 19 | 20 | 22 | 23 | 24 | $name 25 | 26 | 27 | 28 | 29 | 30 | 31 |
    32 | 33 |
    34 | 35 | 38 |
    $name
    39 |
    $blurb
    40 |
    41 | 42 |
    43 | 44 | 56 | 57 |
    58 | 59 | $content 60 | 61 |
    62 | 63 |
    64 | 65 |
    66 |

    Valid XHTML 1.0!

    67 |
    68 | 69 |
    70 | 71 | 72 | 73 | 74 | ]==] 75 | 76 | local function readfile(filename) 77 | local file = io.open(filename) 78 | local contents = file:read("*a") 79 | file:close() 80 | return contents 81 | end 82 | 83 | local function writefile(filename, contents) 84 | local file = io.open(filename, "w+") 85 | file:write(contents) 86 | file:close() 87 | end 88 | 89 | local function gen_page(project, pages, p) 90 | project.pages = function () 91 | for _, page in ipairs(pages) do 92 | local namelink 93 | if page.file == p.file then 94 | namelink = cosmo.fill([[$name]], { name = page.name}) 95 | else 96 | namelink = cosmo.fill([[$name]], { name = page.name, file = page.file}) 97 | end 98 | cosmo.yield{ namelink = namelink, sections = function () 99 | for _, s in ipairs(page.sections) do 100 | cosmo.yield{ name = s.name, anchor = 101 | page.file .. ".html#" .. s.anchor } 102 | end 103 | end } 104 | end 105 | end 106 | return (cosmo.fill(template, project)) 107 | end 108 | 109 | for _, p in ipairs(pages) do 110 | project.content = markdown(readfile(p.file .. ".md")) 111 | writefile(p.file .. ".html", gen_page(project, pages, p)) 112 | end 113 | -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/layout.html: -------------------------------------------------------------------------------- 1 | $import{"archive"} 2 | $import{"index_view"} 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Orbit Blog 14 | 15 | 16 | 17 |
    18 |
    19 | 25 |
    26 |
    27 |
    28 |
    29 | $view 30 |
    31 |
    32 | 33 |
    34 |
    35 |
    36 |

    Recent Posts

    37 |
    38 |
      39 | $show_posts{ include_tags = {"blog-%"}, count = 7 }[[ 40 |
    • $title
    • 41 | ]] 42 |
    43 |
    44 |
    45 |
    46 |

    Links

    47 |
    48 |
      49 | $show_posts{ include_tags = {"blogroll"} }[[ 50 |
    • $title
    • 51 | ]] 52 |
    53 |
    54 |
    55 |
    56 |

    Monthly Archives

    57 |
    58 |
      59 | $month_list{ include_tags = {"blog-%"} }[[ 60 |
    • $month_name $year
    • 61 | ]] 62 |
    63 |
    64 |
    65 |
    66 | 70 |
    71 |
    72 |
    73 | 74 |
    75 |
    76 | 77 |
    78 |
    79 |
    80 |
    81 |
    82 |
    83 | 85 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /doc/us/pages.md: -------------------------------------------------------------------------------- 1 | ## Orbit Pages 2 | 3 | Orbit Pages is a PHP-like programming environment built on top of Orbit. Orbit pages 4 | are HTML pages (but using the extension .op in a typical Orbit installation) that 5 | get dynamically converted into Orbit apps. They are launched by the op.cgi, op.fcgi 6 | and ophandler.lua launchers, for CGI, FastCGI, and Xavante, respectively. A standard 7 | Kepler installation includes support for Orbit pages by default. 8 | 9 | An Orbit page is also a template that uses the [Cosmo](http://cosmo.luaforge.net) 10 | template language. The environment of this template is a sandbox that wraps the 11 | global environment and is recreated on each request. The main variable in this 12 | environment is the `web` variable, which is an Orbit request/response object. 13 | Other variables of note: 14 | 15 | **mapper** - an instance of the default Orbit ORM 16 | 17 | **model(*name*, *dao*)** - same as mapper:new(*name*, *dao*), except that if *name* 18 | is a tabel then calls mapper:new(*name[1]*, *name[2]*), so you can use this in the 19 | template as `$model{ name, dao }` 20 | 21 | **app** - the application's global environment, to be used as a session cache (for DB 22 | connections, for example) for persistent launchers 23 | 24 | **finish(*res*)** - suspends the execution of the current page, and sends *res* as a 25 | response **instead** of the page's contents 26 | 27 | **redirect(*target*)** - same as web:redirect(*target*) followed by finish(). If *target* 28 | is a table does web:redirect(*target[1]*), so you can use this in the template as 29 | `$redirect{ target }` 30 | 31 | **include(*page*, [*env*])** - evaluates the Orbit page in the file *page* (relative to the 32 | current page's path), optionally using the extra variables in *env* in the template's 33 | environment. Can also be used in the template as `$include{ page, env }` 34 | 35 | **forward(*page*, [*env*])** - aborts the execution of the current page and evaluates 36 | and sends the page in file *page* instead; otherwise same as **include** 37 | 38 | There also a few more variables that should be used only in the template: 39 | 40 | **$lua{ *code* }** - runs *code* in the same environment as the page, so 41 | *code* can change the template's variables and even define new ones 42 | 43 | **$if{ *condition* }[[ *then-part* ]],[[ *else-part* ]]** - if *condition* is true then 44 | is replaced by the template evaluation of *then-part*, otherwise *else-part*. *else-part* 45 | is optional, defaulting to blank 46 | 47 | **$fill{ ... }[[ *template* ]]** - replaced by the evaluation of *template* using the environment 48 | passed to fill (*template* does **not** inherit the variables of the page) 49 | 50 | Below is a very simple Orbit page that shows most of the concepts above (including Cosmo 51 | concepts, see the Cosmo documentation for that): 52 | 53 | #!/usr/bin/env op.cgi 54 | 55 | 56 |

    Hello Orbit!

    57 |

    I am in $web|real_path, and the script is 58 | $web|script_name.

    59 | $lua{[[ 60 | if not web.input.msg then 61 | web.input.msg = "nothing" 62 | end 63 | ]]} 64 |

    You passed: $web|input|msg.

    65 | $include{ "bar.op" } 66 | 67 | 68 | 69 | The `bar.op` page it includes is this: 70 | 71 | #!/usr/bin/env op.cgi 72 |

    This is bar, and you passed $web|input|msg!

    73 | 74 | The [Kepler](http://www.keplerproject.org) distribution has a more complete example that has database 75 | access, POST, and even some simple AJAX. 76 | -------------------------------------------------------------------------------- /samples/toycms/admin_style.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | margin: 0; 4 | padding: 0; 5 | font: 85% arial, hevetica, sans-serif; 6 | text-align: center; 7 | color: #000066; 8 | background-color: #FFFFFF; 9 | } 10 | a:link { color: #000066; } 11 | a:visited { color: #0000CC; } 12 | a:hover, a:active 13 | { 14 | color: #CCCCFF; 15 | background-color: #000066; 16 | } 17 | a.button { 18 | color: #000066; 19 | text-decoration: none; 20 | } 21 | a.button:visited { color: #000066; } 22 | a.button:hover { color: #000066; background-color: transparent; } 23 | h2 24 | { 25 | color: #000066; 26 | font: 140% georgia, times, "times new roman", serif; 27 | font-weight: bold; 28 | margin: 0 0 10px 0; 29 | } 30 | h3 31 | { 32 | color: #000066; 33 | font: 106% georgia, times, "times new roman", serif; 34 | font-weight: bold; 35 | margin-top: 0; 36 | } 37 | #container 38 | { 39 | margin: 1em auto; 40 | width: 720px; 41 | text-align: left; 42 | background-color: #FFFFFF; 43 | border: 1px none #0000CC; 44 | } 45 | #header 46 | { 47 | color: #CCCCFF; 48 | background-color: #000088; 49 | height: 45px; 50 | width: 710px; 51 | border-bottom: 1px solid #0000CC; 52 | position: relative; 53 | border: 1px none #0000CC; 54 | border-bottom: 1px solid #0000CC; 55 | padding: 5px; 56 | text-align: right; 57 | font-size: 300%; 58 | } 59 | #mainnav ul { list-style-type: none; } 60 | #mainnav li { display: inline; } 61 | #menu 62 | { 63 | float: right; 64 | width: 165px; 65 | border-left: 1px solid #0000CC; 66 | padding-left: 15px; 67 | padding-right: 15px; 68 | margin-bottom: 30px; 69 | } 70 | #contents { padding-right: 15px; margin: 0 200px 40px 20px; } 71 | #contents p { line-height: 165%; } 72 | .imagefloat { float: right; } 73 | #footer 74 | { 75 | clear: both; 76 | color: #CCCCFF; 77 | background-color: #0000CC; 78 | text-align: right; 79 | font-size: 90%; 80 | } 81 | #footer img 82 | { 83 | vertical-align: middle; 84 | } 85 | #skipmenu 86 | { 87 | position: absolute; 88 | left: 0; 89 | top: 5px; 90 | width: 645px; 91 | text-align: right; 92 | } 93 | #skipmenu a 94 | { 95 | color: #666; 96 | text-decoration: none; 97 | } 98 | #skipmenu a:hover 99 | { 100 | color: #fff; 101 | background-color: #666; 102 | text-decoration: none; 103 | } 104 | #container 105 | { 106 | border: 1px solid #0000CC; 107 | } 108 | #mainnav 109 | { 110 | background-color: #0000CC; 111 | color: #CCCCFF; 112 | padding: 2px 0; 113 | margin-bottom: 22px; 114 | } 115 | #mainnav ul 116 | { 117 | margin: 0 0 0 20px; 118 | padding: 0; 119 | list-style-type: none; 120 | border-left: 1px solid #CCCCFF; 121 | } 122 | #mainnav li 123 | { 124 | display: inline; 125 | padding: 0 10px; 126 | border-right: 1px solid #CCCCFF; 127 | } 128 | #mainnav li a 129 | { 130 | text-decoration: none; 131 | color: #CCCCFF; 132 | } 133 | #mainnav li a:hover 134 | { 135 | text-decoration: none; 136 | color: #0000CC; 137 | background-color: #CCCCFF; 138 | } 139 | #menu ul 140 | { 141 | margin-left: 0; 142 | padding-left: 0; 143 | list-style-type: none; 144 | line-height: 165%; 145 | } 146 | .imagefloat 147 | { 148 | padding: 2px; 149 | border: 1px solid #0000CC; 150 | margin: 0 0 10px 10px; 151 | } 152 | div.blogentry { 153 | padding-bottom: 30px; 154 | } 155 | .blogentry ul 156 | { 157 | list-style-type: square; 158 | margin: 10px 0px 15px -10px; 159 | } 160 | .blogentry li 161 | { 162 | line-height: 150%; 163 | } 164 | #footer 165 | { 166 | background-color: #0000CC; 167 | padding: 5px; 168 | font-size: 90%; 169 | } 170 | -------------------------------------------------------------------------------- /samples/blog/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | body 4 | { 5 | margin: 0; 6 | padding: 0; 7 | font: 85% arial, hevetica, sans-serif; 8 | text-align: center; 9 | color: #000066; 10 | background-color: #FFFFFF; 11 | // background-image: url(../images/img_39.gif); 12 | } 13 | 14 | a:link { color: #000066; } 15 | a:visited { color: #0000CC; } 16 | 17 | a:hover, a:active 18 | { 19 | color: #CCCCFF; 20 | background-color: #000066; 21 | } 22 | 23 | h2 24 | { 25 | color: #000066; 26 | font: 140% georgia, times, "times new roman", serif; 27 | font-weight: bold; 28 | margin: 0 0 10px 0; 29 | } 30 | 31 | //h2 a { text-decoration: none; } 32 | 33 | h3 34 | { 35 | color: #000066; 36 | font: 106% georgia, times, "times new roman", serif; 37 | font-weight: bold; 38 | margin-top: 0; 39 | } 40 | 41 | #container 42 | { 43 | margin: 1em auto; 44 | width: 720px; 45 | text-align: left; 46 | background-color: #FFFFFF; 47 | border: 1px none #0000CC; 48 | } 49 | 50 | #header 51 | { 52 | height: 45px; 53 | width: 100%; 54 | background-image: url(head.jpg); 55 | background-repeat: no-repeat; 56 | background-position: 0 0; 57 | border-bottom: 1px solid #0000CC; 58 | position: relative; 59 | border: 1px none #0000CC; 60 | border-bottom: 1px solid #0000CC; 61 | } 62 | 63 | #header h1 64 | { 65 | font-size: 1px; 66 | text-align: right; 67 | color: #000066; 68 | margin: 0; 69 | padding: 0; 70 | display: none; 71 | } 72 | 73 | #mainnav ul { list-style-type: none; } 74 | #mainnav li { display: inline; } 75 | 76 | #menu 77 | { 78 | float: right; 79 | width: 165px; 80 | border-left: 1px solid #0000CC; 81 | padding-left: 15px; 82 | padding-right: 15px; 83 | } 84 | 85 | #contents { padding-right: 15px; margin: 0 200px 40px 20px; } 86 | #contents p { line-height: 165%; } 87 | //.blogentry { border-bottom: 1px solid #0000CC; } 88 | .imagefloat { float: right; } 89 | 90 | #footer 91 | { 92 | clear: both; 93 | color: #CCCCFF; 94 | background-color: #0000CC; 95 | text-align: right; 96 | font-size: 90%; 97 | } 98 | 99 | #footer img 100 | { 101 | vertical-align: middle; 102 | } 103 | 104 | #skipmenu 105 | { 106 | position: absolute; 107 | left: 0; 108 | top: 5px; 109 | width: 645px; 110 | text-align: right; 111 | } 112 | 113 | #skipmenu a 114 | { 115 | color: #666; 116 | text-decoration: none; 117 | } 118 | 119 | #skipmenu a:hover 120 | { 121 | color: #fff; 122 | background-color: #666; 123 | text-decoration: none; 124 | } 125 | 126 | #container 127 | { 128 | border: 1px solid #0000CC; 129 | } 130 | 131 | #mainnav 132 | { 133 | background-color: #0000CC; 134 | color: #CCCCFF; 135 | padding: 2px 0; 136 | margin-bottom: 22px; 137 | } 138 | 139 | #mainnav ul 140 | { 141 | margin: 0 0 0 20px; 142 | padding: 0; 143 | list-style-type: none; 144 | border-left: 1px solid #CCCCFF; 145 | } 146 | 147 | #mainnav li 148 | { 149 | display: inline; 150 | padding: 0 10px; 151 | border-right: 1px solid #CCCCFF; 152 | } 153 | 154 | #mainnav li a 155 | { 156 | text-decoration: none; 157 | color: #CCCCFF; 158 | } 159 | 160 | #mainnav li a:hover 161 | { 162 | text-decoration: none; 163 | color: #0000CC; 164 | background-color: #CCCCFF; 165 | } 166 | 167 | #menu ul 168 | { 169 | margin-left: 0; 170 | padding-left: 0; 171 | list-style-type: none; 172 | line-height: 165%; 173 | } 174 | 175 | .imagefloat 176 | { 177 | padding: 2px; 178 | border: 1px solid #0000CC; 179 | margin: 0 0 10px 10px; 180 | } 181 | 182 | .blogentry ul 183 | { 184 | // list-style-type: none; 185 | // text-align: right; 186 | // margin: 1em 0; 187 | // padding: 0; 188 | list-style-type: square; 189 | margin: 10px 0px 15px -10px; 190 | // font-size: 95%; 191 | } 192 | 193 | .blogentry li 194 | { 195 | // display: inline; 196 | // padding: 0 0 0 7px; 197 | line-height: 150%; 198 | } 199 | 200 | #footer 201 | { 202 | background-color: #0000CC; 203 | padding: 5px; 204 | font-size: 90%; 205 | } 206 | 207 | -------------------------------------------------------------------------------- /samples/toycms/templates/blog/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | body 4 | { 5 | margin: 0; 6 | padding: 0; 7 | font: 85% arial, hevetica, sans-serif; 8 | text-align: center; 9 | color: #000066; 10 | background-color: #FFFFFF; 11 | // background-image: url(../images/img_39.gif); 12 | } 13 | 14 | a:link { color: #000066; } 15 | a:visited { color: #0000CC; } 16 | 17 | a:hover, a:active 18 | { 19 | color: #CCCCFF; 20 | background-color: #000066; 21 | } 22 | 23 | h2 24 | { 25 | color: #000066; 26 | font: 140% georgia, times, "times new roman", serif; 27 | font-weight: bold; 28 | margin: 0 0 10px 0; 29 | } 30 | 31 | p.posted { font-weight: bold; } 32 | 33 | //h2 a { text-decoration: none; } 34 | 35 | h3 36 | { 37 | color: #000066; 38 | font: 106% georgia, times, "times new roman", serif; 39 | font-weight: bold; 40 | margin-top: 0; 41 | } 42 | 43 | #container 44 | { 45 | margin: 1em auto; 46 | width: 720px; 47 | text-align: left; 48 | background-color: #FFFFFF; 49 | border: 1px none #0000CC; 50 | } 51 | 52 | #header 53 | { 54 | height: 45px; 55 | width: 100%; 56 | background-image: url(images/head.jpg); 57 | background-repeat: no-repeat; 58 | background-position: 0 0; 59 | border-bottom: 1px solid #0000CC; 60 | position: relative; 61 | border: 1px none #0000CC; 62 | border-bottom: 1px solid #0000CC; 63 | } 64 | 65 | #header h1 66 | { 67 | font-size: 1px; 68 | text-align: right; 69 | color: #000066; 70 | margin: 0; 71 | padding: 0; 72 | display: none; 73 | } 74 | 75 | #mainnav ul { list-style-type: none; } 76 | #mainnav li { display: inline; } 77 | 78 | #menu 79 | { 80 | float: right; 81 | width: 165px; 82 | border-left: 1px solid #0000CC; 83 | padding-left: 15px; 84 | padding-right: 15px; 85 | margin-bottom: 50px; 86 | } 87 | 88 | #contents { padding-right: 15px; margin: 0 200px 40px 20px; 89 | } 90 | #contents p { line-height: 165%; } 91 | //.blogentry { border-bottom: 1px solid #0000CC; } 92 | .imagefloat { float: right; } 93 | 94 | #footer 95 | { 96 | clear: both; 97 | color: #CCCCFF; 98 | background-color: #0000CC; 99 | text-align: right; 100 | font-size: 90%; 101 | } 102 | 103 | #footer img 104 | { 105 | vertical-align: middle; 106 | } 107 | 108 | #skipmenu 109 | { 110 | position: absolute; 111 | left: 0; 112 | top: 5px; 113 | width: 645px; 114 | text-align: right; 115 | } 116 | 117 | #skipmenu a 118 | { 119 | color: #666; 120 | text-decoration: none; 121 | } 122 | 123 | #skipmenu a:hover 124 | { 125 | color: #fff; 126 | background-color: #666; 127 | text-decoration: none; 128 | } 129 | 130 | #container 131 | { 132 | border: 1px solid #0000CC; 133 | } 134 | 135 | #mainnav 136 | { 137 | background-color: #0000CC; 138 | color: #CCCCFF; 139 | padding: 2px 0; 140 | margin-bottom: 22px; 141 | } 142 | 143 | #mainnav ul 144 | { 145 | margin: 0 0 0 20px; 146 | padding: 0; 147 | list-style-type: none; 148 | border-left: 1px solid #CCCCFF; 149 | } 150 | 151 | #mainnav li 152 | { 153 | display: inline; 154 | padding: 0 10px; 155 | border-right: 1px solid #CCCCFF; 156 | } 157 | 158 | #mainnav li a 159 | { 160 | text-decoration: none; 161 | color: #CCCCFF; 162 | } 163 | 164 | #mainnav li a:hover 165 | { 166 | text-decoration: none; 167 | color: #0000CC; 168 | background-color: #CCCCFF; 169 | } 170 | 171 | #menu ul 172 | { 173 | margin-left: 0; 174 | padding-left: 0; 175 | list-style-type: none; 176 | line-height: 165%; 177 | } 178 | 179 | .imagefloat 180 | { 181 | padding: 2px; 182 | border: 1px solid #0000CC; 183 | margin: 0 0 10px 10px; 184 | } 185 | 186 | .blogentry ul 187 | { 188 | // list-style-type: none; 189 | // text-align: right; 190 | // margin: 1em 0; 191 | // padding: 0; 192 | list-style-type: square; 193 | margin: 10px 0px 15px -10px; 194 | // font-size: 95%; 195 | } 196 | 197 | .blogentry li 198 | { 199 | // display: inline; 200 | // padding: 0 0 0 7px; 201 | line-height: 150%; 202 | } 203 | 204 | #footer 205 | { 206 | background-color: #0000CC; 207 | padding: 5px; 208 | font-size: 90%; 209 | } 210 | 211 | -------------------------------------------------------------------------------- /samples/sproutcore/static/todos/en/ee972277c11ed2d7cf0765e9c5b9738575b9248d/javascript.js: -------------------------------------------------------------------------------- 1 | (function(){var a="sproutcore/standard_theme";if(!SC.BUNDLE_INFO){throw"SC.BUNDLE_INFO is not defined!" 2 | }if(SC.BUNDLE_INFO[a]){return}SC.BUNDLE_INFO[a]={requires:["sproutcore/empty_theme"],styles:["/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/stylesheet-packed.css","/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/stylesheet.css"],scripts:["/static/sproutcore/standard_theme/en/52366532814d7f12ca549445e2e2a07c4b5f73d6/javascript-packed.js"]} 3 | })();Todos=SC.Application.create({NAMESPACE:"Todos",VERSION:"0.1.0",store:SC.Store.create({commitRecordsAutomatically:YES}).from("Todos.DataSource")}); 4 | Todos.tasksController=SC.ArrayController.create(SC.CollectionViewDelegate,{summary:function(){var a=this.get("length"),b; 5 | if(a&&a>0){b=a===1?"1 task":"%@ tasks".fmt(a)}else{b="No tasks"}return b}.property("length").cacheable(),collectionViewDeleteContent:function(a,e,d){var c=d.map(function(f){return this.objectAt(f) 6 | },this);c.invoke("destroy");var b=d.get("min")-1;if(b<0){b=0}this.selectObject(this.objectAt(b)); 7 | return YES},addTask:function(){var a;a=Todos.store.createRecord(Todos.Task,{description:"New Task",isDone:false}); 8 | this.selectObject(a);this.invokeLater(function(){var d=this.indexOf(a);var c=Todos.mainPage.getPath("mainPane.middleView.contentView"); 9 | var b=c.itemViewForContentIndex(d);b.beginEditing()});return YES},toggleDone:function(){var a=this.get("selection"); 10 | a.setEach("isDone",!a.everyProperty("isDone"));return YES},logout:function(){console.log("logout!"); 11 | window.location.pathname="/logout"}});Todos.TASKS_QUERY=SC.Query.local(Todos.Task,{orderBy:"description"}); 12 | Todos.DataSource=SC.DataSource.extend({fetch:function(a,b){if(b===Todos.TASKS_QUERY){SC.Request.getUrl("/tasks").set("isJSON",YES).notify(this,this.didFetchTasks,{store:a}).send() 13 | }},didFetchTasks:function(c,d){var b=d.store,a=c.get("response");if(a.content){b.loadRecords(Todos.Task,a.content) 14 | }},createRecord:function(a,b){var c=a.readDataHash(b);SC.Request.postUrl("/tasks").set("isJSON",YES).notify(this,this.didCreateTask,{store:a,storeKey:b}).send(c) 15 | },didCreateTask:function(d,f){var e=d.get("rawResponse"),b=e.getResponseHeader("Location"),a=f.store,c=f.storeKey; 16 | a.dataSourceDidComplete(c,null,b)},updateRecord:function(a,c){var d=a.readDataHash(c),b=SC.Store.idFor(c); 17 | SC.Request.putUrl(b).set("isJSON",YES).send(d);a.dataSourceDidComplete(c)},destroyRecord:function(a,c){var b=SC.Store.idFor(c); 18 | SC.Request.deleteUrl(b).send();a.dataSourceDidDestroy(c)}});Todos.Task=SC.Record.extend({isDone:SC.Record.attr(Boolean),description:SC.Record.attr(String)}); 19 | Todos.mainPage=SC.Page.design({mainPane:SC.MainPane.design({childViews:"middleView topView bottomView".w(),classNames:"main-container",topView:SC.ToolbarView.design({layout:{top:0,left:0,right:0,height:36},childViews:"labelView addButton logoutButton".w(),anchorLocation:SC.ANCHOR_TOP,labelView:SC.LabelView.design({layout:{centerY:0,height:24,left:8,width:200},controlSize:SC.LARGE_CONTROL_SIZE,fontWeight:SC.BOLD_WEIGHT,value:"Todos"}),addButton:SC.ButtonView.design({layout:{centerY:0,height:24,right:122,width:100},title:"Add Task",target:"Todos.tasksController",action:"addTask"}),logoutButton:SC.ButtonView.design({layout:{centerY:0,height:24,right:12,width:100},title:"Logout",target:"Todos.tasksController",action:"logout"})}),middleView:SC.ScrollView.design({hasHorizontalScroller:NO,layout:{top:36,bottom:32,left:0,right:0},backgroundColor:"white",contentView:SC.ListView.design({contentBinding:"Todos.tasksController.arrangedObjects",selectionBinding:"Todos.tasksController.selection",contentValueKey:"description",contentCheckboxKey:"isDone",rowHeight:21,canEditContent:YES,canDeleteContent:YES,target:"Todos.tasksController",action:"toggleDone"})}),bottomView:SC.ToolbarView.design({layout:{bottom:0,left:0,right:0,height:32},childViews:"summaryView".w(),anchorLocation:SC.ANCHOR_BOTTOM,summaryView:SC.LabelView.design({layout:{centerY:0,height:18,left:20,right:20},textAlign:SC.ALIGN_CENTER,valueBinding:"Todos.tasksController.summary"})})})}); 20 | Todos.main=function main(){Todos.getPath("mainPage.mainPane").append();var a=Todos.store.find(Todos.TASKS_QUERY); 21 | Todos.tasksController.set("content",a)};function main(){Todos.main()}; -------------------------------------------------------------------------------- /samples/toycms/templates/aboutanything/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | body 4 | { 5 | margin: 0; 6 | padding: 0; 7 | font: 85% arial, hevetica, sans-serif; 8 | text-align: center; 9 | color: #000066; 10 | background-color: #FFFFFF; 11 | // background-image: url(../images/img_39.gif); 12 | } 13 | 14 | a:link { color: #000066; } 15 | a:visited { color: #0000CC; } 16 | 17 | a:hover, a:active 18 | { 19 | color: #CCCCFF; 20 | background-color: #000066; 21 | } 22 | 23 | h2 24 | { 25 | color: #000066; 26 | font: 140% georgia, times, "times new roman", serif; 27 | font-weight: bold; 28 | margin: 0 0 10px 0; 29 | } 30 | 31 | p.posted { font-weight: bold; } 32 | 33 | //h2 a { text-decoration: none; } 34 | 35 | h3 36 | { 37 | color: #000066; 38 | font: 106% georgia, times, "times new roman", serif; 39 | font-weight: bold; 40 | margin-top: 0; 41 | } 42 | 43 | #container 44 | { 45 | margin: 1em auto; 46 | width: 720px; 47 | text-align: left; 48 | background-color: #FFFFFF; 49 | border: 1px none #0000CC; 50 | } 51 | 52 | #header 53 | { 54 | height: 45px; 55 | width: 100%; 56 | background-image: url(images/head.jpg); 57 | background-repeat: no-repeat; 58 | background-position: 0 0; 59 | border-bottom: 1px solid #0000CC; 60 | position: relative; 61 | border: 1px none #0000CC; 62 | border-bottom: 1px solid #0000CC; 63 | } 64 | 65 | #header h1 66 | { 67 | font-size: 1px; 68 | text-align: right; 69 | color: #000066; 70 | margin: 0; 71 | padding: 0; 72 | display: none; 73 | } 74 | 75 | #mainnav ul { list-style-type: none; } 76 | #mainnav li { display: inline; } 77 | 78 | #menu 79 | { 80 | float: right; 81 | width: 165px; 82 | border-left: 1px solid #0000CC; 83 | padding-left: 15px; 84 | padding-right: 15px; 85 | margin-bottom: 50px; 86 | } 87 | 88 | #contents { padding-right: 15px; margin: 0 200px 40px 20px; 89 | } 90 | #contents p { line-height: 165%; } 91 | //.blogentry { border-bottom: 1px solid #0000CC; } 92 | .imagefloat { float: right; } 93 | 94 | #footer 95 | { 96 | clear: both; 97 | color: #CCCCFF; 98 | background-color: #0000CC; 99 | text-align: right; 100 | font-size: 90%; 101 | } 102 | 103 | #footer img 104 | { 105 | vertical-align: middle; 106 | } 107 | 108 | #skipmenu 109 | { 110 | position: absolute; 111 | left: 0; 112 | top: 5px; 113 | width: 645px; 114 | text-align: right; 115 | } 116 | 117 | #skipmenu a 118 | { 119 | color: #666; 120 | text-decoration: none; 121 | } 122 | 123 | #skipmenu a:hover 124 | { 125 | color: #fff; 126 | background-color: #666; 127 | text-decoration: none; 128 | } 129 | 130 | #container 131 | { 132 | border: 1px solid #0000CC; 133 | } 134 | 135 | #mainnav 136 | { 137 | background-color: #0000CC; 138 | color: #CCCCFF; 139 | padding: 2px 0; 140 | margin-bottom: 22px; 141 | } 142 | 143 | #mainnav ul 144 | { 145 | margin: 0 0 0 20px; 146 | padding: 0; 147 | list-style-type: none; 148 | border-left: 1px solid #CCCCFF; 149 | } 150 | 151 | #mainnav li 152 | { 153 | display: inline; 154 | padding: 0 10px; 155 | border-right: 1px solid #CCCCFF; 156 | } 157 | 158 | #mainnav li a 159 | { 160 | text-decoration: none; 161 | color: #CCCCFF; 162 | } 163 | 164 | #mainnav li a:hover 165 | { 166 | text-decoration: none; 167 | color: #0000CC; 168 | background-color: #CCCCFF; 169 | } 170 | 171 | #menu ul 172 | { 173 | margin-left: 0; 174 | padding-left: 0; 175 | list-style-type: none; 176 | line-height: 165%; 177 | } 178 | 179 | .imagefloat 180 | { 181 | padding: 2px; 182 | border: 1px solid #0000CC; 183 | margin: 0 0 10px 10px; 184 | } 185 | 186 | .blogentry ul 187 | { 188 | // list-style-type: none; 189 | // text-align: right; 190 | // margin: 1em 0; 191 | // padding: 0; 192 | list-style-type: square; 193 | margin: 10px 0px 15px -10px; 194 | // font-size: 95%; 195 | } 196 | 197 | .blogentry li 198 | { 199 | // display: inline; 200 | // padding: 0 0 0 7px; 201 | line-height: 150%; 202 | } 203 | 204 | #footer 205 | { 206 | background-color: #0000CC; 207 | padding: 5px; 208 | font-size: 90%; 209 | } 210 | 211 | -------------------------------------------------------------------------------- /doc/us/license.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Orbit 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 |
    16 | 17 | 20 |
    Orbit
    21 |
    MVC for Lua Web Development
    22 |
    23 | 24 |
    25 | 26 | 62 | 63 |
    64 | 65 | 66 | 67 |

    License

    68 | 69 | 70 | 71 |

    72 | Orbit is free software: it can be used for both academic 73 | and commercial purposes at absolutely no cost. There are no 74 | royalties or GNU-like "copyleft" restrictions. Orbit 75 | qualifies as 76 | Open Source 77 | software. 78 | Its licenses are compatible with 79 | GPL. 80 | Orbit is not in the public domain and the 81 | Kepler Project keeps its copyright. 82 | The legal details are below. 83 |

    84 | 85 | 86 | 87 |

    The spirit of the license is that you are free to use 88 | Orbit for any purpose at no cost without having to ask us. 89 | The only requirement is that if you do use Orbit, then you 90 | should give us credit by including the appropriate copyright notice 91 | somewhere in your product or its documentation.

    92 | 93 | 94 | 95 |

    The Orbit library is designed and implemented by Fabio Mascarenhas, 96 | André Carregal and Tomás Guisasola. 97 | The implementation is not derived from licensed software.

    98 | 99 | 100 | 101 |
    102 | 103 | 104 |

    Copyright © 2007-2008 The Kepler Project.

    105 | 106 | 107 | 108 |

    Permission is hereby granted, free of charge, to any person 109 | obtaining a copy of this software and associated documentation 110 | files (the "Software"), to deal in the Software without 111 | restriction, including without limitation the rights to use, copy, 112 | modify, merge, publish, distribute, sublicense, and/or sell copies 113 | of the Software, and to permit persons to whom the Software is 114 | furnished to do so, subject to the following conditions:

    115 | 116 | 117 | 118 |

    The above copyright notice and this permission notice shall be 119 | included in all copies or substantial portions of the Software.

    120 | 121 | 122 | 123 |

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 124 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 125 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 126 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 127 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 128 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 129 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 130 | SOFTWARE.

    131 | 132 | 133 | 134 | 135 | 136 |
    137 | 138 |
    139 | 140 |
    141 |

    Valid XHTML 1.0!

    142 |
    143 | 144 |
    145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Orbit 2.2.3 2 | http://keplerproject.github.com/orbit 3 | 4 | Orbit is an MVC web framework for Lua. The design is inspired by lightweight 5 | Ruby frameworks such as Camping. It completely abandons the CGILua model 6 | of "scripts" in favor of applications, where each Orbit application can fit 7 | in a single file, but you can split it into multiple files if you want. 8 | All Orbit applications follow the WSAPI protocol, so they currently work with 9 | Xavante, CGI and Fastcgi. It includes a launcher that makes it easy to launch 10 | a Xavante instance for development. 11 | 12 | History 13 | * Version 2.2.3 (16/Jul/2015) 14 | Fixed model:save() when using Postgres. The 'id' was being set to "NULL" and that violates the primary key constraint. 15 | NOT 5.2 compliant 16 | 17 | * Version 2.2.2 (10/Sep/2014) 18 | Added the ability to specify the offset in a model. This is useful for implimenting pagination. 19 | NOT 5.2 compliant 20 | 21 | * Version 2.2.1 (12/Jan/2014) 22 | bugfix release for Lua 5.1 23 | NOT 5.2 compliant 24 | documentation corrections 25 | support for Wsapi 1.6 and other dependency modules that no longer use "module" 26 | additional orbit model datatypes: real, float, timestamp, numeric 27 | MIME type application/json included 28 | 29 | * Version 2.2.0 (31/Mar/2010) 30 | Reparse response to resume the dispatcher 31 | better parser for orbit.model conditions, fixes parsing bugs 32 | orbit launcher has parameters to control logging and port 33 | op.cgi/op.fcgi launchers have the same parameters as wsapi.cgi/wsapi.fcgi 34 | Optional Sinatra-like (http://www.sinatrarb.com/) route parser, using LPEG 35 | Pluggable route parsers (route patterns can be strings or objects that answer to :match) 36 | 37 | * Version 2.1.0 (29/Oct/2009) 38 | better decoupling of orbit and orbit.model 39 | support for anything with a match method as patterns 40 | new options for orbit.model finders: distinct, fields 41 | count option for orbit.model now limits number of rows in the SQL 42 | logging of queries in orbit.model 43 | overhaul of the "orbit" script: better options, --help, sets application path 44 | content_type method in the web object to set content type 45 | support for PUT and DELETE (methods `dispatch_put` and `dispatch_delete`) 46 | orbit.model.recycle(*conn_builder*, *timeout*) function, to make a connection that automatically reopens after a certain time 47 | more samples in the samples folder 48 | added a "higher-order" $if to Orbit Pages 49 | 50 | * Version 2.0.2 (10/Mar/2009) 51 | url-decodes path captures (suggested by Ignacio Burgueno on a Jul 24 email to the Kepler list) 52 | added tutorial and new examples 53 | fixed escape.string 54 | web:delete_cookie receives a path parameter in order to correctly remove the cookie. Bug report and patch by Ignacio Burgueño 55 | stripping UTF-8 BOM from templates read from disk 56 | removing SoLazer files in order to make the Orbit package smaller 57 | added alternate name for integer (int) 58 | better error reporting for missing escape and convert functions 59 | removed toboolean 60 | fixed bugs 13451 and 25418: setting status 500 on application errors not throwing an error if file not exists when invalidating 61 | cache 62 | 63 | * Version 2.0.1 (10/Jun/2008): bug-fix release, fixed bug in Orbit pages' redirect function (thanks for Ignacio Burgueño for finding the bug) 64 | 65 | * Version 2.0 (06/Jun/2008): Complete rewrite of Orbit 66 | 67 | * Version 1.0: Initial release, obsolete 68 | 69 | Download and Installation 70 | 71 | The easiest way to download and install Orbit is via LuaRocks. You can install Orbit 72 | with a simple command: 73 | 74 | luarocks install orbit 75 | 76 | Go to the path where LuaRocks put Orbit to see the sample apps and this documentation. 77 | LuaRocks will automatically fetch and install any dependencies you don't already have. 78 | 79 | To run the supplied example, go to the samples/hello directory 80 | of this distribution and do: 81 | 82 | orbit hello.lua 83 | 84 | After the server is running go to your web browser. Some sample 85 | urls for hello.lua: 86 | 87 | http://127.0.0.1:8080/ will show "Hello World!" 88 | http://127.0.0.1:8080/say/foo will show "Hello foo!" 89 | http://127.0.0.1:8080/anythingelse will show "Not found!" 90 | 91 | For more information please check http://keplerproject.github.com/orbit 92 | -------------------------------------------------------------------------------- /doc/us/doc.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #47555c; 3 | font-size: 16px; 4 | font-family: "Open Sans", sans-serif; 5 | margin: 0; 6 | padding: 0; 7 | background: #eff4ff; 8 | } 9 | 10 | a:link { color: #008fee; } 11 | a:visited { color: #008fee; } 12 | a:hover { color: #22a7ff; } 13 | 14 | h1 { font-size:26px; } 15 | h2 { font-size:24px; } 16 | h3 { font-size:18px; } 17 | h4 { font-size:16px; } 18 | 19 | hr { 20 | height: 1px; 21 | background: #c1cce4; 22 | border: 0px; 23 | margin: 20px 0; 24 | } 25 | 26 | code { 27 | font-family: "Open Sans Mono", "Andale Mono", monospace; 28 | } 29 | 30 | tt { 31 | font-family: "Open Sans Mono", "Andale Mono", monospace; 32 | } 33 | 34 | body, td, th { 35 | } 36 | 37 | textarea, pre, tt { 38 | font-family: "Open Sans Mono", "Andale Mono", monospace; 39 | } 40 | 41 | img { 42 | border-width: 0px; 43 | } 44 | 45 | .example { 46 | background-color: #323744; 47 | color: white; 48 | font-size: 16px; 49 | padding: 16px 24px; 50 | border-radius: 2px; 51 | } 52 | 53 | div.header, div.footer { 54 | } 55 | 56 | #container { 57 | } 58 | 59 | #product { 60 | background-color: white; 61 | padding: 10px; 62 | height: 130px; 63 | border-bottom: solid #d3dbec 1px; 64 | } 65 | 66 | #product big { 67 | font-size: 42px; 68 | } 69 | #product strong { 70 | font-weight: normal; 71 | } 72 | 73 | #product_logo { 74 | float: right; 75 | } 76 | 77 | #product_name { 78 | padding-top: 15px; 79 | padding-left: 30px; 80 | font-size: 42px; 81 | font-weight: normal; 82 | } 83 | 84 | #product_description { 85 | padding-left: 30px; 86 | color: #757779; 87 | } 88 | 89 | #main { 90 | background: #eff4ff; 91 | margin: 0; 92 | } 93 | 94 | #navigation { 95 | width: 100%; 96 | background-color: rgb(44,62,103); 97 | padding: 10px; 98 | margin: 0; 99 | } 100 | 101 | #navigation h1 { 102 | display: none; 103 | } 104 | 105 | #navigation a:hover { 106 | text-decoration: underline; 107 | } 108 | 109 | #navigation ul li a { 110 | color: rgb(136, 208, 255); 111 | font-weight: bold; 112 | text-decoration: none; 113 | } 114 | 115 | #navigation ul li li a { 116 | color: rgb(136, 208, 255); 117 | font-weight: normal; 118 | text-decoration: none; 119 | } 120 | 121 | #navigation ul { 122 | display: inline; 123 | color: white; 124 | padding: 0px; 125 | padding-top: 10px; 126 | padding-bottom: 10px; 127 | } 128 | 129 | #navigation li { 130 | display: inline; 131 | list-style-type: none; 132 | padding-left: 5px; 133 | padding-right: 5px; 134 | } 135 | 136 | #navigation li { 137 | padding: 10px; 138 | padding: 10px; 139 | } 140 | 141 | #navigation li li { 142 | } 143 | 144 | #navigation li:hover a { 145 | color: rgb(166, 238, 255); 146 | } 147 | 148 | #content { 149 | padding: 20px; 150 | width: 800px; 151 | margin-left: auto; 152 | margin-right: auto; 153 | } 154 | 155 | #about { 156 | display: none; 157 | } 158 | 159 | dl.reference { 160 | background-color: white; 161 | padding: 20px; 162 | border: solid #d3dbec 1px; 163 | } 164 | 165 | dl.reference dt { 166 | padding: 5px; 167 | padding-top: 25px; 168 | color: #637bbc; 169 | } 170 | 171 | dl.reference dl dt { 172 | padding-top: 5px; 173 | color: #637383; 174 | } 175 | 176 | dl.reference dd { 177 | } 178 | 179 | @media print { 180 | body { 181 | font: 10pt "Times New Roman", "TimeNR", Times, serif; 182 | } 183 | a { 184 | font-weight:bold; color: #004080; text-decoration: underline; 185 | } 186 | #main { 187 | background-color: #ffffff; border-left: 0px; 188 | } 189 | #container { 190 | margin-left: 2%; margin-right: 2%; background-color: #ffffff; 191 | } 192 | #content { 193 | margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; 194 | } 195 | #navigation { 196 | display: none; 197 | } 198 | #product_logo { 199 | display: none; 200 | } 201 | #about img { 202 | display: none; 203 | } 204 | .example { 205 | font-family: "Andale Mono", monospace; 206 | font-size: 8pt; 207 | page-break-inside: avoid; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /samples/blog/blog_config.lua: -------------------------------------------------------------------------------- 1 | 2 | blog_title = "Blog" 3 | 4 | cache_path = "page_cache" 5 | 6 | copyright_notice = "Copyright 2007 Foobar" 7 | 8 | about_blurb = [[This is an example of a blog built using Orbit. You 9 | can browse posts and add comments, but to add new posts you have 10 | to go directly to the database. This will be fixed in the future.]] 11 | 12 | blogroll = { 13 | { "http://slashdot.org", "Slashdot"}, 14 | { "http://news.google.com", "Google News" }, 15 | { "http://www.wikipedia.org", "Wikipedia" }, 16 | } 17 | 18 | -- Uncomment this to send static files through X-Sendfile 19 | -- use_xsendfile = true 20 | 21 | database = { 22 | -- driver = "mysql", 23 | -- conn_data = { "blog", "root", "password" } 24 | driver = "sqlite3", 25 | conn_data = { real_path .. "/blog.db" } 26 | } 27 | 28 | recent_count = 7 29 | 30 | strings = {} 31 | 32 | strings.pt = { 33 | home_page_name = "Página Inicial", 34 | about_title = "Sobre o Blog", 35 | last_posts = "Últimos Posts", 36 | blogroll_title = "Links", 37 | archive_title = "Arquivo", 38 | anonymous_author = "Anônimo", 39 | no_posts = "No há posts publicados.", 40 | published_at = "Publicado às", 41 | comments = "Comentários", 42 | written_by = "Escrito por", 43 | on_date = "em", 44 | new_comment = "Novo comentário", 45 | no_comment = "Você esqueceu o comentário!", 46 | form_name = "Nome:", 47 | form_email = "Email:", 48 | form_url = "Site:", 49 | italics = "itálico", 50 | bold = "negrito", 51 | link = "link", 52 | send = "Enviar" 53 | } 54 | 55 | strings.en = { 56 | home_page_name = "Home Page", 57 | about_title = "About this Blog", 58 | last_posts = "Recent Posts", 59 | blogroll_title = "Links", 60 | archive_title = "Archives", 61 | anonymous_author = "Anonymous", 62 | no_posts = "No published posts.", 63 | published_at = "Published at", 64 | comments = "Comments", 65 | written_by = "Written by", 66 | on_date = "at", 67 | new_comment = "New comment", 68 | no_comment = "You forgot the comment!", 69 | form_name = "Name:", 70 | form_email = "Email:", 71 | form_url = "Site:", 72 | italics = "italics", 73 | bold = "bold", 74 | link = "link", 75 | send = "Send" 76 | } 77 | 78 | language = "en" 79 | 80 | strings = strings[language] 81 | 82 | months = {} 83 | 84 | months.pt = { "Janeiro", "Fevereiro", "Março", "Abril", 85 | "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", 86 | "Novembro", "Dezembro" } 87 | 88 | months.en = { "January", "February", "March", "April", 89 | "May", "June", "July", "August", "September", "October", 90 | "November", "December" } 91 | 92 | weekdays = {} 93 | 94 | weekdays.pt = { "Domingo", "Segunda", "Terça", "Quarta", 95 | "Quinta", "Sexta", "Sábado" } 96 | 97 | weekdays.en = { "Sunday", "Monday", "Tuesday", "Wednesday", 98 | "Thursday", "Friday", "Saturday" } 99 | 100 | -- Utility functions 101 | 102 | time = {} 103 | date = {} 104 | month = {} 105 | 106 | local datetime_mt = { __call = function (tab, date) return tab[language](date) end } 107 | 108 | setmetatable(time, datetime_mt) 109 | setmetatable(date, datetime_mt) 110 | setmetatable(month, datetime_mt) 111 | 112 | function time.pt(date) 113 | local time = os.date("%H:%M", date) 114 | date = os.date("*t", date) 115 | return date.day .. " de " 116 | .. months.pt[date.month] .. " de " .. date.year .. " às " .. time 117 | end 118 | 119 | function date.pt(date) 120 | date = os.date("*t", date) 121 | return weekdays.pt[date.wday] .. ", " .. date.day .. " de " 122 | .. months.pt[date.month] .. " de " .. date.year 123 | end 124 | 125 | function month.pt(month) 126 | return months.pt[month.month] .. " de " .. month.year 127 | end 128 | 129 | local function ordinalize(number) 130 | if number == 1 then 131 | return "1st" 132 | elseif number == 2 then 133 | return "2nd" 134 | elseif number == 3 then 135 | return "3rd" 136 | else 137 | return tostring(number) .. "th" 138 | end 139 | end 140 | 141 | function time.en(date) 142 | local time = os.date("%H:%M", date) 143 | date = os.date("*t", date) 144 | return months.en[date.month] .. " " .. ordinalize(date.day) .. " " .. 145 | date.year .. " at " .. time 146 | end 147 | 148 | function date.en(date) 149 | date = os.date("*t", date) 150 | return weekdays.en[date.wday] .. ", " .. months.en[date.month] .. " " .. 151 | ordinalize(date.day) .. " " .. date.year 152 | end 153 | 154 | function month.en(month) 155 | return months.en[month.month] .. " " .. month.year 156 | end 157 | 158 | -------------------------------------------------------------------------------- /samples/pages/css/doc.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-left: 1em; 3 | margin-right: 1em; 4 | font-family: arial, helvetica, geneva, sans-serif; 5 | background-color:#ffffff; margin:0px; 6 | } 7 | 8 | code { 9 | font-family: "Andale Mono", monospace; 10 | } 11 | 12 | tt { 13 | font-family: "Andale Mono", monospace; 14 | } 15 | 16 | body, td, th { font-size: 11pt; } 17 | 18 | h1, h2, h3, h4 { margin-left: 0em; } 19 | 20 | textarea, pre, tt { font-size:10pt; } 21 | body, td, th { color:#000000; } 22 | small { font-size:0.85em; } 23 | h1 { font-size:1.5em; } 24 | h2 { font-size:1.25em; } 25 | h3 { font-size:1.15em; } 26 | h4 { font-size:1.06em; } 27 | 28 | a:link { font-weight:bold; color: #004080; text-decoration: none; } 29 | a:visited { font-weight:bold; color: #006699; text-decoration: none; } 30 | a:link:hover { text-decoration:underline; } 31 | hr { color:#cccccc } 32 | img { border-width: 0px; } 33 | 34 | 35 | h3 { padding-top: 1em; } 36 | 37 | p { margin-left: 1em; } 38 | 39 | p.name { 40 | font-family: "Andale Mono", monospace; 41 | padding-top: 1em; 42 | margin-left: 0em; 43 | } 44 | 45 | blockquote { margin-left: 3em; } 46 | 47 | .example { 48 | background-color: rgb(245, 245, 245); 49 | border-top-width: 1px; 50 | border-right-width: 1px; 51 | border-bottom-width: 1px; 52 | border-left-width: 1px; 53 | border-top-style: solid; 54 | border-right-style: solid; 55 | border-bottom-style: solid; 56 | border-left-style: solid; 57 | border-top-color: silver; 58 | border-right-color: silver; 59 | border-bottom-color: silver; 60 | border-left-color: silver; 61 | padding: 1em; 62 | margin-left: 1em; 63 | margin-right: 1em; 64 | font-family: "Andale Mono", monospace; 65 | font-size: smaller; 66 | } 67 | 68 | 69 | hr { 70 | margin-left: 0em; 71 | background: #00007f; 72 | border: 0px; 73 | height: 1px; 74 | } 75 | 76 | ul { list-style-type: disc; } 77 | 78 | table.index { border: 1px #00007f; } 79 | table.index td { text-align: left; vertical-align: top; } 80 | table.index ul { padding-top: 0em; margin-top: 0em; } 81 | 82 | table { 83 | border: 1px solid black; 84 | border-collapse: collapse; 85 | margin-left: auto; 86 | margin-right: auto; 87 | } 88 | th { 89 | border: 1px solid black; 90 | padding: 0.5em; 91 | } 92 | td { 93 | border: 1px solid black; 94 | padding: 0.5em; 95 | } 96 | div.header, div.footer { margin-left: 0em; } 97 | 98 | #container 99 | { 100 | margin-left: 1em; 101 | margin-right: 1em; 102 | background-color: #f0f0f0; 103 | } 104 | 105 | #product 106 | { 107 | text-align: center; 108 | border-bottom: 1px solid #cccccc; 109 | background-color: #ffffff; 110 | } 111 | 112 | #product big { 113 | font-size: 2em; 114 | } 115 | 116 | #product_logo 117 | { 118 | } 119 | 120 | #product_name 121 | { 122 | } 123 | 124 | #product_description 125 | { 126 | } 127 | 128 | #main 129 | { 130 | background-color: #f0f0f0; 131 | border-left: 2px solid #cccccc; 132 | } 133 | 134 | #navigation 135 | { 136 | float: left; 137 | width: 12em; 138 | margin: 0; 139 | vertical-align: top; 140 | background-color: #f0f0f0; 141 | overflow:visible; 142 | } 143 | 144 | #navigation h1 { 145 | background-color:#e7e7e7; 146 | font-size:1.1em; 147 | color:#000000; 148 | text-align:left; 149 | margin:0px; 150 | padding:0.2em; 151 | border-top:1px solid #dddddd; 152 | border-bottom:1px solid #dddddd; 153 | } 154 | 155 | #navigation ul 156 | { 157 | font-size:1em; 158 | list-style-type: none; 159 | padding: 0; 160 | margin: 1px; 161 | } 162 | 163 | #navigation li 164 | { 165 | text-indent: -1em; 166 | margin: 0em 0em 0em 0.5em; 167 | display: block; 168 | padding: 3px 0px 0px 12px; 169 | } 170 | 171 | #navigation li li a 172 | { 173 | padding: 0px 3px 0px -1em; 174 | } 175 | 176 | #content 177 | { 178 | margin-left: 12em; 179 | padding: 1em; 180 | border-left: 2px solid #cccccc; 181 | border-right: 2px solid #cccccc; 182 | background-color: #ffffff; 183 | } 184 | 185 | #about 186 | { 187 | clear: both; 188 | margin: 0; 189 | padding: 5px; 190 | border-top: 2px solid #cccccc; 191 | background-color: #ffffff; 192 | } 193 | 194 | @media print { 195 | body { 196 | font: 10pt "Times New Roman", "TimeNR", Times, serif; 197 | } 198 | a { font-weight:bold; color: #004080; text-decoration: underline; } 199 | 200 | #main { background-color: #ffffff; border-left: 0px; } 201 | #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } 202 | 203 | #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } 204 | 205 | #navigation { display: none; 206 | } 207 | 208 | #product_logo 209 | { 210 | display: none; 211 | } 212 | 213 | #about img 214 | { 215 | display: none; 216 | } 217 | 218 | .example { 219 | font-family: "Andale Mono", monospace; 220 | font-size: 8pt; 221 | page-break-inside: avoid; 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /samples/toycms/toycms_plugins.lua: -------------------------------------------------------------------------------- 1 | 2 | function plugins.date(web) 3 | return { 4 | today_day = tonumber(os.date("%d", os.time())), 5 | today_month_name = month_names[tonumber(os.date("%m", os.time()))], 6 | today_year = tonumber(os.date("%Y", os.time())) 7 | } 8 | end 9 | 10 | function plugins.archive(web) 11 | return { 12 | month_list = function (arg, has_block) 13 | if arg and arg.include_tags then 14 | local sections = 15 | models.section:find_all("tag like ?", { arg.include_tags }) 16 | local section_ids = {} 17 | for _, section in ipairs(sections) do 18 | section_ids[#section_ids + 1] = section.id 19 | end 20 | local months = models.post:find_months(section_ids) 21 | local out, template 22 | if not has_block then 23 | out = {} 24 | template = load_template(arg.template or 25 | "month_list.html") 26 | end 27 | for _, month in ipairs(months) do 28 | local env = new_template_env(web) 29 | env.month = month.month 30 | env.year = month.year 31 | env.month_padded = string.format("%.2i", month.month) 32 | env.month_name = month_names[month.month] 33 | env.uri = web:link("/archive/" .. env.year .. "/" .. 34 | env.month_padded) 35 | if has_block then 36 | cosmo.yield(env) 37 | else 38 | local tdata = template(env) 39 | table.insert(out, tdata) 40 | end 41 | end 42 | if not has_block then return table.concat(out, "\n") end 43 | else 44 | return ((not has_block) and "") or nil 45 | end 46 | end 47 | } 48 | end 49 | 50 | function plugins.section_list(web) 51 | return { 52 | section_list = function (arg, has_block) 53 | arg = arg or {} 54 | local template_name = arg.template 55 | if arg.include_tags then 56 | arg = { arg.include_tags } 57 | arg.condition = "tag like ?" 58 | end 59 | local out, template 60 | if not has_block then 61 | out = {} 62 | template = load_template(template_name or 63 | "section_list.html") 64 | end 65 | local sections = models.section:find_all(arg.condition, arg) 66 | for _, section in ipairs(sections) do 67 | web.input.section_id = section.id 68 | local env = new_section_env(web, section) 69 | if has_block then 70 | cosmo.yield(env) 71 | else 72 | local tdata = template(env) 73 | table.insert(out, tdata) 74 | end 75 | end 76 | if not has_block then return table.concat(out, "\n") end 77 | end 78 | } 79 | end 80 | 81 | local function get_posts(web, condition, args, count, template) 82 | local posts = 83 | models.post:find_all(condition, args) 84 | local cur_date 85 | local out 86 | if template then out = {} end 87 | for i, post in ipairs(posts) do 88 | if count and (i > count) then break end 89 | local env = new_post_env(web, post) 90 | env.if_new_date = cosmo.cond(cur_date ~= env.date_string, env) 91 | if cur_date ~= env.date_string then 92 | cur_date = env.date_string 93 | end 94 | env.if_first = cosmo.cond(i == 1, env) 95 | env.if_not_first = cosmo.cond(i ~= 1, env) 96 | env.if_last = cosmo.cond(i == #posts, env) 97 | env.if_not_post = cosmo.cond(web.input.post_id ~= post.id, env) 98 | if template then 99 | local tdata = template(env) 100 | table.insert(out, tdata) 101 | else 102 | cosmo.yield(env) 103 | end 104 | end 105 | if template then return table.concat(out, "\n") end 106 | end 107 | 108 | function plugins.home(web) 109 | return { 110 | headlines = function (arg, has_block) 111 | local template 112 | if not has_block then 113 | template = load_template("home_short_info.html") 114 | end 115 | return get_posts(web, "in_home = ? and published = ?", 116 | { order = "published_at desc", true, true }, 117 | nil, template) 118 | end 119 | } 120 | end 121 | 122 | function plugins.index_view(web) 123 | return { 124 | show_posts = function (arg, has_block) 125 | local section_ids = {} 126 | local template_file = (arg and arg.template) or "index_short_info.html" 127 | if arg and arg.include_tags then 128 | local sections = models.section:find_by_tags{ arg.include_tags } 129 | for _, section in ipairs(sections) do 130 | section_ids[#section_ids + 1] = section.id 131 | end 132 | elseif web.input.section_id then 133 | section_ids[#section_ids + 1] = web.input.section_id 134 | end 135 | if #section_ids == 0 then return "" end 136 | local date_start, date_end 137 | if arg and arg.archive and web.input.month and web.input.year then 138 | date_start = os.time({ year = web.input.year, 139 | month = web.input.month, day = 1 }) 140 | date_end = os.time({ year = web.input.year + 141 | math.floor(web.input.month / 12), 142 | month = (web.input.month % 12) + 1, 143 | day = 1 }) 144 | end 145 | local template 146 | if not has_block then template = load_template(template_file) end 147 | return get_posts(web, "published = ? and section_id = ? and " .. 148 | "published_at >= ? and published_at <= ?", 149 | { order = "published_at desc", true, 150 | section_ids, date_start, 151 | date_end }, 152 | (arg and arg.count), template) 153 | end 154 | } 155 | end 156 | 157 | -------------------------------------------------------------------------------- /src/orbit/pages.lua: -------------------------------------------------------------------------------- 1 | 2 | local orbit = require "orbit" 3 | local model = require "orbit.model" 4 | local cosmo = require "cosmo" 5 | 6 | local io, string = io, string 7 | local setmetatable, loadstring, setfenv = setmetatable, loadstring, setfenv 8 | local type, error, tostring = type, error, tostring 9 | local print, pcall, xpcall, traceback = print, pcall, xpcall, debug.traceback 10 | local select, unpack = select, unpack 11 | 12 | local _G = _G 13 | 14 | module("orbit.pages", orbit.new) 15 | 16 | local template_cache = {} 17 | 18 | local BOM = string.char(239) .. string.char(187) .. string.char(191) 19 | 20 | local function remove_shebang(s) 21 | return s:gsub("^#![^\n]+", "") 22 | end 23 | 24 | local function splitpath(filename) 25 | local path, file = string.match(filename, "^(.*)[/\\]([^/\\]*)$") 26 | return path, file 27 | end 28 | 29 | function load(filename, contents) 30 | filename = filename or contents 31 | local template = template_cache[filename] 32 | if not template then 33 | if not contents then 34 | local file = io.open(filename) 35 | if not file then 36 | return nil 37 | end 38 | contents = file:read("*a") 39 | file:close() 40 | if contents:sub(1,3) == BOM then contents = contents:sub(4) end 41 | end 42 | template = cosmo.compile(remove_shebang(contents)) 43 | template_cache[filename] = template 44 | end 45 | return template 46 | end 47 | 48 | local function env_index(env, key) 49 | local val = _G[key] 50 | if not val and type(key) == "string" then 51 | local template = 52 | load(env.web.real_path .. "/" .. key .. ".op") 53 | if not template then return nil end 54 | return function (arg) 55 | arg = arg or {} 56 | if arg[1] then arg.it = arg[1] end 57 | local subt_env = setmetatable(arg, { __index = env }) 58 | return template(subt_env) 59 | end 60 | end 61 | return val 62 | end 63 | 64 | local function abort(res) 65 | error{ abort, res or "abort" } 66 | end 67 | 68 | local function make_env(web, initial) 69 | local env = setmetatable(initial or {}, { __index = env_index }) 70 | env._G = env 71 | env.app = _G 72 | env.web = web 73 | env.finish = abort 74 | function env.lua(arg) 75 | local f, err = loadstring(arg[1]) 76 | if not f then error(err .. " in \n" .. arg[1]) end 77 | setfenv(f, env) 78 | local ok, res = pcall(f) 79 | if not ok and (type(res)~= "table" or res[1] ~= abort) then 80 | error(res .. " in \n" .. arg[1]) 81 | elseif ok then 82 | return res or "" 83 | else 84 | abort(res[2]) 85 | end 86 | end 87 | env["if"] = function (arg) 88 | if type(arg[1]) == "function" then arg[1] = arg[1](select(2, unpack(arg))) end 89 | if arg[1] then 90 | cosmo.yield{ it = arg[1], _template = 1 } 91 | else 92 | cosmo.yield{ _template = 2 } 93 | end 94 | end 95 | function env.redirect(target) 96 | if type(target) == "table" then target = target[1] end 97 | web:redirect(target) 98 | abort() 99 | end 100 | function env.fill(arg) 101 | cosmo.yield(arg[1]) 102 | end 103 | function env.link(arg) 104 | local url = arg[1] 105 | arg[1] = nil 106 | return web:link(url, arg) 107 | end 108 | function env.static_link(arg) 109 | return web:static_link(arg[1]) 110 | end 111 | function env.include(name, subt_env) 112 | local filename 113 | if type(name) == "table" then 114 | name = name[1] 115 | subt_env = name[2] 116 | end 117 | if name:sub(1, 1) == "/" then 118 | filename = web.doc_root .. name 119 | else 120 | filename = web.real_path .. "/" .. name 121 | end 122 | local template = load(filename) 123 | if not template then return "" end 124 | if subt_env then 125 | if type(subt_env) ~= "table" then subt_env = { it = subt_env } end 126 | subt_env = setmetatable(subt_env, { __index = env }) 127 | else 128 | subt_env = env 129 | end 130 | return template(subt_env) 131 | end 132 | function env.forward(...) 133 | abort(env.include(...)) 134 | end 135 | env.mapper = model.new() 136 | function env.model(name, dao) 137 | if type(name) == "table" then 138 | name, dao = name[1], name[2] 139 | end 140 | return env.mapper:new(name, dao) 141 | end 142 | env.recycle = model.recycle 143 | return env 144 | end 145 | 146 | function fill(web, template, env) 147 | if template then 148 | local ok, res = xpcall(function () return template(make_env(web, env)) end, 149 | function (msg) 150 | if type(msg) == "table" and msg[1] == abort then 151 | return msg 152 | else 153 | return traceback(msg) 154 | end 155 | end) 156 | if not ok and (type(res) ~= "table" or res[1] ~= abort) then 157 | error(res) 158 | elseif ok then 159 | return res 160 | else 161 | return res[2] 162 | end 163 | end 164 | end 165 | 166 | function handle_get(web) 167 | local filename = web.path_translated 168 | web.real_path = splitpath(filename) 169 | local res = fill(web, load(filename)) 170 | if res then 171 | return res 172 | else 173 | web.status = 404 174 | return [[ 175 | Not Found 176 |

    Not found!

    ]] 177 | end 178 | end 179 | 180 | handle_post = handle_get 181 | 182 | return _M 183 | -------------------------------------------------------------------------------- /test/test_routes.lua: -------------------------------------------------------------------------------- 1 | 2 | local R = require "orbit.routes" 3 | 4 | do 5 | local r = R('/foo') 6 | local t = r:match("/foo") 7 | assert(t) 8 | assert(r:build() == "/foo") 9 | end 10 | 11 | do 12 | local r = R('/foo') 13 | local t = r:match("/bar") 14 | assert(not t) 15 | assert(r:build() == "/foo") 16 | end 17 | 18 | do 19 | local r = R('/foo') 20 | local t = r:match("/foobar") 21 | assert(not t) 22 | end 23 | 24 | do 25 | local r = R("/foo/bar/:baz") 26 | local t = r:match("/foo/bar/boo") 27 | assert(t.baz == "boo") 28 | assert(r:build{ baz = "boo"} == "/foo/bar/boo") 29 | assert(not pcall(r.build, r)) 30 | end 31 | 32 | do 33 | local r = R("/foo/bar/:baz") 34 | local t = r:match("/bar/boo") 35 | assert(not t) 36 | end 37 | 38 | do 39 | local r = R("/foo/bar/:baz") 40 | local t = r:match("/foo/bar/boo/bloo") 41 | assert(not t) 42 | end 43 | 44 | do 45 | local r = R("/say/:msg/to/:to") 46 | local t = r:match("/say/hello/to/world") 47 | assert(t.msg == "hello") 48 | assert(t.to == "world") 49 | assert(r:build{ msg = "hello", to = "world" } == "/say/hello/to/world") 50 | assert(r:build{ msg = "hello", to = 5 } == "/say/hello/to/5") 51 | end 52 | 53 | do 54 | local r = R('/say/*/to/*') 55 | local t = r:match('/say/hello/to/world') 56 | assert(#t.splat == 2) 57 | assert(t.splat[1] == "hello") 58 | assert(t.splat[2] == "world") 59 | assert(r:build{ splat = { "hello", "world" } } == "/say/hello/to/world") 60 | end 61 | 62 | do 63 | local r = R('/download/*.*') 64 | local t = r:match('/download/path/to/file.xml') 65 | assert(#t.splat == 2) 66 | assert(t.splat[1] == "path/to/file") 67 | assert(t.splat[2] == "xml") 68 | assert(r:build{ splat = { "path/to/file", "xml" } } == "/download/path/to/file.xml") 69 | end 70 | 71 | do 72 | local r = R('/*/foo/*/*') 73 | local t = r:match('/bar/foo/bling/baz/boom') 74 | assert(#t.splat == 3) 75 | assert(t.splat[1] == "bar") 76 | assert(t.splat[2] == "bling") 77 | assert(t.splat[3] == "baz/boom") 78 | assert(r:build{ splat = { "bar", "bling", "baz/boom" } } == "/bar/foo/bling/baz/boom") 79 | end 80 | 81 | do 82 | local r = R('/*/foo/*') 83 | local t = r:match('/bar/foo/bling/baz/boom') 84 | assert(#t.splat == 2) 85 | assert(t.splat[1] == "bar") 86 | assert(t.splat[2] == "bling/baz/boom") 87 | assert(r:build{ splat = { "bar", "bling/baz/boom" } } == "/bar/foo/bling/baz/boom") 88 | end 89 | 90 | do 91 | local r = R('/*/foo/*') 92 | local t = r:match('/bar/foo/') 93 | assert(#t.splat == 1) 94 | assert(t.splat[1] == "bar") 95 | assert(r:build{ splat = { "bar", "bling/baz/boom" } } == "/bar/foo/bling/baz/boom") 96 | end 97 | 98 | do 99 | local r = R('/*/foo/*') 100 | local t = r:match('/bar/foo') 101 | assert(#t.splat == 1) 102 | assert(t.splat[1] == "bar") 103 | assert(r:build{ splat = { "bar", "bling/baz/boom" } } == "/bar/foo/bling/baz/boom") 104 | end 105 | 106 | do 107 | local r = R('/:foo/*') 108 | local t = r:match('/foo/bar/baz') 109 | assert(#t.splat == 1) 110 | assert(t.foo == "foo") 111 | assert(t.splat[1] == "bar/baz") 112 | assert(r:build{ foo = "foo", splat = { "bar/baz" } } == "/foo/bar/baz") 113 | end 114 | 115 | do 116 | local r = R('/:foo/:bar') 117 | local t = r:match('/user@example.com/name') 118 | assert(t.foo == "user@example.com") 119 | assert(t.bar == "name") 120 | assert(r:build{ foo = "user@example.com", bar = "name" } == "/user@example.com/name") 121 | end 122 | 123 | do 124 | local r = R('/:foo.:bar') 125 | local t = r:match('/user@example.com') 126 | assert(t.foo == "user@example") 127 | assert(t.bar == "com") 128 | assert(r:build{ foo = "user@example", bar = "com" } == "/user@example.com") 129 | end 130 | 131 | do 132 | local r = R('/*') 133 | local t = r:match("/foo/bar/baz") 134 | assert(t.splat[1] == "foo/bar/baz") 135 | assert(r:build{ splat = { "foo/bar/baz" } } == "/foo/bar/baz") 136 | end 137 | 138 | do 139 | local r = R('/*') 140 | local t = r:match("/") 141 | assert(not t.splat[1]) 142 | assert(r:build{ splat = { "foo/bar/baz" } } == "/foo/bar/baz") 143 | end 144 | 145 | do 146 | local r = R('/*') 147 | local t = r:match("/") 148 | assert(not t.splat[1]) 149 | assert(r:build{} == "/") 150 | end 151 | 152 | do 153 | local r = R('/*') 154 | local t = r:match("") 155 | assert(not t.splat[1]) 156 | assert(r:build{ splat = { "foo/bar/baz" } } == "/foo/bar/baz") 157 | end 158 | 159 | do 160 | local r = R('/?:foo?/?:bar?') 161 | local t = r:match('/hello/world') 162 | assert(t.foo == 'hello') 163 | assert(t.bar == 'world') 164 | assert(r:build{ foo = "hello", bar = "world" } == "/hello/world") 165 | end 166 | 167 | do 168 | local r = R('/?:foo?/?:bar?') 169 | local t = r:match('/hello') 170 | assert(t.foo == 'hello') 171 | assert(not t.bar) 172 | assert(r:build{ foo = "hello" } == "/hello") 173 | end 174 | 175 | do 176 | local r = R('/?:foo?/?:bar?') 177 | local t = r:match('/') 178 | assert(not t.foo) 179 | assert(not t.bar) 180 | assert(r:build() == "/") 181 | end 182 | 183 | do 184 | local r = R('/:foo/*') 185 | local t = r:match('/hello%20world/how%20are%20you') 186 | assert(t.foo == "hello world") 187 | assert(t.splat[1] == "how are you") 188 | assert(r:build{ foo = "hello world", splat = { "how are you" } } == '/hello+world/how+are+you') 189 | end 190 | -------------------------------------------------------------------------------- /samples/toycms/cached.diff: -------------------------------------------------------------------------------- 1 | --- toycms.lua 2008-01-09 17:33:16.000000000 -0200 2 | +++ /var/www/toycms/toycms.lua 2008-01-10 19:12:34.000000000 -0200 3 | @@ -1,3 +1,5 @@ 4 | +#!/usr/bin/env launcher 5 | + 6 | require"orbit" 7 | require"markdown" 8 | require"cosmo" 9 | @@ -180,17 +182,113 @@ 10 | 11 | require"toycms_plugins" 12 | 13 | +local function readfile(filename) 14 | + local file = io.open(filename, "rb") 15 | + if file then 16 | + local contents = file:read("*a") 17 | + file:close() 18 | + return contents 19 | + else return nil end 20 | +end 21 | + 22 | +local function page_file(path_info) 23 | + path_info = string.sub(path_info, 2, #path_info) 24 | + path_info = string.gsub(path_info, "/", "-") 25 | + if path_info == "" then path_info = "index" end 26 | + return 'page-cache/' .. path_info .. '.html' 27 | +end 28 | + 29 | +local function parse_headers(s) 30 | + local headers = {} 31 | + for header in string.gmatch(s, "[^\r\n]+") do 32 | + local name, value = string.match(header, "^([^:]+):%s+(.+)$") 33 | + if headers[name] then 34 | + if type(headers[name]) == "table" then 35 | + table.insert(headers[name], value) 36 | + else 37 | + headers[name] = { headers[name], value } 38 | + end 39 | + else 40 | + headers[name] = value 41 | + end 42 | + end 43 | + return headers 44 | +end 45 | + 46 | +local function parse_response(contents) 47 | + local b, e = string.find(contents, "\r\n\r\n") 48 | + local headers = string.sub(contents, 1, b + 1) 49 | + local body = string.sub(contents, e + 1, #contents) 50 | + return parse_headers(headers), body 51 | +end 52 | + 53 | +local function get_page(path_info) 54 | + local filename = page_file(path_info) 55 | + local contents = readfile(filename) 56 | + if contents then 57 | +-- return parse_response(contents) 58 | + return contents 59 | + else 60 | + return nil 61 | + end 62 | +end 63 | + 64 | +local function writefile(filename, contents) 65 | + local file = io.open(filename, "wb") 66 | + if file then 67 | + file:write(contents) 68 | + file:close() 69 | + end 70 | +end 71 | + 72 | +local function joinheaders(headers) 73 | + local hs = {} 74 | + for k, v in pairs(headers) do 75 | + if type(v) == "table" then 76 | + for _, tv in ipairs(v) do 77 | + table.insert(hs, string.format("%s: %s", k, v)) 78 | + end 79 | + else 80 | + table.insert(hs, string.format("%s: %s", k, v)) 81 | + end 82 | + end 83 | + return table.concat(hs, "\r\n") 84 | +end 85 | + 86 | +local function write_page(headers, body, path_info) 87 | + local filename = page_file(path_info) 88 | +-- local contents = joinheaders(headers) .. "\r\n\r\n" .. body 89 | +-- writefile(filename, contents) 90 | + writefile(filename, body) 91 | +end 92 | + 93 | +local function cached(f) 94 | + return f 95 | +--[[ return function (app, ...) 96 | +-- local cached_headers, cached_page = get_page(app.path_info) 97 | + local cached_page = get_page(app.path_info) 98 | + if cached_page then 99 | +-- app.headers, app.response = cached_headers, cached_page 100 | + app.response = cached_page 101 | + else 102 | + f(app, ...) 103 | + write_page(app.headers, app.response, app.path_info) 104 | + end 105 | + end]] 106 | +end 107 | + 108 | toycms:add_controllers{ 109 | home_page = { "/", "/index", 110 | - get = function (app) 111 | + get = cached(function (app) 112 | local template = app:load_template("home.html") 113 | if template then 114 | app:render("index", { template = template, 115 | env = app:new_template_env() }) 116 | + 117 | else 118 | app.not_found.get(app) 119 | end 120 | - end 121 | + end) 122 | }, 123 | home_xml = { "/xml", 124 | get = function (app) 125 | @@ -204,7 +302,7 @@ 126 | end 127 | }, 128 | section = { "/section/(%d+)", 129 | - get = function (app, section_id) 130 | + get = cached(function (app, section_id) 131 | local section = app.models.section:find(tonumber(section_id)) 132 | if not section then return app.not_found.get(app) end 133 | local template = app:load_template("section_" .. 134 | @@ -216,7 +314,7 @@ 135 | else 136 | app.not_found.get(app) 137 | end 138 | - end 139 | + end) 140 | }, 141 | section_xml = { "/section/(%d+)/xml", 142 | get = function (app, section_id) 143 | @@ -236,7 +334,7 @@ 144 | end 145 | }, 146 | post = { "/post/(%d+)", 147 | - get = function (app, post_id) 148 | + get = cached(function (app, post_id) 149 | local post = app.models.post:find(tonumber(post_id)) 150 | if not post then return app.not_found.get(app) end 151 | local section = app.models.section:find(post.section_id) 152 | @@ -251,7 +349,7 @@ 153 | else 154 | app.not_found.get(app) 155 | end 156 | - end 157 | + end) 158 | }, 159 | post_xml = { "/post/(%d+)/xml", 160 | get = function (app, post_id) 161 | @@ -273,7 +371,7 @@ 162 | end 163 | }, 164 | archive = { "/archive/(%d+)/(%d+)", 165 | - get = function (app, year, month) 166 | + get = cached(function (app, year, month) 167 | local template = app:load_template("archive.html") 168 | if template then 169 | app.input.month = tonumber(month) 170 | @@ -287,7 +385,7 @@ 171 | else 172 | app.not_found.get(app) 173 | end 174 | - end 175 | + end) 176 | }, 177 | add_comment = { "/post/(%d+)/addcomment", 178 | post = function (app, post_id) 179 | -------------------------------------------------------------------------------- /doc/us/pages.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Orbit 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    14 | 15 |
    16 | 17 | 20 |
    Orbit
    21 |
    MVC for Lua Web Development
    22 |
    23 | 24 |
    25 | 26 | 62 | 63 |
    64 | 65 | 66 |

    Orbit Pages

    67 | 68 |

    Orbit Pages is a PHP-like programming environment built on top of Orbit. Orbit pages 69 | are HTML pages (but using the extension .op in a typical Orbit installation) that 70 | get dynamically converted into Orbit apps. They are launched by the op.cgi, op.fcgi 71 | and ophandler.lua launchers, for CGI, FastCGI, and Xavante, respectively. A standard 72 | Kepler installation includes support for Orbit pages by default.

    73 | 74 |

    An Orbit page is also a template that uses the Cosmo 75 | template language. The environment of this template is a sandbox that wraps the 76 | global environment and is recreated on each request. The main variable in this 77 | environment is the web variable, which is an Orbit request/response object. 78 | Other variables of note:

    79 | 80 |

    mapper - an instance of the default Orbit ORM

    81 | 82 |

    model(name, dao) - same as mapper:new(name, dao), except that if name 83 | is a tabel then calls mapper:new(name[1], name[2]), so you can use this in the 84 | template as $model{ name, dao }

    85 | 86 |

    app - the application's global environment, to be used as a session cache (for DB 87 | connections, for example) for persistent launchers

    88 | 89 |

    finish(res) - suspends the execution of the current page, and sends res as a 90 | response instead of the page's contents

    91 | 92 |

    redirect(target) - same as web:redirect(target) followed by finish(). If target 93 | is a table does web:redirect(target[1]), so you can use this in the template as 94 | $redirect{ target }

    95 | 96 |

    include(page, [env]) - evaluates the Orbit page in the file page (relative to the 97 | current page's path), optionally using the extra variables in env in the template's 98 | environment. Can also be used in the template as $include{ page, env }

    99 | 100 |

    forward(page, [env]) - aborts the execution of the current page and evaluates 101 | and sends the page in file page instead; otherwise same as include

    102 | 103 |

    There also a few more variables that should be used only in the template:

    104 | 105 |

    $lua{ code } - runs code in the same environment as the page, so 106 | code can change the template's variables and even define new ones

    107 | 108 |

    $if{ condition }[[ then-part ]],[[ else-part ]] - if condition is true then 109 | is replaced by the template evaluation of then-part, otherwise else-part. else-part 110 | is optional, defaulting to blank

    111 | 112 |

    $fill{ ... }[[ template ]] - replaced by the evaluation of template using the environment 113 | passed to fill (template does not inherit the variables of the page)

    114 | 115 |

    Below is a very simple Orbit page that shows most of the concepts above (including Cosmo 116 | concepts, see the Cosmo documentation for that):

    117 | 118 |
        #!/usr/bin/env op.cgi
    119 |     <html>
    120 |     <body>
    121 |     <p>Hello Orbit!</p>
    122 |     <p>I am in $web|real_path, and the script is
    123 |     $web|script_name.</p>
    124 |     $lua{[[
    125 |       if not web.input.msg then
    126 |         web.input.msg = "nothing"
    127 |       end
    128 |     ]]}
    129 |     <p>You passed: $web|input|msg.</p>
    130 |     $include{ "bar.op" }
    131 |     </body>
    132 |     </html>
    133 | 
    134 | 135 |

    The bar.op page it includes is this:

    136 | 137 |
        #!/usr/bin/env op.cgi
    138 |     <p>This is bar, and you passed $web|input|msg!</p>
    139 | 
    140 | 141 |

    The Kepler distribution has a more complete example that has database 142 | access, POST, and even some simple AJAX.

    143 | 144 | 145 | 146 |
    147 | 148 |
    149 | 150 |
    151 |

    Valid XHTML 1.0!

    152 |
    153 | 154 |
    155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /src/orbit/routes.lua: -------------------------------------------------------------------------------- 1 | local setmetatable, type, ipairs, table, string = setmetatable, type, ipairs, table, string 2 | 3 | local lpeg = require "lpeg" 4 | local re = require "re" 5 | local util = require "wsapi.util" 6 | 7 | local _M = {} 8 | 9 | local alpha = lpeg.R('AZ', 'az') 10 | local number = lpeg.R('09') 11 | local asterisk = lpeg.P('*') 12 | local question_mark = lpeg.P('?') 13 | local at_sign = lpeg.P('@') 14 | local colon = lpeg.P(':') 15 | local the_dot = lpeg.P('.') 16 | local underscore = lpeg.P('_') 17 | local forward_slash = lpeg.P('/') 18 | local slash_or_dot = forward_slash + the_dot 19 | 20 | local function cap_param(prefix, name, dot) 21 | local inner = (1 - lpeg.S('/' .. (dot or '')))^1 22 | local close = lpeg.P'/' + (dot or -1) + -1 23 | return { 24 | cap = lpeg.Carg(1) * slash_or_dot * lpeg.C(inner^1) * #close / function (params, item, delim) params[name] = util.url_decode(item) end, 25 | clean = slash_or_dot * inner^1 * #close, 26 | tag = "param", 27 | name = name, 28 | prefix = prefix 29 | } 30 | end 31 | 32 | local param_pre = lpeg.C(slash_or_dot) * colon * lpeg.C((alpha + number + underscore)^1) 33 | 34 | local param = (param_pre * #(forward_slash + -1) / cap_param) + 35 | (param_pre * #the_dot / function (prefix, name) return cap_param(prefix, name, ".") end) 36 | 37 | local function cap_opt_param(prefix, name, dot) 38 | local inner = (1 - lpeg.S('/' .. (dot or '')))^1 39 | local close = lpeg.P('/') + lpeg.P(dot or -1) + -1 40 | return { 41 | cap = (lpeg.Carg(1) * slash_or_dot * lpeg.C(inner) * #close / function (params, item, delim) params[name] = util.url_decode(item) end)^-1, 42 | clean = (slash_or_dot * inner * #lpeg.C(close))^-1, 43 | tag = "opt", 44 | name = name, 45 | prefix = prefix 46 | } 47 | end 48 | 49 | local opt_param_pre = lpeg.C(slash_or_dot) * question_mark * colon * lpeg.C((alpha + number + underscore)^1) * question_mark 50 | 51 | local opt_param = (opt_param_pre * #(forward_slash + -1) / cap_opt_param) + 52 | (opt_param_pre * #the_dot / function (prefix, name) return cap_opt_param(prefix, name, ".") end) 53 | 54 | local splat = lpeg.P(lpeg.C(forward_slash + the_dot) * asterisk * #(forward_slash + the_dot + -1)) / 55 | function (prefix) 56 | return { 57 | cap = "*", 58 | tag = "splat", 59 | prefix = prefix 60 | } 61 | end 62 | 63 | local rest = lpeg.C((1 - param - opt_param - splat)^1) 64 | 65 | local function fold_captures(cap, acc) 66 | if type(cap) == "string" then 67 | return { 68 | cap = lpeg.P(cap) * acc.cap, 69 | clean = lpeg.P(cap) * acc.clean 70 | } 71 | end 72 | 73 | -- if we have a star match (match everything) 74 | if cap.cap == "*" then 75 | return { 76 | cap = (lpeg.Carg(1) * (cap.prefix * lpeg.C((1 - acc.clean)^0))^-1 / 77 | function (params, splat) 78 | params.splat = params.splat or {} 79 | if splat and splat ~= "" then 80 | params.splat[#params.splat+1] = util.url_decode(splat) 81 | end 82 | end) * acc.cap, 83 | clean = (cap.prefix * (1 - acc.clean)^0)^-1 * acc.clean 84 | } 85 | end 86 | 87 | return { 88 | cap = cap.cap * acc.cap, 89 | clean = cap.clean * acc.clean 90 | } 91 | end 92 | 93 | local function fold_parts(parts, cap) 94 | 95 | if type(cap) == "string" then -- if the capture is a string 96 | parts[#parts+1] = { 97 | tag = "text", 98 | text = cap 99 | } 100 | else -- it must be a table capture 101 | parts[#parts+1] = { 102 | tag = cap.tag, 103 | prefix = cap.prefix, 104 | name = cap.name 105 | } 106 | end 107 | 108 | return parts 109 | end 110 | 111 | -- the right part (a bottom to top loop) 112 | local function fold_right(t, f, acc) 113 | for i = #t, 1, -1 do 114 | acc = f(t[i], acc) 115 | end 116 | return acc 117 | end 118 | 119 | -- the left part (a top to bottom loop) 120 | local function fold_left(t, f, acc) 121 | for i = 1, #t do 122 | acc = f(acc, t[i]) 123 | end 124 | return acc 125 | end 126 | 127 | local route = lpeg.Ct((param + opt_param + splat + rest)^0 * -1) / function (caps) 128 | local forward_slash_at_end = lpeg.P('/')^-1 * -1 129 | return fold_right(caps, fold_captures, { cap = forward_slash_at_end, clean = forward_slash_at_end }), fold_left(caps, fold_parts, {}) 130 | end 131 | 132 | local function build(parts, params) 133 | local res, i = {}, 1 134 | params = params or {} 135 | params.splat = params.splat or {} 136 | for _, part in ipairs(parts) do 137 | if part.tag == 'param' then 138 | if not params[part.name] then error('route parameter ' .. part.name .. ' does not exist') end 139 | local s = string.gsub (params[part.name], '([^%.@]+)', function (s) return util.url_encode(s) end) 140 | res[#res+1] = part.prefix .. s 141 | elseif part.tag == "splat" then 142 | local s = string.gsub (params.splat[i] or '', '([^/%.@]+)', function (s) return util.url_encode(s) end) 143 | res[#res+1] = part.prefix .. s 144 | i = i + 1 145 | elseif part.tag == "opt" then 146 | if params and params[part.name] then 147 | local s = string.gsub (params[part.name], '([^%.@]+)', function (s) return util.url_encode(s) end) 148 | res[#res+1] = part.prefix .. s 149 | end 150 | else 151 | res[#res+1] = part.text 152 | end 153 | end 154 | 155 | if #res > 0 then 156 | return table.concat(res) 157 | end 158 | 159 | return '/' 160 | end 161 | 162 | function _M.R(path) 163 | local p, b = route:match(path) 164 | 165 | return setmetatable({ 166 | parser = p.cap, 167 | parts = b 168 | }, { 169 | __index = { 170 | match = function (t, s) 171 | local params = {} 172 | if t.parser:match(s, 1, params) then 173 | return params 174 | end 175 | return nil 176 | end, 177 | build = function (t, params) 178 | return build(t.parts, params) 179 | end 180 | } 181 | }) 182 | 183 | end 184 | 185 | return setmetatable(_M, { 186 | __call = function (_, path) 187 | return _M.R(path) 188 | end 189 | }) 190 | -------------------------------------------------------------------------------- /samples/pages/test.op: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env op.cgi 2 | 3 | 5 | 6 | 7 | Orbit Pages Test 8 | 9 | 10 | $lua{[[ 11 | if web.input.user then 12 | web:set_cookie("cookie_kepler", web.input.user) 13 | end 14 | ]]} 15 | 16 | 17 | 18 | 19 |
    20 | 21 |
    22 | 25 |
    26 |
    Orbit Pages simple tests
    27 |
    28 | 29 |
    30 | 31 | 56 | 57 |
    58 | 59 | 60 |

    Form Handling

    61 | 62 |

    63 | Entering values on this form should display them as values in the first submission, 64 | and as a cookie in the next submission 65 |

    66 | 67 |
    68 | 69 | 70 | 71 | 72 |
    73 | 74 |

    75 | The values should show the previous POST 76 |

    77 | 78 |

    79 | Values: Username = $if{$web|input|user}[[$it]],[[(not set)]], Password = $if{$web|input|pass}[[$it]],[[(not set)]] 80 |

    81 | 82 |

    Cookies test

    83 | 84 |

    85 | Here you should see the values posted before the ones shown above 86 |

    87 | 88 |

    89 | cookie_kepler = $if{$web|cookies|cookie_kepler}[[$it]],[[(not set)]] 90 |

    91 | 92 |

    File Upload

    93 | 94 |

    Choose a file to upload, press "Upload" and a link to the file should 95 | appear below with the corresponding "Remove" button. 96 |

    97 | 98 | 99 |
    100 | 101 | $lua{[[ 102 | local f = web.input.file 103 | upload = {} 104 | if f then 105 | local name = f.name 106 | local bytes = f.contents 107 | local dest = io.open(web.real_path .. "/" .. name, "wb") 108 | if dest then 109 | dest:write(bytes) 110 | dest:close() 111 | upload[1] = name 112 | end 113 | end 114 | ]]} 115 | $upload[[ 116 | $it 117 |
    118 | 119 | 120 |
    121 | ]] 122 | $lua{[[ 123 | if web.input.remove then 124 | os.remove(web.input.filename) 125 | end 126 | ]]} 127 | 128 | $lua{[=[ 129 | function showtable(arg) 130 | local t = arg[1] 131 | local out = {} 132 | local put = function (s) table.insert(out, s) end 133 | put "{" 134 | for i,v in pairs (t) do 135 | put("\n") 136 | if type(v) == "table" then 137 | local vv = "{\n" 138 | for a,b in pairs(v) do 139 | vv = string.format ("%s %s = [[%s]],\n", vv, a, tostring(b)) 140 | end 141 | v = vv.." }," 142 | put (string.format (" %s = %s", i, tostring(v))) 143 | else 144 | put (string.format (" %s = [[%s]],", i, tostring(v))) 145 | end 146 | end 147 | if next(t) then 148 | put "\n" 149 | end 150 | put "}\n" 151 | return table.concat(out) 152 | end 153 | ]=]} 154 | 155 |

    web.GET

    156 | 157 |
    158 | $showtable{ $web|GET }
    159 | 
    160 | 161 |

    web.POST

    162 | 163 |
    164 | $showtable{ $web|POST }
    165 | 
    166 | 167 |

    Web Variables

    168 | 169 | 170 | $lua{[[ 171 | vars = { 172 | "real_path", "path_info", "doc_root", "script_name", "path_translated", "prefix", "method" 173 | } 174 | webvar = function (arg) return web[arg[1] ] end 175 | ]]} 176 | $vars[[ 177 | 178 | ]] 179 |
    web.$it$webvar{ $it }
    180 | 181 | 182 |

    Server Variables

    183 | 184 | 185 | $lua{[[ 186 | vars = { 187 | "SERVER_SOFTWARE", "SERVER_NAME", "SERVER_PROTOCOL", "SERVER_PORT", 188 | "GATEWAY_INTERFACE", "REQUEST_METHOD", 189 | "SCRIPT_NAME", "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", 190 | "CONTENT_TYPE", "CONTENT_LENGTH", 191 | "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_USER", "REMOTE_IDENT", 192 | "AUTH_TYPE", 193 | } 194 | servervar = function (arg) return web.vars[arg[1] ] end 195 | ]]} 196 | $vars[[ 197 | 198 | ]] 199 |
    $it$servervar{ $it }
    200 | 201 |

    Date

    202 | 203 |

    Today is: $os|date

    204 | 205 |

    Image test

    206 | 207 |

    Here should be a small image: a small photograph

    208 | 209 |

    FileSystem test

    210 | 211 |

    212 | $lua{[[ 213 | dirname = web.doc_root or "" 214 | dir = {} 215 | for file in lfs.dir(dirname) do dir[#dir + 1] = "   "..file.."
    " end 216 | ]]} 217 | Iterating over $dirname $dir[[$it]] 218 |

    219 | 220 |

    Containment test

    221 | 222 |

    223 | $lua{[[ if not x then x = 1 else x = x + 1 end ]]} 224 | Expected value: 1, actual value: $x. 225 |

    226 | 227 | 228 |
    229 | 230 |
    231 | 232 |
    233 |

    Valid XHTML 1.0

    234 |

    $Id: test.op,v 1.1 2008/06/30 14:29:59 carregal Exp $

    235 |
    236 | 237 |
    238 | 239 | 240 | -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/stylesheet.css: -------------------------------------------------------------------------------- 1 | .sc-button-view.sc-static-layout{margin:0 4px;} 2 | .sc-button-view{display:inline-block;vertical-align:middle;text-decoration:none;} 3 | .sc-button-view .sc-button-inner{position:relative;display:block;height:100%;text-align:center;} 4 | .sc-button-view label{position:relative;display:block;line-height:21px;text-align:center;} 5 | .sc-button-view img{vertical-align:middle;margin-right:2px;position:relative;top:-2px;left:-2px;} 6 | .sc-view{font-family:"Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;font-size:12px;line-height:1.4;} 7 | .ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis;-ms-text-overflow:ellipsis;} 8 | .sc-view body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;} 9 | .sc-view table{border-collapse:collapse;border-spacing:0;} 10 | .sc-view fieldset,.sc-view img{border:0;} 11 | .sc-view address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;} 12 | .sc-view del,.sc-view ins{text-decoration:none;} 13 | .sc-view li{list-style:none;} 14 | .sc-view caption,th{text-align:left;} 15 | .sc-view h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;} 16 | .sc-view q:before,q:after{content:'';} 17 | .sc-view abbr,acronym{border:0;font-variant:normal;} 18 | .sc-view sup{vertical-align:baseline;} 19 | .sc-view sub{vertical-align:baseline;} 20 | .sc-view legend{color:#000;} 21 | .sc-view input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;} 22 | .sc-view input,button,textarea,select{font-size:100%;} 23 | .sc-view body{font:13px/1.231 "Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;*font-size:small;*font:x-small;} 24 | .sc-view select,input,button,textarea,button{font:99% "Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;} 25 | .sc-view table{font-size:inherit;font:100%;} 26 | .sc-view pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;} 27 | .sc-view body{margin:10px;} 28 | .sc-view h1{font-size:138.5%;} 29 | .sc-view h2{font-size:123.1%;} 30 | .sc-view h3{font-size:108%;} 31 | .sc-view h1,h2,h3{margin:1em 0;} 32 | .sc-view h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;} 33 | .sc-view optgroup{font-weight:normal;} 34 | .sc-view abbr,acronym{border-bottom:1px dotted #000;cursor:help;} 35 | .sc-view em{font-style:italic;} 36 | .sc-view del{text-decoration:line-through;} 37 | .sc-view blockquote,ul,ol,dl{margin:1em;} 38 | .sc-view ol,ul,dl{margin-left:2em;} 39 | .sc-view ol li{list-style:decimal outside;} 40 | .sc-view ul li{list-style:disc outside;} 41 | .sc-view dl dd{margin-left:1em;} 42 | .sc-view th,td{border:1px solid #000;padding:.5em;} 43 | .sc-view th{font-weight:bold;text-align:center;} 44 | .sc-view caption{margin-bottom:.5em;text-align:center;} 45 | .sc-view sup{vertical-align:super;} 46 | .sc-view sub{vertical-align:sub;} 47 | .sc-view p,fieldset,table,pre{margin-bottom:1em;} 48 | .sc-view button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;} 49 | .sc-benchmark-graph{z-index:100000;background-color:white;position:absolute;top:0;left:0;bottom:0;overflow:auto;right:0;} 50 | .sc-benchmark-title{font-size:12px;font-weight:bold;position:absolute;left:0;top:5px;} 51 | .sc-benchmark-emphasis{font-weight:bold;} 52 | .sc-benchmark-top{height:20px;left:0;top:25px;background-color:#ccc;opacity:.4;position:relative;border-top:1px solid #aaa;border-bottom:1px solid #aaa;} 53 | .sc-benchmark-tick{width:1px;height:2000px;position:absolute;top:25px;background-color:#ccc;} 54 | .sc-benchmark-tick-label{width:40px;position:absolute;top:27px;font-size:10px;margin-left:2px;white-space:nowrap;} 55 | .sc-benchmark-bar{height:16px;position:absolute;font-size:10px;white-space:nowrap;border:1px solid #C63;background-color:#FC3;-moz-border-radius:2px;-webkit-border-radius:2px;line-height:14px;} 56 | .sc-benchmark-row{position:absolute;left:0;height:30px;} 57 | .sc-benchmark-row.even{opacity:.4;background-color:#ddd;} 58 | .mozilla .sc-view .sc-text-field-view.inline-editor .border,.webkit .sc-view .sc-text-field-view.inline-editor .border,.msie .sc-view .sc-text-field-view.inline-editor .border,.sc-view .sc-text-field-view.inline-editor .border{-webkit-appearance:none;-moz-appearance:none;border:none;} 59 | .mozilla .sc-view .sc-text-field-view.inline-editor.focus{outline-offset:0;} 60 | .sc-label-view.sc-large-size{font-size:18px;line-height:24px;} 61 | .sc-label-view.sc-regular-size{font-size:12px;line-height:19px;} 62 | .sc-label-view.sc-small-size{font-size:11px;line-height:14px;} 63 | .sc-label-view.sc-tiny-size{font-size:9px;line-height:12px;} 64 | .sc-label-view.disabled{color:#999;color:rgba(50,50,50,0.5);} 65 | .sc-label-view img.icon{position:relative;vertical-align:middle;} 66 | .sc-label-view .sc-hint{position:absolute;top:3px;left:1px;right:1px;bottom:3px;padding:0;color:#aaa;font-size:12px;} 67 | .sc-static-layout,.sc-view.sc-static-layout{position:relative;} 68 | .sc-view .sc-text-field-view{border:none;z-index:100;overflow:visible;background:white;} 69 | .safari .sc-view .sc-text-field-view.focus{outline:auto 7px -webkit-focus-ring-color;outline-offset:-2px;} 70 | .mozilla .sc-view .sc-text-field-view.focus{outline-color:-moz-mac-focusring;outline-offset:-5px;outline-style:solid;outline-width:3px;} 71 | .msie .sc-view .sc-text-field-view.focus{outline:1px dotted;} 72 | .sc-text-field-view .border{position:absolute;top:0;left:0;bottom:0;right:0;} 73 | .mozilla .sc-view .sc-text-field-view .border{-moz-appearance:textfield;} 74 | .msie .sc-view .sc-text-field-view .border{border:1px inset;} 75 | .safari .sc-text-field-view .border{-webkit-appearance:textfield;} 76 | .sc-view .sc-text-field-view .padding{top:0;left:3px;bottom:0;right:3px;position:absolute;} 77 | .sc-view .sc-text-field-view.text-area .padding{right:0;} 78 | .sc-view .sc-text-field-view .sc-text-field-accessory-view{z-index:2;} 79 | .sc-text-field-view input{position:absolute;top:0;left:0;width:100%;height:100%;line-height:100%;bottom:0;right:0;display:block;background:transparent;vertical-align:middle;} 80 | .msie .sc-text-field-view input{line-height:1.8em;} 81 | .mozilla .sc-text-field-view input{top:3px;} 82 | .sc-text-field-view textarea{position:absolute;top:0;left:0;width:100%;bottom:0;right:0;height:100%;display:block;background:transparent;vertical-align:middle;resize:none;line-height:1.8em;overflow:auto;} 83 | .sc-text-field-view .sc-hint{z-index:1;position:absolute;top:3px;left:1px;right:1px;bottom:3px;padding:0;color:#aaa;font-size:12px;} 84 | .sc-text-field-view.text-area .sc-hint{top:2px;left:3px;right:3px;bottom:2px;} 85 | .sc-text-field-view.focus .sc-hint,.sc-text-field-view.not-empty .sc-hint{display:none;} 86 | .sc-view{cursor:default;overflow:hidden;position:absolute;-moz-user-select:none;-khtml-user-select:none;user-select:none;margin:0;} 87 | .sc-view.allow-select{-moz-user-select:text;-khtml-user-select:text;user-select:text;cursor:text;} 88 | .sc-view:focus,a.sc-view:focus,.sc-view:active,a.sc-view:active{outline:none;} 89 | .sc-view img{border:none;} 90 | .sc-view.hidden{display:none!important;} 91 | .sc-view.textAlignRight{text-align:right;} -------------------------------------------------------------------------------- /samples/sproutcore/static/sproutcore/foundation/en/bcfdf5ca1125ccb312799938d8f09a81676f5db0/stylesheet-packed.css: -------------------------------------------------------------------------------- 1 | .sc-button-view.sc-static-layout{margin:0 4px;} 2 | .sc-button-view{display:inline-block;vertical-align:middle;text-decoration:none;} 3 | .sc-button-view .sc-button-inner{position:relative;display:block;height:100%;text-align:center;} 4 | .sc-button-view label{position:relative;display:block;line-height:21px;text-align:center;} 5 | .sc-button-view img{vertical-align:middle;margin-right:2px;position:relative;top:-2px;left:-2px;} 6 | .sc-view{font-family:"Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;font-size:12px;line-height:1.4;} 7 | .ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-o-text-overflow:ellipsis;-ms-text-overflow:ellipsis;} 8 | .sc-view body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;} 9 | .sc-view table{border-collapse:collapse;border-spacing:0;} 10 | .sc-view fieldset,.sc-view img{border:0;} 11 | .sc-view address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;} 12 | .sc-view del,.sc-view ins{text-decoration:none;} 13 | .sc-view li{list-style:none;} 14 | .sc-view caption,th{text-align:left;} 15 | .sc-view h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;} 16 | .sc-view q:before,q:after{content:'';} 17 | .sc-view abbr,acronym{border:0;font-variant:normal;} 18 | .sc-view sup{vertical-align:baseline;} 19 | .sc-view sub{vertical-align:baseline;} 20 | .sc-view legend{color:#000;} 21 | .sc-view input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;} 22 | .sc-view input,button,textarea,select{font-size:100%;} 23 | .sc-view body{font:13px/1.231 "Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;*font-size:small;*font:x-small;} 24 | .sc-view select,input,button,textarea,button{font:99% "Lucida Sans","Lucida Grande",Verdana,Arial,sans-serif;} 25 | .sc-view table{font-size:inherit;font:100%;} 26 | .sc-view pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;} 27 | .sc-view body{margin:10px;} 28 | .sc-view h1{font-size:138.5%;} 29 | .sc-view h2{font-size:123.1%;} 30 | .sc-view h3{font-size:108%;} 31 | .sc-view h1,h2,h3{margin:1em 0;} 32 | .sc-view h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;} 33 | .sc-view optgroup{font-weight:normal;} 34 | .sc-view abbr,acronym{border-bottom:1px dotted #000;cursor:help;} 35 | .sc-view em{font-style:italic;} 36 | .sc-view del{text-decoration:line-through;} 37 | .sc-view blockquote,ul,ol,dl{margin:1em;} 38 | .sc-view ol,ul,dl{margin-left:2em;} 39 | .sc-view ol li{list-style:decimal outside;} 40 | .sc-view ul li{list-style:disc outside;} 41 | .sc-view dl dd{margin-left:1em;} 42 | .sc-view th,td{border:1px solid #000;padding:.5em;} 43 | .sc-view th{font-weight:bold;text-align:center;} 44 | .sc-view caption{margin-bottom:.5em;text-align:center;} 45 | .sc-view sup{vertical-align:super;} 46 | .sc-view sub{vertical-align:sub;} 47 | .sc-view p,fieldset,table,pre{margin-bottom:1em;} 48 | .sc-view button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;} 49 | .sc-benchmark-graph{z-index:100000;background-color:white;position:absolute;top:0;left:0;bottom:0;overflow:auto;right:0;} 50 | .sc-benchmark-title{font-size:12px;font-weight:bold;position:absolute;left:0;top:5px;} 51 | .sc-benchmark-emphasis{font-weight:bold;} 52 | .sc-benchmark-top{height:20px;left:0;top:25px;background-color:#ccc;opacity:.4;position:relative;border-top:1px solid #aaa;border-bottom:1px solid #aaa;} 53 | .sc-benchmark-tick{width:1px;height:2000px;position:absolute;top:25px;background-color:#ccc;} 54 | .sc-benchmark-tick-label{width:40px;position:absolute;top:27px;font-size:10px;margin-left:2px;white-space:nowrap;} 55 | .sc-benchmark-bar{height:16px;position:absolute;font-size:10px;white-space:nowrap;border:1px solid #C63;background-color:#FC3;-moz-border-radius:2px;-webkit-border-radius:2px;line-height:14px;} 56 | .sc-benchmark-row{position:absolute;left:0;height:30px;} 57 | .sc-benchmark-row.even{opacity:.4;background-color:#ddd;} 58 | .mozilla .sc-view .sc-text-field-view.inline-editor .border,.webkit .sc-view .sc-text-field-view.inline-editor .border,.msie .sc-view .sc-text-field-view.inline-editor .border,.sc-view .sc-text-field-view.inline-editor .border{-webkit-appearance:none;-moz-appearance:none;border:none;} 59 | .mozilla .sc-view .sc-text-field-view.inline-editor.focus{outline-offset:0;} 60 | .sc-label-view.sc-large-size{font-size:18px;line-height:24px;} 61 | .sc-label-view.sc-regular-size{font-size:12px;line-height:19px;} 62 | .sc-label-view.sc-small-size{font-size:11px;line-height:14px;} 63 | .sc-label-view.sc-tiny-size{font-size:9px;line-height:12px;} 64 | .sc-label-view.disabled{color:#999;color:rgba(50,50,50,0.5);} 65 | .sc-label-view img.icon{position:relative;vertical-align:middle;} 66 | .sc-label-view .sc-hint{position:absolute;top:3px;left:1px;right:1px;bottom:3px;padding:0;color:#aaa;font-size:12px;} 67 | .sc-static-layout,.sc-view.sc-static-layout{position:relative;} 68 | .sc-view .sc-text-field-view{border:none;z-index:100;overflow:visible;background:white;} 69 | .safari .sc-view .sc-text-field-view.focus{outline:auto 7px -webkit-focus-ring-color;outline-offset:-2px;} 70 | .mozilla .sc-view .sc-text-field-view.focus{outline-color:-moz-mac-focusring;outline-offset:-5px;outline-style:solid;outline-width:3px;} 71 | .msie .sc-view .sc-text-field-view.focus{outline:1px dotted;} 72 | .sc-text-field-view .border{position:absolute;top:0;left:0;bottom:0;right:0;} 73 | .mozilla .sc-view .sc-text-field-view .border{-moz-appearance:textfield;} 74 | .msie .sc-view .sc-text-field-view .border{border:1px inset;} 75 | .safari .sc-text-field-view .border{-webkit-appearance:textfield;} 76 | .sc-view .sc-text-field-view .padding{top:0;left:3px;bottom:0;right:3px;position:absolute;} 77 | .sc-view .sc-text-field-view.text-area .padding{right:0;} 78 | .sc-view .sc-text-field-view .sc-text-field-accessory-view{z-index:2;} 79 | .sc-text-field-view input{position:absolute;top:0;left:0;width:100%;height:100%;line-height:100%;bottom:0;right:0;display:block;background:transparent;vertical-align:middle;} 80 | .msie .sc-text-field-view input{line-height:1.8em;} 81 | .mozilla .sc-text-field-view input{top:3px;} 82 | .sc-text-field-view textarea{position:absolute;top:0;left:0;width:100%;bottom:0;right:0;height:100%;display:block;background:transparent;vertical-align:middle;resize:none;line-height:1.8em;overflow:auto;} 83 | .sc-text-field-view .sc-hint{z-index:1;position:absolute;top:3px;left:1px;right:1px;bottom:3px;padding:0;color:#aaa;font-size:12px;} 84 | .sc-text-field-view.text-area .sc-hint{top:2px;left:3px;right:3px;bottom:2px;} 85 | .sc-text-field-view.focus .sc-hint,.sc-text-field-view.not-empty .sc-hint{display:none;} 86 | .sc-view{cursor:default;overflow:hidden;position:absolute;-moz-user-select:none;-khtml-user-select:none;user-select:none;margin:0;} 87 | .sc-view.allow-select{-moz-user-select:text;-khtml-user-select:text;user-select:text;cursor:text;} 88 | .sc-view:focus,a.sc-view:focus,.sc-view:active,a.sc-view:active{outline:none;} 89 | .sc-view img{border:none;} 90 | .sc-view.hidden{display:none!important;} 91 | .sc-view.textAlignRight{text-align:right;} --------------------------------------------------------------------------------