June 29, 2007

Ah, licensing...

So, the big news of the day for the open-source world (and largely cast to the side by Mozillians from my reading) is the release of the General Public License, version 3. One of the unanswered questions I have been thinking about is: "Should I upgrade Verbosio's boilerplates to reflect a minimum GPL version of 3? Or should I leave it at 2 or later?" The consensus from the mozilla.org community so far has been this isn't necessary. (Largely lost in the news was the release of the Lesser General Public License, version 3.)

This has some implications to think about, though.

The standard boilerplate for MPL/LGPL/GPL multi-licensed code says, and I quote:

Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL")...

This essentially means there are now at least five different license versions which Verbosio (and by implication, most of Mozilla) code is available under: MPL 1.1, GPL 2.0, LGPL 2.1, GPL 3.0, LGPL 3.0. I'm not entirely sure what that leads to for my project.

There's another point that I should mention here. One of my ideas for Verbosio is to include the GNU diffutils and Subversion software, integrated into Verbosio natively as XPCOM components. However, with licensing issues, I'm not sure I can do that.

The diffutils package is GPL only, version 2+. As timeless pointed out to me recently, the MPL license itself is not compatible with GPL (but does allow GPL as a parallel license). As for Subversion, well, it's under a Collabnet license which - since I'm not a lawyer and I don't want to think about it - I don't know if it's GPL-compatible. (Subversion's Wikipedia article currently claims it's under the Apache license in the sidebar.)

So the way I read it, I could release Verbosio with diffutils under GPL - but not under MPL or LGPL (with diffutils under LGPL). With Subversion thrown in, I just don't know.

This could be a problem later on down the road, if someone wants to build a non-GPL application based on Verbosio. But that's an old story, isn't it?

Please, no holy wars over which license is better. I'd be happy if someone could analyze Subversion's license and tell me if it's compatible. Similarly I'd like to know if someone knew of a MPL- or LGPL-compatible diff / patch utilities package. I very much doubt everyone contributing to diffutils would willingly reclassify it under LGPL or MPL just for me.

UPDATE: I think I figured out a workaround for license incompatibilities. Namely, a license applies to what you ship in a single package. Extensions can come in their own packages, and thus with their own licenses. So for incompatible licenses, if I offer the new functionality as extensions (but not part of the main download), I can still comply with the licenses for everyone. (A key distinction is that the extension shouldn't be something the main package or other packages with incompatible licenses depend on. Otherwise, it's not really an extension or an external package, and the licenses are forced to work together where they can't.)

I'll have to be a little careful about how I arrange my repository, but this could be a workable solution. Please offer your professional opinions on this.

Posted by WeirdAl at 3:30 PM | Comments (4)

June 17, 2007

Verbosio progress, 06/17/2007

A few days ago, Benjamin Smedberg astutely summarized his thoughts on a XUL IDE: "I like this dialog, steal it". Now, that wasn't the point of his blog entry, but it did leap out at me.

You see, I've been talking for over two years now about Verbosio. In particular, I've been talking about this markup template system, and how you could build markup templates for Verbosio in Verbosio, etc., etc., etc. But I never found a nice, short way to describe what my intent was, until Benjamin (accidentally, and without his knowledge) did it for me.

Verbosio's markup template system is all about "stealing" code.

Now, I want to be clear: I don't mean stealing code in the sense of taking someone's copyrighted works without their permission. You should never use any editing tool to plagiarize someone else's work. For XML documents under an open-source license, however (MPL/LGPL/GPL, anyone?), it's fair game. Besides, by the time you're done creating a template, it's highly unlikely the template will more closely resemble the original than it would resemble any other similar piece of code.

Below are a couple of screenshots of a wizard I'm building. This wizard will let you take a fragment of XML written in a given XML language (in this case, XUL), and transform it into a Verbosio markup template. The template (specifically, its user interface) appears in the upper-right corner of the wizard. The upper-left corner lets you select nodes to edit for the template. The bottom panel is where you would set up the attributes and text contents of the template.

createWizard-pt1.PNG

createWizard-pt2.PNG

You can accuse me of building a really bad user-interface in this wizard, and I would accept that criticism without shame. My goal here is to build something that works, for a proof-of-concept release. I'm still working on this wizard, to be honest. But here I've accomplished the hard part: taking a minimalist XUL element (<xul:button/>), and building a template for that XUL element. A few dump() statements in the background show the template even works - you can change the button within the template. (Don't knock me on the attribute name column - it's a placeholder for real namespace-aware attributes.)

Now I have to integrate the above functionality (which took me at least two days of code on this alone, and several weeks of design speculation) into Verbosio's core, and create a complete path from unknown element to new element template. That's coming, hopefully by the end of the week.

Posted by WeirdAl at 7:07 PM

June 12, 2007

Reflections on a Solid State Society

Last night, Sci-Fi Channel aired the USA premiere of "Ghost in the Shell: Solid State Society". As I am a fan of anime in general and sci-fi anime in particular, I was quite thrilled about it. This follow-on to the original movies, and more specifically the Stand-Alone Complex series (plural), lives up to my expectations. A good tale, one that makes you think - and that, my friends, is the hallmark of really good science fiction.

Since I don't do movie reviews on my blog, I'll leave it at that. The DVD comes out next month, I believe.

The producers behind GitS have also indicated this isn't the end of the SAC series. So I'd like to suggest to the folks at Mozilla Japan (and fans in that part of the world) that maybe we can get a little inside joke into the next series.

Specifically, this little guy. The way I envision it, Chief Aramaki digs up a little robotic doll reminiscent of him, and gives it to Togusa's daughter for a birthday gift. The "old ape" (SeaMonkey reference) talks about how his brother passed it on to him years and years ago, and it's become a pet (much like how many of us treat our preferred Internet browser). As the storyline for GitS only takes place about 30 years into our future, people like Togusa and Aramaki would certainly remember it from their own younger days.

Call me silly, but I like nice touches like that.

Posted by WeirdAl at 9:28 AM | Comments (1)

June 10, 2007

Verbosio progress, 06/10/2007

I keep telling myself I'm two to three weeks away from a proof-of-concept release. Unfortunately, finding those weeks is proving very difficult. Hence, not much outward progress on Verbosio lately.

Just a way you can edit DTD entities with the XML you're also editing!

It also is a little dynamic:

Finally, the changes you're making don't apply until you hit the "OK" button. If you then open up the DTD document, you'll see the DTD itself also has the new value:

I had originally written this so the DTD entity would be exposed beneath the attribute value, so you could change the DTD name and value by independent textboxes. One glance at that user interface told me it wasn't going to work - it was going to be non-obvious. So I redesigned it from scratch. The "goalposts" you see in these images are actually SVG markup, living anonymously within a XBL binding on a <markup:entity-box/> element inside a XUL document. That's four different XML languages, plus JavaScript - one of those languages being a graphics language - all working together to give an unique look and feel which I hope is intuitive. XULRunner 1.9a5 just smiles at this and says, "More, please."

The effects aren't perfect, and neither is the implementation. For instance, if you type into the textbox something larger than the textbox's visual size, the goalposts move outside the textbox's horizontal boundaries. Also, actually committing the changes (clicking "Ok") does far more DOM operations than are strictly necessary. Here, all that Verbosio should need to do is a few attribute modifications, but in reality it also does node insertions and removals. So the code, while functional, needs some optimization.

The change log, as usual, is in the extended entry.

2007-06-10 08:19  ajvincent

	* verbosio/www/screenshots.html: Add images for June 10, 2007 to
	  screenshots page.

2007-06-10 08:15  ajvincent

	* verbosio/www/images/Jun10_2007/: showDTDEntity.png,
	  showDTDEntity_thumb.png: Fix screenshots showing the DTD entity
	  for the first time.

2007-06-10 08:07  ajvincent

	* verbosio/www/screenshots.html: Switch screenshots.html to using
	  thumbnails for April 26, 2007.

2007-06-10 08:05  ajvincent

	* verbosio/www/images/: Apr26_2007/menuitemEdit_thumb.png,
	  Apr26_2007/previewPanel_thumb.png, Jun10_2007/dtdUpdated.png,
	  Jun10_2007/dtdUpdated_thumb.png, Jun10_2007/editDTDEntity.png,
	  Jun10_2007/editDTDEntity_thumb.png, Jun10_2007/itemEdit.png,
	  Jun10_2007/itemEdit_thumb.png, Jun10_2007/showDTDEntity.png,
	  Jun10_2007/showDTDEntity_thumb.png: Add new screenshots and
	  thumbnails for June 10, 2007.  Add thumbnails for April 26, 2007.

2007-06-10 02:00  ajvincent

	*
	  verbosio/src/generic-viewers/preview-edit/content/preview-edit.js:
	  Teach preview document viewer how to react to mutation DOM events
	  from the master document.

2007-06-10 01:52  ajvincent

	* verbosio/src/core/content/verbosio.js: Register added wrappers
	  with the mutation event registry.

2007-06-10 01:51  ajvincent

	* verbosio/src/xpathgen/components/nsXPathGenerator.js: Post new
	  XPathGenerator component (from bug 319768 @
	  bugzilla.mozilla.org).  Not an exact copy, but close enough.

2007-06-10 01:49  ajvincent

	* verbosio/src/core/components/entityManager.js: Convert assertion
	  (possibly bogus) to warning; editing DTD entities seems to work
	  without the assertion.

2007-06-10 01:47  ajvincent

	* verbosio/src/core/content/tools/mutationEvents.js: Remove unused
	  eventSubtreeModifiedDispatcher for mutationEventRegistry.  Update
	  mutationEventRegistry to reflect current API (gDocumentPack
	  instead of unused documentRegistry).	Add new
	  mutationEventNotifier to notify document viewers of mutation
	  events.

2007-06-10 01:44  ajvincent

	* verbosio/src/core/content/bindings/verbosio.xml: Remove some
	  excessively noisy dump statements.

2007-06-09 18:35  ajvincent

	* verbosio/src/core/components/templateXTF.js: Update the template
	  when the user types something into a textbox.

2007-06-09 18:27  ajvincent

	* verbosio/src/core/content/verbosio.js: Fix API change on
	  txnDispatcher.executeListeners:  gDocumentPack owns the
	  transaction manager, not individual document wrappers.

2007-06-09 18:25  ajvincent

	* verbosio/src/core/content/templateFrame.xul: Fix assertions for
	  scope not having a Components property.'

2007-06-09 18:23  ajvincent

	* verbosio/src/core/components/documentFile.js: Back out part of
	  documentFile.js rev 1.14, as it broke support for Windows.

2007-06-09 16:57  ajvincent

	* verbosio/src/core/app-resources/ecma-debug.js: Fix minor
	  regression with warn() calls.

2007-06-09 16:47  ajvincent

	* verbosio/src/core/content/templateFrame.xul: Add commands for
	  accepting and canceling a template's changes.

2007-06-09 16:46  ajvincent

	* verbosio/src/core/content/tools/xeTransactionCommon.js: Add an
	  entity change action for recorded transactions.

2007-06-09 16:45  ajvincent

	* verbosio/src/core/components/entityManager.js: Track the owner
	  node of an entity through clones.  Also, update each attribute
	  only once.

2007-06-09 16:43  ajvincent

	* verbosio/src/core/: components/templateXTF.js,
	  idl/xeIMarkupLanguage.idl: Implement exporting of document
	  fragments from an edited markup template.  These fragments will
	  replace the original node they edit.

2007-06-09 16:42  ajvincent

	* verbosio/src/core/content/verbosio.js: The verbosio.advanceTxn()
	  call should not need a xeIDocumentWrapper argument.

2007-06-03 22:58  ajvincent

	* verbosio/src/core/components/xeBaseURIMap.js: Kill Windows
	  newline characters.

2007-06-03 22:57  ajvincent

	* verbosio/src/backport.pl.in: As module files currently live in
	  the components directory, copy them to the modules directory
	  before backporting to srcdir.

2007-06-03 22:52  ajvincent

	* verbosio/src/core/components/: nodePositionService.js,
	  templateXTF.js, textDocumentWrapper.js, verbosio-utils.js,
	  virtualProtocol.js, xeBaseURIMap.js, xeFileSearch.js,
	  xeTestEngine.js: Code redux:	Use XPCOMUtils.jsm,
	  ArrayConverter.jsm, ecma-debug.jsm, XMLValidator.jsm modules, and
	  drop a lot of redundant code as a result.

2007-06-03 22:48  ajvincent

	* verbosio/src/core/components/xblLanguagePack.js: Strict warning
	  fix:	lose a trailing comma.

2007-06-03 21:32  ajvincent

	* verbosio/src/core/components/verbosioEditor.js: Kill
	  verbosioEditor.js - the transaction that originally needed it
	  turned out to be unnecessary.

2007-06-03 17:27  ajvincent

	* verbosio/src/core/components/entityManager.js: Code redux:  Use
	  XPCOMUtils.jsm, ArrayConverter.jsm, ecma-debug.jsm,
	  XMLValidate.jsm modules for entityManager.js.

2007-06-03 17:26  ajvincent

	* verbosio/src/core/modules/ecma-debug.jsm: ECMA Debug module
	  clean-up.

2007-06-03 17:25  ajvincent

	* verbosio/src/core/modules/XMLValidator.jsm: Don't dump the
	  JavaScript stack for XMLValidator.validate() failures.

2007-06-03 16:47  ajvincent

	* verbosio/src/core/: components/documentFile.js,
	  modules/XMLValidator.jsm: Code redux:  Add XMLValidator
	  JavaScript module.  Use XMLValidator.jsm for documentFile.js.

2007-06-03 16:26  ajvincent

	* verbosio/src/core/modules/ArrayConverter.jsm: Add
	  ArrayConverter.jsm (from
	  https://bugzilla.mozilla.org/show_bug.cgi?id=380839 patch v1.1)

2007-06-03 16:18  ajvincent

	* verbosio/src/core/components/documentFile.js: Code redux:  use
	  ecma-debug.jsm for documentFile.js

2007-06-03 16:11  ajvincent

	* verbosio/src/: backport.pl.in, make-project.pl: Add support for
	  Verbosio JS modules to the build process.

2007-06-03 15:47  ajvincent

	* verbosio/src/core/modules/: ecma-debug.js, ecma-debug.jsm: Copy
	  verbosio/src/core/app-resources/ecma-debug.js rev 1.3 to
	  verbosio/src/core/modules/ecma-debug.jsm rev 1.1.

2007-06-03 15:46  ajvincent

	* verbosio/src/core/modules/ecma-debug.js: Copy
	  verbosio/src/core/app-resources/ecma-debug.js rev 1.3 to
	  verbosio/src/core/modules/ecma-debug.js rev 1.1.

2007-06-03 15:43  ajvincent

	* verbosio/src/core/app-resources/ecma-debug.js: Adjust
	  ecma-debug.js script in preparation for module import.

2007-06-03 15:30  ajvincent

	* verbosio/src/core/components/documentFile.js: Code redux:  use
	  XPCOMUtils.jsm for module code, documentFile.js

2007-06-02 23:27  ajvincent

	* verbosio/src/core/application.ini.in: Move Verbosio requirements
	  for base platform to XULRunner 1.9a5.

2007-06-01 22:07  ajvincent

	* verbosio/src/core/components/templateXTF.js: Remove
	  handleDefault() from templateXTF, as a result of mozilla.org bug
	  378247 being fixed.

2007-06-01 22:06  ajvincent

	* verbosio/src/core/idl/xeIDTDWrapper.idl: Code style change:
	  arguments for methods should be on different lines.

2007-06-01 22:06  ajvincent

	* verbosio/src/code-languages/css/components/css-document.js:
	  Factor out a couple more interfaces we know the CSS document
	  wrapper does not support.

2007-06-01 22:04  ajvincent

	* verbosio/src/: core/components/DTDDocumentWrapper.js,
	  core/components/entityManager.js,
	  core/components/xeTestEngine.js, core/idl/xeIEntityManager.idl,
	  document-packs/xul-application/components/xul-application.js: Add
	  support for changing the value of a DTD entity, and updating the
	  XML documents that entity affects.

2007-06-01 21:45  ajvincent

	* verbosio/src/core/idl/xeITransaction.idl: Drop
	  getAffectedWrappers() method; we're not doing validation work in
	  0.1a1.

2007-05-28 14:32  ajvincent

	* verbosio/src/core/content/verbosio.js: Remove the transaction
	  control object from verbosio.js.

2007-05-28 08:59  ajvincent

	* verbosio/src/core/components/xeTestEngine.js: Remove dead
	  testcase, and check caught errors a little more carefully.

2007-05-28 08:58  ajvincent

	* verbosio/src/: core/content/template.css,
	  generic-viewers/preview-edit/content/preview-edit.js: Move some
	  styling of markup template UI's around - most notably
	  overflow:scroll should belong to the  element.

2007-05-28 08:56  ajvincent

	* verbosio/src/core/components/documentFile.js: Add some
	  assertions, and bail out if we try to load a jarred file.

2007-05-28 08:55  ajvincent

	* verbosio/src/core/components/DTDDocumentWrapper.js: Update
	  DTDDocumentWrapper.js file to reflect minor changes (transaction
	  managers belonging to the doc pack, base wrappers for each DTD
	  wrapper, etc.

2007-05-28 08:50  ajvincent

	* verbosio/src/core/idl/: xeIDocumentWrapper.idl,
	  xeIPrecondition.idl: Forward-declare interfaces instead of
	  importing them.  This helps to isolate IDL syntax errors to a
	  specific file.

2007-05-28 08:48  ajvincent

	* verbosio/src/: core/components/entityManager.js,
	  document-packs/xul-application/components/xul-application.js,
	  generic-viewers/source-edit/content/source-edit.js,
	  generic-viewers/source-edit/content/bindings/source-editor.xml,
	  markup-languages/xul/components/xul-document.js: Document packs
	  should own entity managers, not XML document wrappers.  Also,
	  lose the xeITransactionControl implementation.

2007-05-28 08:45  ajvincent

	* verbosio/src/core/idl/: xeIDocumentPack.idl,
	  xeIEntityManager.idl, xeIXMLDocumentWrapper.idl: Document packs
	  should own entity managers, not XML document wrappers.

2007-05-28 08:43  ajvincent

	* verbosio/src/core/idl/xeIDTDWrapper.idl: JavaDoc fixes for
	  xeIDTDWrapper.idl.

2007-05-28 08:41  ajvincent

	* verbosio/src/core/: components/xeTransactionControl.js,
	  idl/xeITransactionControl.idl: Remove xeITransactionControl.idl,
	  xeTransactionControl.js.  They were not scalable (imagine doing
	  an action, opening a new document, undoing the action).

2007-05-11 20:39  ajvincent

	* verbosio/src/core/content/template.css: CSS error fix from
	  previous checkin.

2007-05-11 20:31  ajvincent

	* verbosio/src/core/content/verbosio.js: Update verbosio.js
	  transaction handling to reflect API changes at shutdown.

2007-05-11 20:29  ajvincent

	* verbosio/src/core/content/: template.css, bindings/template.xml:
	  Add 'goalposts' user interface indicators for DTD entity editing.
	  Work in progress.

2007-05-08 20:58  ajvincent

	* verbosio/src/: core/components/xeTestEngine.js,
	  document-packs/xul-application/components/xul-application.js,
	  document-packs/xul-application/content/xul-application.js:
	  Implement application pack component for XUL-based extensions.

2007-05-08 20:49  ajvincent

	* verbosio/src/core/content/tools/packTypesRegistry.js: Add XXX
	  comment for pack types registry.  It should use the native
	  category manager, but currently doesn't.

2007-05-08 20:46  ajvincent

	* verbosio/src/: core/components/xeTransactionControl.js,
	  misc/uuid.txt: Mark uuid's reserved, and use a new one for
	  xeTransactionControl's TransactionListener.

2007-05-07 22:32  ajvincent

	* verbosio/src/: core/components/entityManager.js,
	  core/components/templateXTF.js, core/components/xeTestEngine.js,
	  core/idl/xeIEntityManager.idl,
	  core/content/bindings/template.xml, misc/uuid.txt: Convert entity
	  references for attributes into xeIEntity objects - lose the
	  wrappedJSObject hacks.

2007-05-07 22:11  ajvincent

	* verbosio/src/core/components/virtualProtocol.js: Silence lots of
	  virtual protocol, virtual channel QI warnings.

2007-05-02 23:16  ajvincent

	* verbosio/src/core/content/verbosio.js: Bustage fix for previous
	  checkin.

2007-05-02 23:11  ajvincent

	* verbosio/src/core/content/verbosio.js: Transaction handling
	  rewrite, phase 1:  Rewrite xeITransaction to list document
	  wrappers it affects, and add xeTransactionControl.js, which
	  requires transactions implement xeITransaction and only modify
	  documents under their control.

2007-05-02 23:07  ajvincent

	* verbosio/src/core/: components/xeTestEngine.js,
	  components/xeTransactionControl.js, idl/xeIDocumentWrapper.idl,
	  idl/xeITransaction.idl, idl/xeITransactionControl.idl:
	  Transaction handling rewrite, phase 1:  Rewrite xeITransaction to
	  list document wrappers it affects, and add
	  xeTransactionControl.js, which requires transactions implement
	  xeITransaction and only modify documents under their control.

2007-05-01 21:55  ajvincent

	* verbosio/src/core/components/xeTestEngine.js: Automated test
	  regression fix (believed to be 1.9a4 tweak) - typeof
	  entityData['XUL_NS'] == 'object'.

2007-04-28 19:58  ajvincent

	* verbosio/src/markup-languages/xul/content/templates.xml: Show
	  entities to the user for the menuitem template.

2007-04-28 19:57  ajvincent

	* verbosio/src/core/: components/templateXTF.js,
	  content/template.css, content/templateFrame.xul,
	  content/bindings/template.xml: Add support for showing DTD
	  entities to the user.  Implement a  binding
	  for this.

2007-04-28 19:53  ajvincent

	* verbosio/src/core/components/entityManager.js: Adjust stored
	  entity maps to include the value of the entity (for text
	  entities), and the document wrapper it came from.

2007-04-28 19:51  ajvincent

	* verbosio/src/core/: components/DTDDocumentWrapper.js,
	  idl/xeIDTDWrapper.idl: Add baseWrapper property to xeIDTDWrapper.

2007-04-28 19:48  ajvincent

	* verbosio/src/core/idl/xeIVirtualFileService.idl: Remove dump
	  method from xeIVirtualFileService.

2007-04-28 15:01  ajvincent

	* verbosio/src/core/components/: virtualProtocol.js,
	  xeTestEngine.js: Bug 16934, clean up and review virtual://
	  protocol handler.  Also add testcase for protocol handler.
	  r=biesi

2007-04-27 20:26  ajvincent

	* verbosio/src/core/application.ini.in: Move Verbosio requirement
	  for XULRunner to a minimum version of 1.9a5pre.
Posted by WeirdAl at 7:22 AM

June 6, 2007

Debugging xpcshell tests (and what they actually test)

Scenario: You're working on a mozilla.org trunk bug, and you've got a xpcshell testcase. Great. Except that it's failing. What you want to do is to set a breakpoint in your C++ code to figure out why the test fails, but to do that you need your debugger attached to xpcshell. Since the xpcshell test harnesses usually run straight through, and run without user interaction, you never have a chance to attach to the right xpcshell.

Until today.

After I got tired of fighting this scenario a couple dozen times, I decided to write a patch which could let you load a given xpcshell test, and manually run the test. Instead of trying to figure out the full list of JS files your test needs, now you can debug the one test.

From your objdir, you run "make SOLO_FILE=(filename) -C (target directory) check-interactive". This launches xpcshell and loads your testcase. You can then attach a debugger and set your breakpoints. Example: make SOLO_FILE=test_import.js -C js/src/xpconnect/tests check-interactive

js>_execute_test(); runs the test. (You still need to name your test function in each file "run_test()".)

js>quit(); exits the xpcshell.

Gory details in bug 382682.

Posted by WeirdAl at 12:23 PM | Comments (1)

June 1, 2007

Time to move off MovableType?

Several days ago, I asked in this blog if anyone knew how to create a category-based feed for moon.mozpad.org. I got no responses on that. Nor did I find anything useful in the MovableType documentation, or in the help forums, or on Google's searches.

That, plus the newest rounds of blogspam I've been getting, are starting to become really, really annoying. Also, I just love messing with XHTML, and being able to serve a blog as application/xhtml+xml would be nice. Being able to throw SVG in there, inline, would be even nicer.

So, without wanting to host it myself, I'm wondering if any popular blogging platform can do all of the above - easily - and also import all the entries and comments I currently have on this weblog. If a fellow Mozillian would be willing to host these thoughts, and can do the complete import, I'd be quite happy. I simply want to migrate to a new blogging platform that is a little more customizable and easier to make changes to.

UPDATE: It seems everyone's recommending WordPress. Okay. :-)

I'm also cleaning up Ludovic's reply, and finding myself wishing Firefox had search & replace capabilites for HTML textboxes and inputs. Please tell me if you know of an extension to do that...

Posted by WeirdAl at 10:40 PM | Comments (12)