witten
/
luminotes
Archived
1
0
Fork 0

* tools/updatedb.py now takes an optional navigation note id parameter, so the titleless navigation note can be updated.

* both tools/initdb.py and tools/updatedb.py set link ids appropriately, rather than just leaving them all as "new"
 * both tools/initdb.py and tools/updatedb.py set certain links to use https if configured as such in config/Common.py
 * tools/initdb.py no longer creates a default "witten" user
 * Added target="_top" to links that should replace the top-level window, and updated client code to ignore links with targets.
 * Removed form_base_url from Editor.js, as https URL is now tacked on by initdb.py/updatedb.py instead.
This commit is contained in:
Dan Helfman 2007-08-02 04:01:11 +00:00
parent a5694d3661
commit b58f5cb1a1
10 changed files with 108 additions and 81 deletions

10
INSTALL
View File

@ -17,7 +17,7 @@ changes, because it uses CherryPy's built-in web server with auto-reload
enabled, so the server will automatically reload any modified source files as
soon as they're modified.
To start the server in development mode:
To start the server in development mode, run:
python2.5 luminotes.py -d
@ -35,10 +35,10 @@ mode doesn't support auto-reload, and logging goes to file (luminotes.log)
instead of the console, but performance should be better than in development
mode.
If you want to use SSL, Edit static/js/Editor.js and change the value of
form_base_url to the URL of your SSL server. For instance:
If you want to use SSL, edit config/Common.py and change the value of
luminotes.https_url to the URL of your SSL server. For instance:
form_base_url = "https://luminotes.com";
"luminotes.https_url": "https://luminotes.com",
Then you'll need to configure your web server to forward requests for
non-static pages to CherryPy. These instructions are for Apache, but in
@ -57,7 +57,7 @@ installed. These rules cause Apache to serve static files itself, while
passing through requests for dynamic pages to the CherryPy web server running
locally.
To actually start the production mode server:
To actually start the production mode server, run:
python2.5 luminotes.py

View File

@ -15,5 +15,6 @@ settings = {
"encoding_filter.encoding": "utf-8",
"decoding_filter.on": True,
"decoding_filter.encoding": "utf-8",
"luminotes.https_url": "",
},
}

View File

@ -28,11 +28,11 @@ You're free to title your wiki notes as you see fit.</li>
<li><b>notebook change history</b><br />
You can go back and review previous revisions of all your notes, so you never
lose a single word.</li>
Make updates without worry. You can always go back and view older versions of
your wiki.</li>
</ul>
<p>
Sound interesting? Then <a href="/notebooks/%s?note_id=new">take a tour</a> or <a href="/notebooks/%s?note_id=new">try it out</a> for yourself!
Sound interesting? Then <a href="/notebooks/%s?note_id=new">take a tour</a> or <a href="/notebooks/%s?note_id=new" target="_top">try it out</a> for yourself!
</p>

View File

@ -1,6 +1,6 @@
<h3>login</h3>
No account yet? Want to make a wiki? You can <a href="/notebooks/%s?note_id=new">try it out</a> for free.
No account yet? Want to make a wiki? You can <a href="/notebooks/%s?note_id=new" target="_top">try it out</a> for free.
<form id="login_form">
<p>

View File

@ -1,5 +1,5 @@
<a href="/notebooks/%s?note_id=new">about</a> -
<a href="/notebooks/%s?note_id=new">features</a> -
<a href="/notebooks/%s?note_id=new">take a tour</a> -
<a href="/notebooks/%s?note_id=new">try it out</a> -
<a href="/notebooks/%s?note_id=new">login</a>
<a href="/notebooks/%s?note_id=new" target="_top">try it out</a> -
<a href="/notebooks/%s?note_id=new" target="_top">login</a>

View File

@ -14,7 +14,8 @@ so not all browsers will work for editing your wiki. Supported browsers include:
</ul>
<p>
The following web browsers are known <i>not</i> to work with Luminotes:
The following web browsers are known <i>not</i> to work with some or all
Luminotes features, at least currently:
</p>
<ul>
@ -25,5 +26,6 @@ The following web browsers are known <i>not</i> to work with Luminotes:
</ul>
If you're looking for a personal wiki with more minimal browser requirements,
you might want to try TiddlyWiki. If you're looking for a more general-purpose
wiki for multiple users, check out MoinMoin.
you might want to try <a href="http://tiddlywiki.com/"
target="_top">TiddlyWiki</a>. And for a more general-purpose wiki, check out
<a href="http://moinmoin.wikiwikiweb.de/" target="_top">MoinMoin</a>.

View File

@ -1,4 +1,3 @@
form_base_url = "";
note_titles = {} // map from note title to the open editor for that note
function Editor( id, notebook_id, note_text, revisions_list, insert_after_iframe_id, read_write, startup, highlight, focus ) {
@ -140,7 +139,7 @@ Editor.prototype.finish_init = function () {
if ( signup_button ) {
var signup_form = withDocument( this.document, function () { return getElement( "signup_form" ); } );
connect( signup_button, "onclick", function ( event ) {
signal( self, "submit_form", form_base_url + "/users/signup", signup_form ); event.stop();
signal( self, "submit_form", "/users/signup", signup_form ); event.stop();
} );
}
@ -148,7 +147,7 @@ Editor.prototype.finish_init = function () {
if ( login_button ) {
var login_form = withDocument( this.document, function () { return getElement( "login_form" ); } );
connect( login_button, "onclick", function ( event ) {
signal( self, "submit_form", form_base_url + "/users/login", login_form ); event.stop();
signal( self, "submit_form", "/users/login", login_form ); event.stop();
} );
}
@ -256,9 +255,6 @@ Editor.prototype.mouse_clicked = function ( event ) {
if ( event.mouse().button.middle || event.mouse().button.right )
return;
event.stop();
signal( this, "state_changed", this );
// search through the tree of elements containing the clicked target. if a link isn't found, bail
var link = event.target()
while ( link.nodeName != "A" ) {
@ -266,9 +262,15 @@ Editor.prototype.mouse_clicked = function ( event ) {
if ( !link )
return;
}
if ( !link.href )
// ignore external links pointing outside of this wiki (indicated by the presence of a link
// target), and let the browser handle them normally
if ( !link.href || link.target )
return;
event.stop();
signal( this, "state_changed", this );
// in case the link is to ourself, first grab the most recent version of our title
this.scrape_title();

0
tools/__init__.py Normal file
View File

View File

@ -12,7 +12,7 @@ from model.User import User
class Initializer( object ):
HTML_PATH = u"static/html"
ENTRY_FILES = [ # the second element of the tuple is whether to show the note on startup
NOTE_FILES = [ # the second element of the tuple is whether to show the note on startup
( u"navigation.html", True ),
( u"about.html", True ),
( u"features.html", True ),
@ -29,15 +29,11 @@ class Initializer( object ):
self.database = database
self.main_notebook = None
self.read_only_main_notebook = None
self.user_notebook = None
self.user = None
self.anonymous = None
threads = (
self.create_main_notebook(),
self.create_anonymous_user(),
self.create_user_notebook(),
self.create_user(),
)
for thread in threads:
@ -50,25 +46,28 @@ class Initializer( object ):
main_notebook_id = ( yield Scheduler.SLEEP )
self.main_notebook = Notebook( main_notebook_id, u"Luminotes" )
for ( filename, startup ) in self.ENTRY_FILES:
full_filename = os.path.join( self.HTML_PATH, filename )
contents = file( full_filename ).read().replace( "%s", main_notebook_id )
# create the read-only view of the main notebook
self.database.next_id( self.scheduler.thread )
read_only_main_notebook_id = ( yield Scheduler.SLEEP )
self.read_only_main_notebook = Read_only_notebook( read_only_main_notebook_id, self.main_notebook )
# create an id for each note
note_ids = {}
for ( filename, startup ) in self.NOTE_FILES:
self.database.next_id( self.scheduler.thread )
note_id = ( yield Scheduler.SLEEP )
note_ids[ filename ] = ( yield Scheduler.SLEEP )
note = Note( note_id, contents )
for ( filename, startup ) in self.NOTE_FILES:
full_filename = os.path.join( self.HTML_PATH, filename )
contents = fix_note_contents( file( full_filename ).read(), read_only_main_notebook_id, note_ids )
note = Note( note_ids[ filename ], contents )
self.main_notebook.add_note( note )
if startup:
self.main_notebook.add_startup_note( note )
self.database.save( self.main_notebook )
# create the read-only view of the main notebook
self.database.next_id( self.scheduler.thread )
read_only_main_notebook_id = ( yield Scheduler.SLEEP )
self.read_only_main_notebook = Read_only_notebook( read_only_main_notebook_id, self.main_notebook )
self.database.save( self.read_only_main_notebook )
def create_anonymous_user( self ):
@ -79,29 +78,6 @@ class Initializer( object ):
self.anonymous = User( anonymous_user_id, u"anonymous", None, None, notebooks )
self.database.save( self.anonymous )
def create_user_notebook( self ):
# create the user notebook along with a startup note
self.database.next_id( self.scheduler.thread )
user_notebook_id = ( yield Scheduler.SLEEP )
self.user_notebook = Notebook( user_notebook_id, u"my notebook" )
self.database.next_id( self.scheduler.thread )
note_id = ( yield Scheduler.SLEEP )
note = Note( note_id, u"<h3>" )
self.user_notebook.add_note( note )
self.user_notebook.add_startup_note( note )
self.database.save( self.user_notebook )
def create_user( self ):
# create the user
self.database.next_id( self.scheduler.thread )
user_id = ( yield Scheduler.SLEEP )
notebooks = [ self.user_notebook ]
self.user = User( user_id, u"witten", u"dev", u"witten@torsion.org", notebooks )
self.database.save( self.user )
def main():
if os.path.exists( "data.db" ):
@ -113,5 +89,31 @@ def main():
scheduler.wait_until_idle()
def fix_note_contents( contents, notebook_id, note_ids ):
import re
from config.Common import settings
LINK_PATTERN = re.compile( '(<a href=")([^"]+?note_id=)([^"]*)("[^>]*>)([^<]*)(</a>)' )
# plug in the notebook id where appropriate
contents = contents.replace( "%s", notebook_id )
# stitch together note links to use the actual note ids of the referenced notes.
# also, use the https URL for certain links if one is configured
def fix_link( match ):
title = match.group( 5 )
https_url = u""
if title in ( u"try it out", u"login" ):
https_url = settings[ u"global" ].get( u"luminotes.https_url", u"" )
return u"".join( [
match.group( 1 ), https_url, match.group( 2 ), note_ids[ title + ".html" ], match.group( 3 ),
match.group( 4 ), match.group( 5 ), match.group( 6 ),
] )
return LINK_PATTERN.sub( fix_link, contents )
if __name__ == "__main__":
main()

View File

@ -2,15 +2,16 @@
import os
import os.path
from config.Common import settings
from controller.Database import Database
from controller.Scheduler import Scheduler
from model.Note import Note
from tools.initdb import fix_note_contents
class Initializer( object ):
HTML_PATH = u"static/html"
ENTRY_FILES = [ # the second element of the tuple is whether to show the note on startup
#( u"navigation.html", True ), # skip for now, since the navigtaion note doesn't have a title
NOTE_FILES = [ # the second element of the tuple is whether to show the note on startup
( u"about.html", True ),
( u"features.html", True ),
( u"take a tour.html", False ),
@ -21,9 +22,10 @@ class Initializer( object ):
( u"advanced browser features.html", False ),
]
def __init__( self, scheduler, database ):
def __init__( self, scheduler, database, navigation_note_id = None ):
self.scheduler = scheduler
self.database = database
self.navigation_note_id = navigation_note_id
threads = (
self.update_main_notebook(),
@ -36,29 +38,31 @@ class Initializer( object ):
def update_main_notebook( self ):
self.database.load( u"User anonymous", self.scheduler.thread )
anonymous = ( yield Scheduler.SLEEP )
read_only_main_notebook = anonymous.notebooks[ 0 ]
main_notebook = anonymous.notebooks[ 0 ]._Read_only_notebook__wrapped
startup_notes = []
# update all of the notes in the main notebook
for ( filename, startup ) in self.ENTRY_FILES:
full_filename = os.path.join( self.HTML_PATH, filename )
contents = file( full_filename ).read().replace( "%s", main_notebook.object_id )
# get the id for each note
note_ids = {}
for ( filename, startup ) in self.NOTE_FILES:
title = filename.replace( u".html", u"" )
note = main_notebook.lookup_note_by_title( title )
note_ids[ filename ] = note.object_id
if note:
main_notebook.update_note( note, contents )
# if for some reason the note isn't present, create it
else:
self.database.next_id( self.scheduler.thread )
note_id = ( yield Scheduler.SLEEP )
note = Note( note_id, contents )
main_notebook.add_note( note )
# update the navigation note if its id was given
if self.navigation_note_id:
self.database.next_id( self.scheduler.thread )
next_id = ( yield Scheduler.SLEEP )
note = main_notebook.lookup_note( self.navigation_note_id )
self.update_note( "navigation.html", True, main_notebook, read_only_main_notebook, startup_notes, next_id, note_ids, note )
main_notebook.remove_startup_note( note )
if startup:
startup_notes.append( note )
# update all of the notes in the main notebook
for ( filename, startup ) in self.NOTE_FILES:
self.database.next_id( self.scheduler.thread )
next_id = ( yield Scheduler.SLEEP )
title = filename.replace( u".html", u"" )
note = main_notebook.lookup_note_by_title( title )
self.update_note( filename, startup, main_notebook, read_only_main_notebook, startup_notes, next_id, note_ids, note )
for note in startup_notes:
main_notebook.add_startup_note( note )
@ -66,13 +70,29 @@ class Initializer( object ):
main_notebook.name = u"Luminotes"
self.database.save( main_notebook )
def update_note( self, filename, startup, main_notebook, read_only_main_notebook, startup_notes, next_id, note_ids, note = None ):
full_filename = os.path.join( self.HTML_PATH, filename )
contents = fix_note_contents( file( full_filename ).read(), read_only_main_notebook.object_id, note_ids )
def main():
if note:
main_notebook.update_note( note, contents )
# if for some reason the note isn't present, create it
else:
note = Note( next_id, contents )
main_notebook.add_note( note )
main_notebook.remove_startup_note( note )
if startup:
startup_notes.append( note )
def main( args ):
scheduler = Scheduler()
database = Database( scheduler, "data.db" )
initializer = Initializer( scheduler, database )
initializer = Initializer( scheduler, database, args and args[ 0 ] or None )
scheduler.wait_until_idle()
if __name__ == "__main__":
main()
import sys
main( sys.argv[ 1: ] )