Permalink
Browse files

Initial import. Here we go.

  • Loading branch information...
0 parents commit cd3f713e77d1d93a173fe6bf67ebaae5144e9ea9 @jeffmcfadden committed Jul 18, 2011
48 .gitignore
@@ -0,0 +1,48 @@
+config/database.yml
+log/*.log*
+log/*.pid
+log/restart.txt
+tmp/**/*
+tmp
+bin/*
+db/*.sqlite3
+db/schema.rb
+db/access_logs
+*.swp
+*.swo
+*.swn
+coverage
+public/system
+public/dgweb
+public/assets
+public/css
+public/jscripts
+Thumbs.db
+scratch_directory
+mkmf.log
+
+# Other useful tidbit
+.DS_Store
+doc/api
+doc/app
+doc/plugins
+coverage
+*~
+
+.bundle
+
+rerun.txt
+
+db/dumps/**/*
+
+config/settings/locals.rb
+
+# For sphinx.
+db/sphinx/*
+config/*.sphinx.conf
+log/searchd.*.pid
+
+config/initializers/rails_asset_id.rb
+app/views/dgnetwork/logged_in_index.html_bak.erb
+app/views/feeds/_feed_item_grouping.html_bak.erb
+app/views/about_us/contact_us.html copy.erb
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Jeff McFadden
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
187 README.md
@@ -0,0 +1,187 @@
+# Markdown Preview for Rails
+
+This gem gives you instant markdown preview for any textarea you want, anywhere in your application.
+
+## Installation
+
+## Issues
+
+## Credits
+
+
+
+= TinyMCE for Rails
+
+This plugin provides for the installation and utilization of TinyMCE in Ruby on Rails applications of version 2.3.5 and onward.
+
+TinyMCE is a WYSIWYG HTML editing component released under the GNU Lesser General Public License 2.1 (LGPL 2.1) by Moxiecode Systems (http://tinymce.moxiecode.com/).
+
+
+== Installation
+
+Installing TinyMCE for Rails takes no more than a few minutes to install.
+
+=== Step 1
+
+The recommended installation method for getting tiny_mce working in your application is to use the gem version. To do so, open the console and run:
+
+ [sudo] gem install tiny_mce
+
+Then add this to config/environment.rb of your Rails application:
+
+ config.gem 'tiny_mce'
+
+Alternatively, you can install it as a plugin. To do so, open a console, and in the root of you Rails application, install the plugin by running *one* of the following (depending on the method you use to import plugins):
+
+* script/plugin install git://github.com/kete/tiny_mce.git
+* piston import git://github.com/kete/tiny_mce.git vendor/plugins/tiny_mce
+* git submodule add git://github.com/kete/tiny_mce.git vendor/plugins/tiny_mce
+* Download the latest files ( http://github.com/kete/tiny_mce/tarball/master ) and extract to vendor/plugins/tiny_mce
+
+=== Step 2
+
+Add the following to the top of the controller of the page you want to add TinyMCE to.
+
+ uses_tiny_mce
+
+Then append the following to the text area you want to transform into a TinyMCE editor. You can change the name of the class you want to use by editing the 'editor_selector' param in the controller code options.
+
+ :class => "mceEditor"
+
+Lastly, add the following line(s) to the <head> element of your application view:
+
+ <%= include_tiny_mce_if_needed %>
+
+Now you're all set! Start your server. The gem/plugin will automatically copy the sources to the public javascripts directory when the server is started.
+
+
+== Configuration
+
+There are several ways to configure the plugin to get the desirable effect you're looking for. The following ways can be combined to create complex tiny mce setups
+
+=== Load Order
+
+A load order is present so that you have finer grained control over what shows up where. The load order currently looks like this. The later ones receive more power, that is, the overwrite similar settings in previous configurations.
+
+1. The default tiny_mce plugin settings. Sets it to work on textareas with class of mceEditor, with the english advanced theme.
+2. config/tiny_mce.yml if present. You set your own options here, used across all editors on the site.
+3. uses_tiny_mce declaration. You set you own options here, used across all editors in the controller.
+4. include_tiny_mce_if_needed declaration. You set your own options here, used across all editors contained within that layout.
+
+Below, I'll cover how to use #2, and #3, which are the most likely ones you'll want to use.
+
+=== Global Options
+
+If you have a set of default options that is used throughout all editors in your application, you might want to make them global. You can do this by putting your settings into config/tiny_mce.yml. If the file exists, the tiny_mce plugin will parse the options in it first.
+
+==== Example
+
+ theme: advanced
+ plugins:
+ - table
+ - fullscreen
+
+=== TinyMCE options
+
+You can change the theme, order/choice of buttons, selectors Id, plugins, and many more by passing an :options hash to the uses_tiny_mce declaration.
+
+The options hash can contain any number of settings available in lib/tiny_mce/valid_tinymce_options.yml (a copy of the settings available per version).
+
+If an option is misspelled, invalid, or deprecated (no longer in TinyMCE), when you go to a page containing your editor, you will receive an Exception, which must be dealt with before continuing.
+
+You can read about all these options at http://tinymce.moxiecode.com/documentation.php
+
+==== Example
+
+ uses_tiny_mce :options => {
+ :theme => 'advanced',
+ :theme_advanced_resizing => true,
+ :theme_advanced_resize_horizontal => false,
+ :plugins => %w{ table fullscreen }
+ }
+
+=== Filter options
+
+If, like most applications, you only need the editor on the new, create, edit, and update pages, then tell the uses_tiny_mce declaration this, so it doesn't load up all the files unnecessarily.
+
+The declaration accepts any number of default parameters a normal controller filter would.
+
+==== Example
+
+ uses_tiny_mce :only => [:new, :create, :edit, :update]
+
+
+=== Additional Javascript options
+
+Sometimes, when you need complex arrays of data for plugins or such, the plugin helpers aren't complex enough to do what you need. But you can always fall back to supplying your own options. You can this by passing a raw javascript (no <script> tags) to the uses_tiny_mce declaration. Consider the following example for the template plugin.
+
+ uses_tiny_mce :raw_options => "template_templates : [ {
+ title : 'Editor Details',
+ src : 'editor_details.htm',
+ description : 'Adds Editors Name and Staff ID'
+ } ]"
+
+
+== Methods
+
+TinyMCE has a range of convenience methods for loading TinyMCE. Besides the uses_tiny_mce shown above, they include:
+
+ using_tiny_mce?
+ Check whether the uses_tiny_mce declaration has been made in the current controller
+
+ raw_tiny_mce_init
+ Creates a string of javascript formed from the options declared to uses_tiny_mce (is not wrapped in a JS tag though, use tiny_mce_init for that)
+
+ tiny_mce_init
+ Creates a javascript tag formed from the options declared to uses_tiny_mce (executes whether uses_tiny_mce was declared or not)
+ tiny_mce_init_if_needed
+ Creates a javascript tag formed from the options declared to uses_tiny_mce (executes only when uses_tiny_mce has been declared)
+
+ include_tiny_mce_js
+ Includes the TinyMCE core javascript file, must be declared before tiny_mce_init (executes whether uses_tiny_mce was declared or not)
+ include_tiny_mce_js_if_needed
+ Includes the TinyMCE core javascript file, must be declared before tiny_mce_init (executes only when uses_tiny_mce has been declared)
+
+ include_tiny_mce_if_needed
+ Includes the TinyMCE core javascript file, and creates a string of javascript formed from the options declared to uses_tiny_mce (executes only when uses_tiny_mce has been declared)
+
+
+== Spellchecking
+
+See SPELLCHECKING_PLUGIN.rdoc . Note: Spell checking is not tested o regularly maintained. Use with caution.
+
+http://github.com/kete/tiny_mce/tree/master/SPELLCHECKING_PLUGIN.rdoc
+
+
+== Testing
+
+The plugin comes with a test suite that can be run once the plugin is installed in an application.
+
+Change into the plugins directory and run 'rake' to start them.
+
+Note: The tests require Rails 2.2 or higher, and are currently tested on Rails 2.3 (so problems in older versions may arise - please see "Reporting an Issue" if they do)
+
+
+== Reporting an Issue
+
+If you have a problem, please report it on the tiny_mce plugin ticket tracker (on Ligthouseapp)
+
+http://kete.lighthouseapp.com/projects/14744-tiny_mce/tickets
+
+Be sure to include Rails version, plugin version, and when possible, a sample application that can reproduce the problem. Upload it to one of the various file hosting sites and link to it in the ticket. Don't include vendored rails or the tiny_mce plugin in the archive (if I know the versions, I'll add these myself).
+
+
+== Contributing
+
+If you've added something, why not share it. Fork the repository (http://github.com/kete/tiny_mce), make the changes and send a pull request to the maintainers.
+
+Changes with tests, and full documentation are preferred.
+
+
+= Credits
+
+This plugin was created by Blake Watters <blake@near-time.com>
+
+This plugin is currently maintained by Kieran Pilkington <kieran@katipo.co.nz>
+
+Bundled TinyMCE version: 3.3.6
13 Rakefile
@@ -0,0 +1,13 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the markdown_preview gem.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
14 app/controllers/markdown_preview_controller.rb
@@ -0,0 +1,14 @@
+class MarkdownPreviewController < ApplicationController
+
+ def convert
+ markdown = RDiscount.new( MarkdownPreview.preprocess_markdown( params[:markdown_text] ) )
+
+ html = markdown.to_html
+
+ respond_to do |format|
+ format.json { render :json => { :html => html } }
+ end
+ end
+
+end
+
3 config/routes.rb
@@ -0,0 +1,3 @@
+Rails.application.routes.draw do |map|
+ post "markdown_preview/convert" => "markdown_preview#convert"
+end
125 lib/markdown_preview.rb
@@ -0,0 +1,125 @@
+# Require all the necessary files to run MarkdownPreview
+require 'markdown_preview/base'
+require 'markdown_preview/exceptions'
+require 'markdown_preview/configuration'
+require 'markdown_preview/helpers'
+
+module MarkdownPreview
+ def self.initialize
+ return if @intialized
+ raise "ActionController is not available yet." unless defined?(ActionController)
+ ActionController::Base.send(:include, MarkdownPreview::Base)
+ ActionController::Base.send(:helper, MarkdownPreview::Helpers)
+ MarkdownPreview.install_or_update_markdown_preview
+ @intialized = true
+ end
+
+ #Override this is a config somewhere if you want to preprocess your incoming
+ #markdown string. i.e. add a custom tag or something.
+ def self.preprocess_markdown( markdown )
+ markdown
+ end
+
+ def self.install_or_update_markdown_preview
+ require 'fileutils'
+ orig = File.join(File.dirname(__FILE__), 'markdown_preview', 'assets', 'markdown_preview')
+ dest = File.join(Rails.root.to_s, 'public', 'javascripts', 'markdown_preview')
+ markdown_preview_js = File.join(dest, 'markdown_preview.js')
+
+ unless File.exists?(markdown_preview_js) && FileUtils.identical?(File.join(orig, 'markdown_preview.js'), markdown_preview_js)
+ if File.exists?(markdown_preview_js)
+ # upgrade
+ begin
+ puts "Removing directory #{dest}..."
+ FileUtils.rm_rf dest
+ puts "Creating directory #{dest}..."
+ FileUtils.mkdir_p dest
+ puts "Copying MarkdownPreview to #{dest}..."
+ FileUtils.cp_r "#{orig}/.", dest
+ puts "Successfully updated MarkdownPreview."
+ rescue
+ puts 'ERROR: Problem updating MarkdownPreview. Please manually copy '
+ puts orig
+ puts 'to'
+ puts dest
+ end
+ else
+ # install
+ begin
+ puts "Creating directory #{dest}..."
+ FileUtils.mkdir_p dest
+ puts "Copying MarkdownPreview to #{dest}..."
+ FileUtils.cp_r "#{orig}/.", dest
+ puts "Successfully installed MarkdownPreview."
+ rescue
+ puts "ERROR: Problem installing MarkdownPreview. Please manually copy "
+ puts orig
+ puts "to"
+ puts dest
+ end
+ end
+ end
+
+
+
+ orig = File.join(File.dirname(__FILE__), 'markdown_preview', 'assets', 'markdown_preview')
+ dest = File.join(Rails.root.to_s, 'public', 'stylesheets', 'markdown_preview')
+ markdown_preview_css = File.join(dest, 'markdown_preview.css')
+
+ unless File.exists?(markdown_preview_css) && FileUtils.identical?(File.join(orig, 'markdown_preview.css'), markdown_preview_css)
+ if File.exists?(markdown_preview_css)
+ # upgrade
+ begin
+ puts "Removing directory #{dest}..."
+ FileUtils.rm_rf dest
+ puts "Creating directory #{dest}..."
+ FileUtils.mkdir_p dest
+ puts "Copying MarkdownPreview to #{dest}..."
+ FileUtils.cp_r "#{orig}/.", dest
+ puts "Successfully updated MarkdownPreview."
+ rescue
+ puts 'ERROR: Problem updating MarkdownPreview. Please manually copy '
+ puts orig
+ puts 'to'
+ puts dest
+ end
+ else
+ # install
+ begin
+ puts "Creating directory #{dest}..."
+ FileUtils.mkdir_p dest
+ puts "Copying MarkdownPreview to #{dest}..."
+ FileUtils.cp_r "#{orig}/.", dest
+ puts "Successfully installed MarkdownPreview."
+ rescue
+ puts "ERROR: Problem installing MarkdownPreview. Please manually copy "
+ puts orig
+ puts "to"
+ puts dest
+ end
+ end
+ end
+
+
+
+
+ end
+
+ module Base
+ end
+
+ class Engine < Rails::Engine
+ config.autoload_paths += %W(#{config.root}/lib)
+
+ def self.activate
+ #Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*.rb")) do |c|
+ # Rails.env.production? ? require(c) : load(c)
+ #end
+
+ end
+
+ config.to_prepare &method(:activate).to_proc
+ end
+end
+
+MarkdownPreview.initialize
69 lib/markdown_preview/assets/markdown_preview/markdown_preview.css
@@ -0,0 +1,69 @@
+ .markdown_wrap{
+ border: 2px solid #CCC;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ }
+
+ .markdown_wrap textarea{
+ width: 100%;
+ }
+
+ .markdown_wrap_menu{
+ height: 1.5em;
+ background-color: #CCC;
+ margin: 0px;
+ padding: 2px;
+ }
+
+ .markdown_wrap_help{
+ background-color: #AAA;
+ padding: 3px;
+ display: none;
+ }
+
+ .markdown_wrap_content{
+ padding: 2px;
+ }
+
+ .markdown_wrap_menu div{
+ font-size: 80%;
+ color: #222;
+
+ float: left;
+ margin-right: 1em;
+ border: 1px solid #888;
+ padding: 2px;
+ -webkit-border-radius: 2em;
+ -moz-border-radius: 2em;
+ border-radius: 2em;
+
+ padding-left: 10px;
+ padding-right: 10px;
+ text-align: center;
+
+ }
+
+ .markdown_wrap_menu .markdown_wrap_menu_help{
+ float: right;
+ }
+
+ .markdown_wrap.editing .markdown_wrap_menu_preview, .markdown_wrap.previewing .markdown_wrap_menu_edit, .markdown_wrap_menu_help{
+ background-color: none;
+ border: 1px solid #888;
+ }
+
+ .markdown_wrap.editing .markdown_wrap_menu_edit, .markdown_wrap.previewing .markdown_wrap_menu_preview, .markdown_wrap.helping .markdown_wrap_menu_help{
+ background-color: #EEE;
+ border-top: 1px solid #444;
+ border-bottom: 1px solid #BBB;
+ }
+
+ .markdown_wrap_menu_edit, .markdown_wrap_menu_preview, .markdown_wrap_menu_help{
+ cursor: pointer;
+ }
+
+ .markdown_wrap_preview{
+ display: none;
+ }
+
140 lib/markdown_preview/assets/markdown_preview/markdown_preview.js
@@ -0,0 +1,140 @@
+ (function( $ ){
+
+ $.fn.markdownPreview = function( type ) {
+
+ return this.each(function() {
+
+ var $this = $(this);
+
+ $this.wrap( '<div class="markdown_wrap editing"></div>' );
+
+ $this.before( '<div class="markdown_wrap_menu"><div class="markdown_wrap_menu_help">Help</div><div class="markdown_wrap_menu_edit">Write</div><div class="markdown_wrap_menu_preview">Preview</div></div>' );
+
+ var help_text = [
+'<div class="content cheatsheet">',
+ '<h2>Markdown Cheat Sheet</h2>',
+ '<div class="cheatsheet-content">',
+ '<div class="mod">',
+ '<div class="col">',
+ '<h3>Format Text</h3>',
+ '<p>Headers</p>',
+ '<pre># This is an &lt;h1&gt; tag',
+'## This is an &lt;h2&gt; tag',
+'###### This is an &lt;h6&gt; tag</pre>',
+' <p>Text styles</p>',
+' <pre>*This text will be italic*',
+'_This will also be italic_',
+'**This text will be bold**',
+'__This will also be bold__',
+'',
+'*You **can** combine them*',
+'</pre>',
+ '</div>',
+ '<div class="col">',
+ '<h3>Lists</h3>',
+ '<p>Unordered</p>',
+ '<pre>* Item 1',
+'* Item 2',
+' * Item 2a',
+' * Item 2b</pre>',
+' <p>Ordered</p>',
+' <pre>1. Item 1',
+'2. Item 2',
+'3. Item 3',
+' * Item 3a',
+' * Item 3b</pre>',
+ '</div>',
+ '<div class="col">',
+ '<h3>Miscellaneous</h3>',
+ '<p>Images</p>',
+ '<pre>![GitHub Logo](/images/logo.png)',
+'Format: ![Alt Text](url)',
+'</pre>',
+ '<p>Links</p>',
+ '<pre>http://github.com - automatic!',
+'[GitHub](http://github.com)</pre>',
+'<p>Blockquotes</p>',
+ '<pre>As Kanye West said:',
+'&gt; We\'re living the future so',
+'&gt; the present is our past.',
+'</pre>',
+ '</div>',
+ '</div>',
+ '<div class="rule"></div>',
+ '</div>',
+ '</div>' ].join( "\n" );
+
+
+ $this.before( '<div class="markdown_wrap_help">' + help_text + '</div>' );
+
+ $this.wrap( '<div class="markdown_wrap_content"></div>' );
+ $this.after( '<div class="markdown_wrap_preview"></div>' );
+
+ $this.wrap( '<div class="markdown_wrap_editor"></div>' );
+
+ /*
+ if ( !type || type == 'width' ) {
+ $this.width( $this.width() );
+ }
+
+ if ( !type || type == 'height' ) {
+ $this.height( $this.height() );
+ }*/
+
+ });
+
+ };
+
+ $( '.markdown_wrap_menu_help' ).live( 'click', function(){
+ //console.log( 'Clicked Help' );
+ $( this ).closest( '.markdown_wrap' ).toggleClass( 'helping' );
+
+ $( this ).closest( '.markdown_wrap' ).find( '.markdown_wrap_help' ).slideToggle( 'fast' );
+ });
+
+ $( '.markdown_wrap_menu_edit' ).live( 'click', function(){
+ //console.log( 'Clicked Edit' );
+ $( this ).closest( '.markdown_wrap' ).removeClass( 'previewing' ).addClass( 'editing' );
+
+ $( this ).closest( '.markdown_wrap' ).find( '.markdown_wrap_preview' ).hide();
+ $( this ).closest( '.markdown_wrap' ).find( '.markdown_wrap_editor' ).show();
+ });
+
+ $( '.markdown_wrap_menu_preview' ).live( 'click', function(){
+ //console.log( 'Clicked Preview' );
+ $( this ).closest( '.markdown_wrap' ).removeClass( 'editing' ).addClass( 'previewing' );
+
+ var editor = $( this ).closest( '.markdown_wrap' ).find( '.markdown_wrap_editor' );
+ var preview = $( this ).closest( '.markdown_wrap' ).find( '.markdown_wrap_preview' );
+
+ preview.html( 'Loading...' );
+
+ editor.hide();
+ preview.show();
+
+ var editor_content = editor.find( 'textarea' ).val();
+
+ $.ajax({
+ type: 'POST',
+ url: '/markdown_preview/convert',
+ data: 'format=json&markdown_text=' + editor_content,
+ success: function( data, textStatus, jqXHR ){
+ preview.html( data['html'] );
+ },
+ error: function(jqXHR, textStatus, errorThrown){
+ //console.log( "ERROR" );
+ //console.log( jqXHR );
+ //console.log( textStatus );
+ //console.log( errorThrown );
+ },
+ dataType: 'text json'
+ });
+
+ });
+ })( jQuery );
+
+
+ $( document ).ready( function(){
+ $( '.markdown_preview' ).markdownPreview();
+ });
+
29 lib/markdown_preview/base.rb
@@ -0,0 +1,29 @@
+module MarkdownPreview
+ # The base module we include into ActionController::Base
+ module Base
+ # When this module is included, extend it with the available class methods
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ # The controller declaration to enable markdown_preview certain actions.
+ # Takes options hash, raw_options string, and any normal params you
+ # can send to a before_filter (only, except etc)
+ def uses_markdown_preview(options = {})
+ configuration = MarkdownPreview::Configuration.new(options.delete(:options), options.delete(:raw_options))
+
+ # Set instance vars in the current class
+ proc = Proc.new do |c|
+ configurations = c.instance_variable_get(:@markdown_preview_configurations) || []
+ configurations << configuration
+ c.instance_variable_set(:@markdown_preview_configurations, configurations)
+ c.instance_variable_set(:@uses_markdown_preview, true)
+ end
+
+ # Run the above proc before each page load this method is declared in
+ before_filter(proc, options)
+ end
+ end
+ end
+end
5 lib/markdown_preview/configuration.rb
@@ -0,0 +1,5 @@
+module MarkdownPreview
+ class Configuration
+
+ end
+end
14 lib/markdown_preview/exceptions.rb
@@ -0,0 +1,14 @@
+module MarkdownPreview
+ # Setup a couple of Exception classes that we use later on
+ class MarkdownPreviewInvalidOption < Exception
+ def self.invalid_option(option)
+ new "Invalid option #{option} passed to MarkdownPreview"
+ end
+ end
+
+ class MarkdownPreviewInvalidOptionType < Exception
+ def self.invalid_type_of(value, parameters={})
+ new "Invalid value of type #{value.class} passed for MarkdownPreview option #{parameters[:for].to_s}"
+ end
+ end
+end
29 lib/markdown_preview/helpers.rb
@@ -0,0 +1,29 @@
+module MarkdownPreview
+ # The helper module we include into ActionController::Base
+ module Helpers
+
+ # Has uses_markdown_preview method been declared in the controller for this page?
+ def using_markdown_preview?
+ !@uses_markdown_preview.blank?
+ end
+
+ # Form a JS include tag for the MarkdownPreview JS src for inclusion in the <head>
+ def include_markdown_preview_js
+ #javascript_include_tag (Rails.env.to_s == 'development' ? "markdown_preview/markdown_preview" : "markdown_preview/markdown_preview.min")
+ javascript_include_tag (Rails.env.to_s == 'development' ? "markdown_preview/markdown_preview" : "markdown_preview/markdown_preview")
+ end
+
+ # Form a JS include tag for the MarkdownPreview JS src for inclusion in the <head>
+ def include_markdown_preview_css
+ stylesheet_link_tag( "markdown_preview/markdown_preview" )
+ end
+
+ # Form a JS include tag for the MarkdownPreview JS src, and form the raw JS and wrap
+ # in in a <script> tag for inclusion in the <head> for inclusion in the <head>
+ def include_markdown_preview_if_needed(options = {}, raw_options = nil)
+ if using_markdown_preview?
+ include_markdown_preview_js + include_markdown_preview_css
+ end
+ end
+ end
+end
8 lib/tasks/markdown_preview.rake
@@ -0,0 +1,8 @@
+namespace :markdown_preview do
+
+ desc 'Install or update the Markdown Preview sources'
+ task :install => :environment do
+ MarkdownPreview.install_or_update_markdown_preview
+ end
+
+end
19 markdown_preview.gemspec
@@ -0,0 +1,19 @@
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'markdown_preview'
+ s.version = '0.1.0'
+ s.authors = ["Jeff McFadden"]
+ s.email = "jeff.mcfadden@gmail.com"
+ s.homepage = "http://github.com/jeffmcfadden/markdown_preview"
+ s.summary = "Markdown Preview of any textarea editor for your rails applications."
+ s.description = "Gem that allows easy preview of your textarea content as markdown."
+
+ s.required_ruby_version = '>= 1.9.2'
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.require_path = 'lib'
+ s.requirements << 'none'
+
+ s.add_dependency('rdiscount')
+end
71 test/functional/full_tiny_mce_controller_test.rb
@@ -0,0 +1,71 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+# Make a test class with full options
+class FullTinyMCEController < ApplicationController
+ uses_tiny_mce :options => { :plugins => ['spellchecker'] },
+ :raw_options => '',
+ :only => ['new_page', 'edit_page']
+ include TinyMCEActions
+end
+
+# Lets make sure that if routes arn't the
+# defaults, these tests will still work
+ActionController::Routing::Routes.draw do |map|
+ map.with_options :controller => 'full_tiny_mce' do |tiny_mce|
+ tiny_mce.connect '/full_tiny_mce/new_page', :action => 'new_page'
+ tiny_mce.connect '/full_tiny_mce/edit_page', :action => 'edit_page'
+ tiny_mce.connect '/full_tiny_mce/show_page', :action => 'show_page'
+ tiny_mce.connect '/full_tiny_mce/spellchecker', :action => 'spellchecker'
+ end
+end
+
+# Use non-default action names to get around possible authentication
+# filters to ensure the tests work in most cases
+class FullTinyMCEControllerTest < ActionController::TestCase
+
+ test "all instance variables are properly set on new and edit" do
+ get :new_page
+ assert_instance_vars_set
+ get :edit_page
+ assert_instance_vars_set
+ end
+
+ test "tiny mce is only loaded on the pages specified to the uses_tiny_mce declaration" do
+ get :show_page
+ assert_response :success
+ assert_nil assigns(:uses_tiny_mce)
+ assert_nil assigns(:tiny_mce_configurations)
+ # assert_nil assigns(:raw_tiny_mce_options)
+ end
+
+ #
+ # Spellchecking Controller Test
+ #
+
+ test "additional spellchecking method is available" do
+ assert @controller.methods.include?("spellchecker")
+ end
+
+ test "the spellchecker action is available" do
+ get :spellchecker
+ assert_response(:success)
+ end
+
+ test "the spellchecker has a default path to use" do
+ get :new_page
+ assert_not_nil assigns(:tiny_mce_configurations).first
+ assert_equal assigns(:tiny_mce_configurations).first.options["spellchecker_rpc_url"], "/full_tiny_mce/spellchecker"
+ end
+
+ private
+
+ def assert_instance_vars_set
+ assert_response :success
+ assert (assigns(:uses_tiny_mce) &&
+ assigns(:uses_tiny_mce) == true)
+ assert (assigns(:tiny_mce_configurations) &&
+ assigns(:tiny_mce_configurations).is_a?(Array) &&
+ assigns(:tiny_mce_configurations).first.options == { "spellchecker_rpc_url"=> "/full_tiny_mce/spellchecker",
+ "plugins" => ['spellchecker'] })
+ end
+end
58 test/functional/multi_configuration_tiny_mce_controller_test.rb
@@ -0,0 +1,58 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+# Make a test class with full options
+class MultiConfigurationTinyMCEController < ApplicationController
+ uses_tiny_mce :options => { :plugins => ['spellchecker'] },
+ :raw_options => '',
+ :only => ['new_page','edit_page']
+ uses_tiny_mce :options => { :plugins => ['paste','fullscreen'] },
+ :raw_options => '',
+ :only => ['edit_page']
+ include TinyMCEActions
+end
+
+# Lets make sure that if routes arn't the
+# defaults, these tests will still work
+ActionController::Routing::Routes.draw do |map|
+ map.with_options :controller => 'multi_configuration_tiny_mce' do |tiny_mce|
+ tiny_mce.connect '/full_tiny_mce/new_page', :action => 'new_page'
+ tiny_mce.connect '/full_tiny_mce/edit_page', :action => 'edit_page'
+ tiny_mce.connect '/full_tiny_mce/show_page', :action => 'show_page'
+ tiny_mce.connect '/full_tiny_mce/spellchecker', :action => 'spellchecker'
+ end
+end
+
+# Use non-default action names to get around possible authentication
+# filters to ensure the tests work in most cases
+class MultiConfigurationTinyMCEControllerTest < ActionController::TestCase
+
+ test "all instance variables are properly set on new" do
+ get :new_page
+ assert_response :success
+ assert (assigns(:uses_tiny_mce) &&
+ assigns(:uses_tiny_mce) == true)
+ assert (assigns(:tiny_mce_configurations) &&
+ assigns(:tiny_mce_configurations).is_a?(Array) &&
+ assigns(:tiny_mce_configurations).first.options == { "spellchecker_rpc_url"=> "/multi_configuration_tiny_mce/spellchecker",
+ "plugins" => ['spellchecker'] })
+ end
+
+ test "all instance variables are properly set on edit" do
+ get :edit_page
+ assert_response :success
+ assert (assigns(:uses_tiny_mce) &&
+ assigns(:uses_tiny_mce) == true)
+ assert (assigns(:tiny_mce_configurations) &&
+ assigns(:tiny_mce_configurations).is_a?(Array) &&
+ assigns(:tiny_mce_configurations).first.options == { "spellchecker_rpc_url"=> "/multi_configuration_tiny_mce/spellchecker",
+ "plugins" => ['spellchecker'] } &&
+ assigns(:tiny_mce_configurations).second.options == { "plugins" => ['paste','fullscreen'] })
+ end
+
+ test "tiny mce is only loaded on the pages specified to the uses_tiny_mce declaration" do
+ get :show_page
+ assert_response :success
+ assert_nil assigns(:uses_tiny_mce)
+ assert_nil assigns(:tiny_mce_configurations)
+ end
+end
48 test/functional/slim_tiny_mce_controller_test.rb
@@ -0,0 +1,48 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+# Make a test class with no options
+class SlimTinyMCEController < ApplicationController
+ uses_tiny_mce
+ include TinyMCEActions
+end
+
+# Lets make sure that if routes arn't the
+# defaults, these tests will still work
+ActionController::Routing::Routes.draw do |map|
+ map.with_options :controller => 'slim_tiny_mce' do |tiny_mce|
+ tiny_mce.connect '/slim_tiny_mce/new_page', :action => 'new_page'
+ tiny_mce.connect '/slim_tiny_mce/edit_page', :action => 'edit_page'
+ tiny_mce.connect '/slim_tiny_mce/show_page', :action => 'show_page'
+ tiny_mce.connect '/slim_tiny_mce/spellchecker', :action => 'spellchecker'
+ end
+end
+
+# Use non-default action names to get around possible authentication
+# filters to ensure the tests work in most cases
+class SlimTinyMCEControllerTest < ActionController::TestCase
+
+ test "all instance variables are properly set on all pages" do
+ get :new_page
+ assert_instance_vars_set
+ get :edit_page
+ assert_instance_vars_set
+ get :show_page
+ assert_instance_vars_set
+ end
+
+ private
+
+ def assert_instance_vars_set
+ assert_response :success
+ assert (assigns(:uses_tiny_mce) &&
+ assigns(:uses_tiny_mce) == true)
+ assert (assigns(:tiny_mce_configurations) &&
+ assigns(:tiny_mce_configurations).is_a?(Array))
+
+ # assert (assigns(:tiny_mce_options) &&
+ # assigns(:tiny_mce_options).is_a?(Hash))
+ # assert (assigns(:raw_tiny_mce_options) &&
+ # assigns(:raw_tiny_mce_options) == '')
+ end
+
+end
31 test/test_helper.rb
@@ -0,0 +1,31 @@
+require File.expand_path(File.dirname(__FILE__) + "/../../../../test/test_helper")
+
+# Use non-default action names to get around possible authentication
+# filters to ensure the tests work in most cases
+module TinyMCEActions
+ def new_page
+ render :text => 'Hello'
+ end
+ def edit_page
+ render :text => 'Hello'
+ end
+ def show_page
+ render :text => 'Hello'
+ end
+end
+
+class TestController
+ def self.helper(s) s; end
+end
+
+def set_constant(constant, value)
+ if respond_to?(:silence_warnings)
+ silence_warnings do
+ Object.send(:remove_const, constant) if Object.const_defined?(constant)
+ Object.const_set(constant, value)
+ end
+ else
+ Object.send(:remove_const, constant) if Object.const_defined?(constant)
+ Object.const_set(constant, value)
+ end
+end
56 test/unit/configuration_test.rb
@@ -0,0 +1,56 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ConfigurationTest < ActiveSupport::TestCase
+
+ test "tiny mce should load the valid options on init" do
+ assert_not_nil TinyMCE::Configuration.valid_options
+ end
+
+ test "tiny mce should allow a certain number of options" do
+ assert_equal 141, TinyMCE::Configuration.valid_options.size
+ end
+
+ test "the valid method accepts valid options as strings or symbols" do
+ configuration = TinyMCE::Configuration.new
+ assert configuration.valid?('mode')
+ assert configuration.valid?('plugins')
+ assert configuration.valid?('theme')
+ assert configuration.valid?(:mode)
+ assert configuration.valid?(:plugins)
+ assert configuration.valid?(:theme)
+ end
+
+ test "the valid method detects invalid options as strings or symbols" do
+ configuration = TinyMCE::Configuration.new
+ assert !configuration.valid?('a_fake_option')
+ assert !configuration.valid?(:wrong_again)
+ end
+
+ test "plugins can be set in the options validator and be valid" do
+ configuration = TinyMCE::Configuration.new
+ configuration.plugins = Array.new
+ assert !configuration.valid?('paste_auto_cleanup_on_paste')
+ configuration.plugins = %w{paste}
+ assert configuration.valid?('paste_auto_cleanup_on_paste')
+ end
+
+ test "plugins can be added at a later stage in the script" do
+ configuration = TinyMCE::Configuration.new
+ configuration.plugins = %w{paste}
+ assert configuration.valid?('paste_auto_cleanup_on_paste')
+ configuration.plugins += %w{fullscreen}
+ assert ['paste', 'fullscreen'], configuration.plugins
+ assert configuration.valid?('fullscreen_overflow')
+ end
+
+ test "advanced theme container options get through based on regex" do
+ configuration = TinyMCE::Configuration.new
+ assert configuration.valid?('theme_advanced_container_content1')
+ assert configuration.valid?('theme_advanced_container_content1_align')
+ assert configuration.valid?('theme_advanced_container_content1_class')
+ assert !configuration.valid?('theme_advanced_container_[content]')
+ assert !configuration.valid?('theme_advanced_container_[content]_align')
+ assert !configuration.valid?('theme_advanced_container_[content]_class')
+ end
+
+end
118 test/unit/helpers/tiny_mce_helper_test.rb
@@ -0,0 +1,118 @@
+require File.dirname(__FILE__) + '/../../test_helper'
+require 'action_view/test_case'
+
+module TinyMCE
+ class HelpersTest < ActionView::TestCase
+
+ #
+ # For the following, supply as little config options as possible.
+ #
+
+ test "using_tiny_mce method works as expected" do
+ @uses_tiny_mce = nil
+ assert !using_tiny_mce?
+ @uses_tiny_mce = false
+ assert !using_tiny_mce?
+ @uses_tiny_mce = true
+ assert using_tiny_mce?
+ end
+
+ test "correct tiny mce is loaded depending on environment" do
+ Rails.instance_variable_set('@_env', nil)
+ set_constant('RAILS_ENV', 'development')
+ assert_match /\/javascripts\/tiny_mce\/tiny_mce_src\.js/, include_tiny_mce_js
+ Rails.instance_variable_set('@_env', nil)
+ set_constant('RAILS_ENV', 'production')
+ assert_match /\/javascripts\/tiny_mce\/tiny_mce\.js/, include_tiny_mce_js
+ Rails.instance_variable_set('@_env', nil)
+ set_constant('RAILS_ENV', 'test') # set it back to test
+ end
+
+ test "correct tiny mce is only loaded when using it" do
+ @uses_tiny_mce = nil
+ assert_nil include_tiny_mce_js_if_needed
+ @uses_tiny_mce = true
+ assert_not_nil include_tiny_mce_js_if_needed
+ end
+
+ test "tiny_mce_init wraps raw js in a javascript tag" do
+ assert_equal default_tiny_mce_javascript, tiny_mce_init(Hash.new, String.new)
+ end
+
+ test "tiny_mce_init_if_needed only wraps raw js in a javascript tag if needed" do
+ @uses_tiny_mce = nil
+ assert_nil tiny_mce_init_if_needed
+ @uses_tiny_mce = true
+ assert_equal default_tiny_mce_javascript, tiny_mce_init_if_needed(Hash.new, String.new)
+ end
+
+ test "include_tiny_mce_if_needed outputs the required JS when needed" do
+ @uses_tiny_mce = nil
+ assert_nil include_tiny_mce_if_needed
+ @uses_tiny_mce = true
+ assert_match /<script src=.*tiny_mce.js.*<script.*tinyMCE.init/m, include_tiny_mce_if_needed
+ end
+
+ #
+ # Now we test the formed Javascript (i.e. the raw_tiny_mce_init method)
+ #
+
+ test "string, symbol, or fixnum is formed as expected" do
+ assert_equal "tinyMCE.init({\nauto_focus : 'true',\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ 'auto_focus' => 'true' })
+ assert_equal "tinyMCE.init({\nauto_focus : 'true',\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ 'auto_focus' => :true })
+ assert_equal "tinyMCE.init({\nauto_focus : '1',\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ 'auto_focus' => 1 })
+ end
+
+ test "array is formed as expected" do
+ assert_equal "tinyMCE.init({\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\nplugins : \"table\",\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ :plugins => %w{table} })
+ assert_equal "tinyMCE.init({\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\nplugins : \"table,contextmenu,paste\",\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ :plugins => %w{table contextmenu paste} })
+ end
+
+ test "booleans are formed as expected" do
+ assert_equal "tinyMCE.init({\nauto_focus : true,\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ 'auto_focus' => true })
+ assert_equal "tinyMCE.init({\nauto_focus : false,\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});",
+ raw_tiny_mce_init({ 'auto_focus' => false })
+ end
+
+ test "defaults are overridable" do
+ assert_equal "tinyMCE.init({\neditor_selector : 'test-selector',\nlanguage : 'en',\nmode : 'specific_textareas',\ntheme : 'advanced'\n\n});",
+ raw_tiny_mce_init({ :theme => 'advanced', :mode => 'specific_textareas', :editor_selector => 'test-selector' })
+ end
+
+ test "additional tiny mce options can be set in the form of raw js" do
+ assert_equal "tinyMCE.init({\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple',\ntemplate_templates : [ { title : 'Editor Details' }]\n\n});",
+ raw_tiny_mce_init(Hash.new, "template_templates : [ { title : 'Editor Details' }]")
+ end
+
+ test "exception is raised when an invalid option is used" do
+ assert_raise TinyMCEInvalidOption do
+ raw_tiny_mce_init({ 'invalid_option' => true })
+ end
+ end
+
+ test "exception when plugins option is not an array" do
+ assert_raise TinyMCEInvalidOptionType do
+ raw_tiny_mce_init({'plugins' => 'invalid as a string'})
+ end
+ end
+
+ test "exception is raised when an invalid option value type is used" do
+ assert_raise TinyMCEInvalidOptionType do
+ raw_tiny_mce_init({ 'mode' => Class })
+ end
+ end
+
+ private
+
+ def default_tiny_mce_javascript
+ "<script type=\"text/javascript\">\n//<![CDATA[\ntinyMCE.init({\neditor_selector : 'mceEditor',\nlanguage : 'en',\nmode : 'textareas',\ntheme : 'simple'\n\n});\n//]]>\n</script>"
+ end
+
+ end
+end
16 test/unit/tiny_mce_test.rb
@@ -0,0 +1,16 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TinyMCETest < ActiveSupport::TestCase
+
+ test "including tiny mce module into a class should provide uses_tiny_mce method" do
+ test_controller = TestController.new
+ assert !test_controller.class.respond_to?(:uses_tiny_mce)
+ TestController.send(:include, TinyMCE::Base)
+ assert test_controller.class.respond_to?(:uses_tiny_mce)
+ end
+
+ test "tiny mce plugin is included into action controller base and uses_tiny_mce method available" do
+ assert ApplicationController.respond_to?(:uses_tiny_mce)
+ end
+
+end

0 comments on commit cd3f713

Please sign in to comment.