% ' This is Textile ' A Humane Web Text Generator ' The original Textile was written in PHP. The following is required by the ' license: ' Version 1.0 ' 21 Feb, 2003 ' Copyright (c) 2003, Dean Allen, www.textism.com ' All rights reserved. ' This is a port to VBScript by mmm-oshii@agresticism.org, copyright 2003. It ' most likely doesn't work as well, so only use it if you have to. ' _______ ' LICENSE ' Redistribution and use in source and binary forms, with or without ' modification, are permitted provided that the following conditions are met: ' * Redistributions of source code must retain the above copyright notice, ' this list of conditions and the following disclaimer. ' * Redistributions in binary form must reproduce the above copyright notice, ' this list of conditions and the following disclaimer in the documentation ' and/or other materials provided with the distribution. ' * Neither the name Textile nor the names of its contributors may be used to ' endorse or promote products derived from this software without specific ' prior written permission. ' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ' IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ' ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE ' LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ' CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ' SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ' INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ' CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ' ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ' POSSIBILITY OF SUCH DAMAGE. ' _____________ ' USING TEXTILE ' Block modifier syntax: ' Header: hn. ' Paragraphs beginning with 'hn. ' (where n is 1-6) are wrapped in header tags. ' Example:
Text
' Paragraph with CSS class: p(class). ' Paragraphs beginning with 'p(class). ' receive a CSS class attribute. ' Example:Text
' Blockquote: bq. ' Paragraphs beginning with 'bq. ' are wrapped in block quote tags. ' Example:Text' Blockquote with citation: bq(citeurl). ' Paragraphs beginning with 'bq(citeurl). ' receive a citation attribute. ' Example:
Text' Numeric list: # ' Consecutive paragraphs beginning with # are wrapped in ordered list tags. ' Example:
computer code
' ==notextile== leave text alone (do not format)
' "linktext":url linktext
' "linktext(title)":url linktext
' !imageurl! ")
Line = Replace(Line, "<code>", "")
Line = Replace(Line, "<notextile>", "")
Line = Replace(Line, "<kbd>", "")
End If
' Each line gets pushed to a new array.
' Not any more, it's the same array now.
Text(I) = Line
Next
' Text is now the new array, cast to a string
Text = Join(Text, "")
End If
' Deal with forced breaks; this is going to be a problem between pre tags, but we'll clean them later.
' What does this do again?
' Text = RegExpReplace(RegExp, Text, "(\S)(_*)(\W*) *\n([^#*\s])", "$1$2$3
$4")
' Simple linebreaks.
Text = RegExpReplace(RegExp, Text, "([^\n])\n([^\n])", "$1
\n$2")
' Might be a problem with lists.
Text = Replace(Text, "l>
", "l>" & vbNewLine)
' Clear out multiple newlines for now.
' Is this quicker than a regex?
Do While InStr(Text, vbNewLine & vbNewLine)
Text = Replace(Text, vbNewLine & vbNewLine, vbNewLine)
Loop
' Split the text into an array by newlines.
Text = Text & vbNewLine & " "
Text = Split(Text, vbNewLine)
' These should be set to this by default, but it never hurts to be explicit.
' (In a programming sense, you dirty bugger.)
List = ""
Pre = False
' Bulleted list: *; numeric list: #; blockquote: bq.; classy header: hn(class).; plain header: hn.; classy paragraph p(class).; plain paragraph; remaining plain paragraph.
BlockSearch = Array("^\s?\*\s(.*)", "^\s?#\s(.*)", "^bq\. (.*)", "^h(\d)\(([\w]+)\)\.\s(.*)", "^h(\d)\. (.*)", "^p\(([\w]+)\)\.\s(.*)", "^p\. (.*)", "^([^\t ]+.*)")
' liu and lio, also known as the diveintomark.org way of doing it, seem a better idea to me.
BlockReplace = Array("\t\t$1 ", "\t\t$1 ", "\t$1
", "\t$3 $4", "\t$2 ", "\t$2
$3", "\t$1
", "\t$1
")
' Loop through lines.
For I = 0 To UBound(Text)
Line = Text(I)
' Deal with lines with single spaces on them.
If RegExpMatch(RegExp, Line, "^\s*$") Then Line = ""
' Matches are off if we're between pre (or code, says the original, but I see no code tags mentioned) tags.
If RegExpMatch(RegExp, Line, "") Then Pre = True
' Deal with block replacements first, then see if we're in a list.
If Not Pre Then
For J = 0 To UBound(BlockSearch)
Line = RegExpReplace(RegExp, Line, BlockSearch(J), BlockReplace(J))
Next
End If
' Kill any br tags that slipped in earlier.
If Pre Then Line = Replace(Line, "
", vbNewLine)
' Matches back on after pre.
If RegExpMatch(RegExp, Line, "<\/pre>") Then Pre = False
' On entry to a list, List realises its true potential.
' Ordered lists are lio.
If List = "" And RegExpMatch(RegExp, Line, "\t\t") Then
List = "ul"
Line = RegExpReplace(RegExp, Line, "(.*?.*?)", "\t\n$1")
ElseIf List = "" And RegExpMatch(RegExp, Line, "\t\t") Then
List = "ol"
Line = RegExpReplace(RegExp, Line, "(.*?.*?)", "\t\n$1")
' At the end of a ul.
ElseIf List = "ul" And Not RegExpMatch(RegExp, Line, "\t") Then
List = ""
Line = RegExpReplace(RegExp, Line, "^(.*)$", "\t
\n\n$1")
' At the end of a ol.
ElseIf List = "ol" And Not RegExpMatch(RegExp, Line, "\t") Then
List = ""
Line = RegExpReplace(RegExp, Line, "^(.*)$", "\t\n\n$1")
End If
' Push each line to a new array once processed.
' Sod that, put it back in the same array.
Text(I) = Line
Next
' Put it all back together again.
Text = Join(Text, vbNewLine)
' Clean up notextile--which doesn't quite work as I'd expect, BTW.
Text = RegExpReplace(RegExp, Text, "<\/?notextile>", "")
' Clean up lio and liu.
Text = RegExpReplace(RegExp, Text, "<(\/?)li(u|o)>", "<$1li>")
' Turn the temp char back to an ampersand entity.
Text = Replace(Text, "x%x%", "&")
' Get rid of p around other block elements, like headings and blockquotes. Why? Because I suck.
Text = RegExpReplace(RegExp, Text, "()?<(\/?)(h[1-6]|blockquote|p)>(<\/p>)?", "<$2$3>")
' Newline linebreaks, just for markup tidiness.
Text = Replace(Text, "
", "
" & vbNewLine)
' For the reason above, add some more linebreaks.
Text = RegExpReplace(RegExp, Text, "(<\/h[1-6]>|
|)", "$1\n")
' Get rid of random brs.
Text = RegExpReplace(RegExp, Text, "\n
\n", "")
' Eliminate trailing linebreaks.
' This probably has a problem when the client's sending things the server doesn't recognise as vbNewLine. So I've repeated it, in an ugly manner.
Do While Right(Text, 1) = vbCrLf Or Right(Text, 1) = vbCr Or Right(Text, 1) = vbLf
Text = Left(Text, Len(Text) - 1)
Loop
' If Not InStr(Text, vbNewLine & "
" & vbNewLine) Then Text = "The hell?"
' Return the text. Would you believe me if I said I forgot this in an early version? Well, I did. Took me quite a while to figure it out.
Textile = Text
' The RegExp object has been our trusty workhorse, but glue keeps people's feet on the ground.
Set RegExp = Nothing
' This has been Textile.
End Function
' Behind-the-curtains regex stuff. Note that when I say 'replaces' in these functions, I don't mean that they are exact copies of the function they replace. The text comes first in these, and we have to pass a regular expression object.
Private Function RegExpMatch(RegExp, Text, Pattern)
' Replaces preg_match.
With RegExp
.IgnoreCase = True
.Global = True
.Pattern = Pattern
End With
RegExpMatch = RegExp.Test(Text)
End Function
Private Function RegExpReplace(RegExp, Text, Pattern, ReplaceText)
' Replaces preg_replace.
With RegExp
.IgnoreCase = True
.Global = True
.Pattern = Pattern
End With
' Look, I know I've done this the wrong way round, OK?
' In this function, /i mean case sensitive, not case insensitive.
If Right(Pattern, 2) = "/i" Then
RegExp.IgnoreCase = False
RegExp.Pattern = Left(Pattern, Len(Pattern) - 2)
End If
' Tabs and newlines seem to not quite work right normally. No matter.
ReplaceText = Replace(ReplaceText, "\t", vbTab)
ReplaceText = Replace(ReplaceText, "\n", vbNewLine)
RegExpReplace = RegExp.Replace(Text, ReplaceText)
End Function
Private Function RegExpSplit(RegExp, Text, Pattern, Delimiter)
' Replaces preg_split (with PREG_SPLIT_DELIM_CAPTURE set).
Dim Match, Matches, MatchInfo, Between
With RegExp
.IgnoreCase = True
.Global = True
.Pattern = Pattern
End With
Set Matches = RegExp.Execute(Text)
MatchInfo = Array(1, 0, 1, 0)
For Each Match In Matches
' At first I thought this would be easy, but I had forgotten that I am stupid. Although this code isn't very long, it took a fair bit of head-wall interaction to get it right.
' Previous match's index, previous match's length, current match's index, current match's length.
MatchInfo(0) = MatchInfo(2)
MatchInfo(1) = MatchInfo(3)
MatchInfo(2) = Match.FirstIndex + 1
MatchInfo(3) = Match.Length
' Get the string in the text which starts at the end of the previous match, and continues for the difference between the end of the previous match and the start of the current match.
Between = Mid(Text, MatchInfo(0) + MatchInfo(1), MatchInfo(2) - (MatchInfo(0) + MatchInfo(1)))
' If there is a string between the tags, add it. Otherwise don't.
If Len(Between) > 0 Then
RegExpSplit = RegExpSplit & Between & Delimiter
End If
' Add the match itself.
RegExpSplit = RegExpSplit & Match.Value & Delimiter
Next
' Don't forget text after the last HTML tag! I really should have spotted this sooner.
If MatchInfo(2) + MatchInfo(3) < Len(Text) Then
RegExpSplit = RegExpSplit & Mid(Text, MatchInfo(2) + MatchInfo(3), Len(Text) - MatchInfo(2) + MatchInfo(3)) & Delimiter
End If
End Function
%>