├── .gitignore ├── .gitmodules ├── README.asciidoc ├── TODO ├── asciidoc.js ├── bootstrap-docs.conf └── examples ├── base-css-article.asciidoc ├── base-css-book.asciidoc └── javaeeworkshop.asciidoc /.gitignore: -------------------------------------------------------------------------------- 1 | /examples/asciidoc.js 2 | /examples/bootstrap 3 | /examples/*.html 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "bootstrap"] 2 | path = bootstrap 3 | url = git://github.com/twitter/bootstrap.git 4 | -------------------------------------------------------------------------------- /README.asciidoc: -------------------------------------------------------------------------------- 1 | = Bootstrap documentation-style backend for AsciiDoc 2 | 3 | An AsciiDoc backend that renders the AsciiDoc source as HTML5 in the style of the http://twitter.github.com/bootstrap[Twitter Bootstrap docs]. 4 | 5 | == Installation 6 | 7 | To install the bootstrap docs backend, download https://github.com/downloads/mojavelinux/asciidoc-bootstrap-docs-backend/bootstrap-docs.zip[bootstrap-docs.zip] and install it using the asciidoc command (you will need AsciiDoc version 8.6.6 or newer): 8 | 9 | asciidoc --backend install bootstrap-docs.zip 10 | 11 | Next, checkout the Twitter Bootstrap repositor in the backend folder: 12 | 13 | cd ~/.asciidoc/backends/bootstrap-docs 14 | git clone git://github.com/twitter/bootstrap.git 15 | 16 | If you enable the link-assets attribute, then you should also checkout (or symlink) the bootstrap clone in the same directory as the rendered file. You also need to create a symlink to asciidoc.js included in this backend. 17 | 18 | == Usage 19 | 20 | Use the 'bootstrap-docs' backend as you would the built-in backends. 21 | 22 | == Example 23 | 24 | As you would expect, the rendered output looks shockingly similar to the Twitter Bootstrap documentation. 25 | 26 | Compare the original http://twitter.github.com/bootstrap/base-css.html[Base CSS] chapter with the http://cloud.github.com/downloads/mojavelinux/asciidoc-bootstrap-docs-backend/example.html[HTML output] from this https://raw.github.com/mojavelinux/asciidoc-bootstrap-docs-backend/master/examples/base-css-book.asciidoc[AsciiDoc source]. Hey Twitter, want to switch to AsciiDoc? 27 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - add support for picking up a -navinfo.(xml|html) file for the navigation like the docinfo 2 | - use http://fortawesome.github.com/Font-Awesome/ instead of glyphicons 3 | - make prettyprint optional 4 | - make Example callout optional 5 | - multi-line admonition 6 | - use jQuery for toc 7 | - figure out how to remove endlines in base64.encode w/o having to use sed 8 | -------------------------------------------------------------------------------- /asciidoc.js: -------------------------------------------------------------------------------- 1 | var asciidoc = { // Namespace. 2 | 3 | ///////////////////////////////////////////////////////////////////// 4 | // Table Of Contents generator 5 | ///////////////////////////////////////////////////////////////////// 6 | 7 | /* Author: Mihai Bazon, September 2002 8 | * http://students.infoiasi.ro/~mishoo 9 | * 10 | * Table Of Content generator 11 | * Version: 0.5-bootstrap-docs 12 | * Modified to accomodate the bootstrap-docs backend 13 | * 14 | * Feel free to use this script under the terms of the GNU General Public 15 | * License, as long as you do not remove or alter this notice. 16 | */ 17 | 18 | /* modified by Troy D. Hanson, September 2006. License: GPL */ 19 | /* modified by Stuart Rackham, 2006, 2009. License: GPL */ 20 | /* modified by Dan Allen, 2012. License: GPL */ 21 | 22 | // toclevels = 1..4. 23 | toc: function (toclevels) { 24 | 25 | function getText(el) { 26 | var text = ""; 27 | for (var i = el.firstChild; i != null; i = i.nextSibling) { 28 | if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. 29 | text += i.data; 30 | else if (i.firstChild != null) 31 | text += getText(i); 32 | } 33 | return text; 34 | } 35 | 36 | function TocEntry(el, text, toclevel) { 37 | this.element = el; 38 | this.text = text; 39 | this.toclevel = toclevel; 40 | } 41 | 42 | function tocEntries(el, toclevels) { 43 | var result = new Array; 44 | var re = new RegExp('[hH]([1-'+(toclevels)+'])'); 45 | // Function that scans the DOM tree for header elements (the DOM2 46 | // nodeIterator API would be a better technique but not supported by all 47 | // browsers). 48 | var iterate = function (el) { 49 | for (var i = el.firstChild; i != null; i = i.nextSibling) { 50 | if (i.nodeType == 1 /* Node.ELEMENT_NODE */) { 51 | var mo = re.exec(i.tagName); 52 | if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "loose") { 53 | result[result.length] = new TocEntry(i, getText(i), mo[1]-1); 54 | } 55 | iterate(i); 56 | } 57 | } 58 | } 59 | iterate(el); 60 | return result; 61 | } 62 | 63 | var toc = document.getElementById("toc"); 64 | if (!toc) { 65 | return; 66 | } 67 | 68 | // Delete existing TOC entries in case we're reloading the TOC. 69 | var tocEntriesToRemove = []; 70 | var i; 71 | for (i = 0; i < toc.childNodes.length; i++) { 72 | var entry = toc.childNodes[i]; 73 | if (entry.nodeName.toLowerCase() == 'div' 74 | && entry.getAttribute("class") 75 | && entry.getAttribute("class").match(/^toclevel/)) 76 | tocEntriesToRemove.push(entry); 77 | } 78 | for (i = 0; i < tocEntriesToRemove.length; i++) { 79 | toc.removeChild(tocEntriesToRemove[i]); 80 | } 81 | 82 | // Rebuild TOC entries. 83 | var entries = tocEntries(document.getElementById("content"), toclevels); 84 | for (var i = 0; i < entries.length; ++i) { 85 | var entry = entries[i]; 86 | if (entry.element.id == "") { 87 | var sec = entry.element.parentNode; 88 | if (sec.nodeName.toLowerCase() != 'section') { 89 | sec = sec.parentNode; 90 | } 91 | if (sec.nodeName.toLowerCase() == 'section' && sec.id != "") { 92 | entry.element.id = sec.id; 93 | } 94 | else { 95 | entry.element.id = "toc_" + i; 96 | } 97 | } 98 | var a = document.createElement("a"); 99 | a.href = "#" + entry.element.id; 100 | var img = document.createElement("i"); 101 | img.className = 'icon-chevron-right'; 102 | a.appendChild(img); 103 | a.appendChild(document.createTextNode(entry.text)); 104 | var li = document.createElement("li"); 105 | li.appendChild(a); 106 | //li.className = "toclevel" + entry.toclevel; 107 | toc.appendChild(li); 108 | } 109 | if (entries.length == 0) 110 | toc.parentNode.removeChild(toc); 111 | }, 112 | 113 | 114 | ///////////////////////////////////////////////////////////////////// 115 | // Footnotes generator 116 | ///////////////////////////////////////////////////////////////////// 117 | 118 | /* Based on footnote generation code from: 119 | * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html 120 | */ 121 | 122 | footnotes: function () { 123 | // Delete existing footnote entries in case we're reloading the footnodes. 124 | var i; 125 | var noteholder = document.getElementById("footnotes"); 126 | if (!noteholder) { 127 | return; 128 | } 129 | var entriesToRemove = []; 130 | for (i = 0; i < noteholder.childNodes.length; i++) { 131 | var entry = noteholder.childNodes[i]; 132 | if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote") 133 | entriesToRemove.push(entry); 134 | } 135 | for (i = 0; i < entriesToRemove.length; i++) { 136 | noteholder.removeChild(entriesToRemove[i]); 137 | } 138 | 139 | // Rebuild footnote entries. 140 | var cont = document.getElementById("content"); 141 | var spans = cont.getElementsByTagName("span"); 142 | var refs = {}; 143 | var n = 0; 144 | for (i=0; i" + n + "]"; 155 | spans[i].setAttribute("data-note", note); 156 | } 157 | noteholder.innerHTML += 158 | "
" + 159 | "" + 160 | n + ". " + note + "
"; 161 | var id =spans[i].getAttribute("id"); 162 | if (id != null) refs["#"+id] = n; 163 | } 164 | } 165 | if (n == 0) 166 | noteholder.parentNode.removeChild(noteholder); 167 | else { 168 | // Process footnoterefs. 169 | for (i=0; i" + n + "]"; 177 | } 178 | } 179 | } 180 | }, 181 | 182 | install: function(toclevels) { 183 | var timerId; 184 | 185 | function reinstall() { 186 | asciidoc.footnotes(); 187 | if (toclevels) { 188 | asciidoc.toc(toclevels); 189 | } 190 | } 191 | 192 | function reinstallAndRemoveTimer() { 193 | clearInterval(timerId); 194 | reinstall(); 195 | } 196 | 197 | timerId = setInterval(reinstall, 500); 198 | if (document.addEventListener) 199 | document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false); 200 | else 201 | window.onload = reinstallAndRemoveTimer; 202 | } 203 | 204 | } 205 | -------------------------------------------------------------------------------- /bootstrap-docs.conf: -------------------------------------------------------------------------------- 1 | # 2 | # bootstrap-docs.conf 3 | # 4 | # An AsciiDoc backend that renders the AsciiDoc source as HTML5 in the style of 5 | # the Twitter Bootstrap docs (http://twitter.github.com/bootstrap). 6 | # 7 | # author Dan Allen 8 | # version 1.0.0 9 | # license ASLv2 10 | # 11 | 12 | include::{asciidoc-confdir}/html5.conf[] 13 | 14 | [miscellaneous] 15 | newline=\n 16 | 17 | [attributes] 18 | basebackend=html 19 | basebackend-html= 20 | basebackend-bootstrap-docs= 21 | toclevels=1 22 | idprefix= 23 | 24 | [quotes] 25 | _=small 26 | 27 | [monospacedwords] 28 | | 29 | 30 | [tags] 31 | monospaced=| 32 | small=| 33 | 34 | [macros] 35 | # example match: abbr:CDI[Contexts & Dependency Injection] 36 | (?su)(?abbr):(?P\S*?)\[(?P.*?)\]= 37 | 38 | [abbr-inlinemacro] 39 | # For some reason ifdef::basebackend-html[] is not working 40 | # And WTF? is this inability to substitute {title={attrlist}} correctly? why is title empty string when it isn't set? 41 | {basebackend$html:{target}} 42 | {basebackend$html:{target}} 43 | {basebackend$docbook:{target}} 44 | 45 | [literal-inlinemacro] 46 | {passtext} 47 | 48 | [ruler-blockmacro] 49 |
50 | 51 | [paragraph] 52 | |

53 | 54 | [toc] 55 | 57 | 58 | [preamble] 59 |
60 | | 61 |
62 | 63 | [sect0] 64 | 65 | 68 | | 69 | 70 | 71 | [sect1] 72 | ifdef::doctype-book[] 73 | {title} 74 | endif::doctype-book[] 75 | ifdef::doctype-article[] 76 | 77 | 80 | | 81 | 82 | endif::doctype-article[] 83 | 84 | [sect2] 85 | ifdef::doctype-book[] 86 |

{title}

87 | endif::doctype-book[] 88 | ifdef::doctype-article[] 89 | {title} 90 | endif::doctype-article[] 91 | 92 | [sect3] 93 | ifdef::doctype-book[] 94 |

{title}

95 | endif::doctype-book[] 96 | ifdef::doctype-article[] 97 |

{title}

98 | endif::doctype-article[] 99 | 100 | [sect4] 101 | ifdef::doctype-book[] 102 |
{title}
103 | endif::doctype-book[] 104 | ifdef::doctype-article[] 105 |

{title}

106 | endif::doctype-article[] 107 | 108 | [floatingtitle] 109 | {title} 110 | 111 | [blockdef-listing] 112 | address-style=template="addressblock",name="address",caption="{address-caption}",subs=("macros","quotes","replacements","replacements2") 113 | quote-style=template="quoteblock",name="quote",caption="{quote-caption}",posattrs=("style","attribution","citetitle"),subs=("macros","quotes","replacements","replacements2") 114 | 115 | [exampleblock] 116 |
117 | | 118 |
119 | 120 | [admonitionblock] 121 |

{caption} |

122 | 123 | [listingblock] 124 | # WTF? is up with asciidoc attribute matching, it's all screwy 125 | {options!
}
126 | 
127 | |
128 | 
129 | 130 | [quoteblock] 131 | {options$exampleblock:
} 132 | 133 | | 134 | {attribution} {citetitle} 135 | 136 | {options$exampleblock:
} 137 | 138 | [addressblock] 139 |
|
140 | 141 | [listtags-bulleted] 142 | list=| 143 | item=
  • |
  • 144 | text=| 145 | 146 | [listtags-numbered] 147 | list=
      |
    148 | item=
  • |
  • 149 | text=| 150 | 151 | [listtags-labeled] 152 | list=
    |
    153 | entry= 154 | label= 155 | term=
    |
    156 | item=
    |
    157 | text=| 158 | 159 | [listtags-horizontal] 160 | list=
    |
    161 | entry= 162 | label= 163 | term=
    |
    164 | item=
    |
    165 | text=| 166 | 167 | [tabletags-default] 168 | colspec= 169 | bodyrow=| 170 | headdata=| 171 | bodydata=| 172 | paragraph=| 173 | 174 | [table] 175 | 176 | {caption={table-caption} {counter:table-number}. }{title} 177 | 178 | {colspecs} 179 | 180 | {headrows#} 181 | {headrows} 182 | {headrows#} 183 | {footrows#} 184 | {footrows} 185 | {footrows#} 186 | 187 | {bodyrows} 188 | 189 | 190 | 191 | [header] 192 | 193 | 194 | 195 | 196 | 197 | {doctitle={title}} 198 | 199 | 200 | 201 | ifdef::link-assets[] 202 | template::[linked-header-assets] 203 | endif::link-assets[] 204 | ifndef::link-assets[] 205 | template::[inline-header-assets] 206 | endif::link-assets[] 207 | 208 | 209 | 228 |
    229 |
    230 |

    {title={doctitle}}

    231 |

    {description}

    232 |
    233 |
    234 |
    235 |
    236 | 239 |
    240 | 241 | [footer] 242 |
    243 |
    244 |
    245 |
    246 |
    247 |

    Back to top

    248 |

    {footer#{footer}}

    249 |
    250 |
    251 | ifdef::link-assets[] 252 | template::[linked-footer-assets] 253 | endif::link-assets[] 254 | ifndef::link-assets[] 255 | template::[inline-footer-assets] 256 | endif::link-assets[] 257 | 258 | 259 | 260 | 261 | [linked-header-assets] 262 | 263 | 264 | 265 | 266 | 269 | 270 | 271 | [inline-header-assets] 272 | 301 | 304 | 305 | 306 | [linked-footer-assets] 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | [inline-footer-assets] 315 | 316 | 325 | -------------------------------------------------------------------------------- /examples/base-css-article.asciidoc: -------------------------------------------------------------------------------- 1 | Base · Bootstrap 2 | ================ 3 | Twitter 4 | :title: Base CSS 5 | :description: Fundamental HTML elements styled and enhanced with extensible classes. 6 | :footer: Designed and built with all the love in the world by @mdo and @fat. 7 | :brand: Bootstrap 8 | :doctype: article 9 | :toc: 10 | :backend: bootstrap-docs 11 | //:bootstrapdocsdir: {indir} 12 | :link-assets: 13 | :glyphicons: http://glyphicons.com[Glyphicons] 14 | 15 | == Typography 16 | 17 | === Headings 18 | 19 | All HTML headings, `

    ` through `

    ` are available. 20 | 21 | ========== 22 | [float] 23 | = h1. Heading 1 24 | [float] 25 | == h2. Heading 2 26 | [float] 27 | === h3. Heading 3 28 | [float] 29 | ==== h4. Heading 4 30 | [float] 31 | ===== h5. Heading 5 32 | ========== 33 | 34 | [caption="Heads up!", name="info"] 35 | NOTE: AsciiDoc only supports headings through `
    `. 36 | 37 | === Body copy 38 | 39 | Bootstrap's global default `font-size` is *14px*, with a `line-height` of *20px*. This is applied to the `` and all paragraphs. In addition, `

    ` (paragraphs) receive a bottom margin of half their line-height (10px by default). 40 | 41 | ==== 42 | Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula. 43 | 44 | Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec ullamcorper nulla non metus auctor fringilla. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. 45 | 46 | Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. 47 | ==== 48 | 49 | [listing] 50 |

    ...

    51 | 52 | ==== Lead body copy 53 | 54 | Make a paragraph stand out by adding `.lead`. 55 | 56 | ==== 57 | [role="lead"] 58 | Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus. 59 | ==== 60 | 61 | [listing] 62 |

    ...

    63 | 64 | ==== Built with Less 65 | 66 | The typographic scale is based on two LESS variables in *variables.less*: `@baseFontSize` and `@baseLineHeight`. The first is the base font-size used throughout and the second is the base line-height. We use those variables and some simple math to create the margins, paddings, and line-heights of all our type and more. Customize them and Bootstrap adapts. 67 | 68 | '''' 69 | 70 | === Emphasis 71 | 72 | Make use of HTML's default emphasis tags with lightweight styles. 73 | 74 | ==== `small` 75 | 76 | For de-emphasizing inline or blocks of text, _use the small tag._ 77 | 78 | ==== 79 | _This line of text is meant to be treated as fine print._ 80 | ==== 81 | 82 | [listing] 83 |

    84 | This line of text is meant to be treated as fine print. 85 |

    86 | 87 | ==== Bold 88 | 89 | For emphasizing a snippet of text with a heavier font-weight. 90 | 91 | ==== 92 | The following snippet of text is *rendered as bold text*. 93 | ==== 94 | 95 | [listing] 96 | rendered as bold text 97 | 98 | ==== Italics 99 | 100 | For emphasizing a snippet of text with italics. 101 | 102 | ==== 103 | The following snippet of text is 'rendered as italicized text'. 104 | ==== 105 | 106 | [listing] 107 | rendered as italicized text 108 | 109 | [caption="Heads up!", name="info"] 110 | NOTE: Feel free to use `` and `` in HTML5. `` is meant to highlight words or phrases without conveying additional importance while `` is mostly for voice, technical terms, etc. 111 | 112 | ==== Emphasis classes 113 | 114 | Convey meaning through color with a handful of emphasis utility classes. 115 | 116 | ==== 117 | [role="muted"] 118 | Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh. 119 | [role="text-warning"] 120 | Etiam porta sem malesuada magna mollis euismod. 121 | [role="text-error"] 122 | Donec ullamcorper nulla non metus auctor fringilla. 123 | [role="text-info"] 124 | Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis. 125 | [role="text-success"] 126 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula. 127 | ==== 128 | 129 | [options="linenums"] 130 | ---- 131 |

    Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

    132 |

    Etiam porta sem malesuada magna mollis euismod.

    133 |

    Donec ullamcorper nulla non metus auctor fringilla.

    134 |

    Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis.

    135 |

    Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

    136 | ---- 137 | 138 | '''' 139 | 140 | === Abbreviations 141 | 142 | Stylized implemenation of HTML's `` element for abbreviations and acronyms to show the expanded version on hover. Abbreviations with a `title` attribute have a light dotted bottom border and a help cursor on hover, providing additional context on hover. 143 | 144 | ==== `` 145 | 146 | For expanded text on long hover of an abbreviation, include the `title` attribute. 147 | 148 | ==== 149 | An abbreviation of the word attribute is abbr:attr[attribute]. 150 | ==== 151 | 152 | [listing] 153 | attr 154 | 155 | ==== `` 156 | 157 | Add `.initialism` to an abbreviation for a slightly smaller font-size. 158 | 159 | ==== 160 | abbr:HTML[title="HyperText Markup Language", role="initialism"] is the best thing since sliced bread. 161 | ==== 162 | 163 | [listing] 164 | HTML 165 | 166 | '''' 167 | 168 | === Addresses 169 | 170 | Present contact information for the nearest ancestor or the entire body of work. 171 | 172 | ==== `
    ` 173 | 174 | Preserve formatting by ending all lines with `
    `. 175 | 176 | ==== 177 | [address] 178 | ---- 179 | *Twitter, Inc.* + 180 | 795 Folsom Ave, Suite 600 + 181 | San Francisco, CA 94107 + 182 | abbr:P[Phone]: (123) 456-7890 183 | ---- 184 | [address] 185 | ---- 186 | *Full Name* + 187 | first.last@gmail.com 188 | ---- 189 | ==== 190 | 191 | [options="linenums"] 192 | ---- 193 |
    194 | Twitter, Inc.
    195 | 795 Folsom Ave, Suite 600
    196 | San Francisco, CA 94107
    197 | P: (123) 456-7890 198 |
    199 | 200 |
    201 | Full Name
    202 | first.last@gmail.com 203 |
    204 | ---- 205 | 206 | '''' 207 | 208 | === Blockquotes 209 | 210 | For quoting blocks of content from another source within your document. 211 | 212 | ==== Default blockquote 213 | 214 | Wrap `
    ` around any abbr:HTML[HyperText Markup Language] as the quote. For straight quotes we recommend a `

    `. 215 | 216 | ==== 217 | [quote] 218 | ---- 219 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 220 | ---- 221 | ==== 222 | 223 | [options="linenums"] 224 | ---- 225 |

    226 |

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

    227 |
    228 | ---- 229 | 230 | ==== Blockquote options 231 | 232 | Style and content changes for simple variations on a standard blockquote. 233 | 234 | ===== Naming a source 235 | 236 | Add `` tag for identifying the source. Wrap the name of the source work in ``. 237 | 238 | [attribution="Someone famous in", citetitle="Source Title", options="exampleblock"] 239 | ____ 240 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 241 | ____ 242 | 243 | [options="linenums"] 244 | ---- 245 |
    246 |

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

    247 | Someone famous Source Title 248 |
    249 | ---- 250 | 251 | ===== Alternate displays 252 | 253 | Use `.pull-right` for a floated, right-aligned blockquote. 254 | 255 | [attribution="Someone famous in", citetitle="Source Title", options="exampleblock", role="pull-right"] 256 | ____ 257 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 258 | ____ 259 | 260 | [options="linenums"] 261 | ---- 262 |
    263 | ... 264 |
    265 | ---- 266 | 267 | '''' 268 | 269 | === Lists 270 | 271 | ==== Unordered 272 | 273 | A list of items in which the order does 'not' explicitly matter. 274 | 275 | ==== 276 | - Lorem ipsum dolor sit amet 277 | - Consectetur adipiscing elit 278 | - Integer molestie lorem at massa 279 | - Facilisis in pretium nisl aliquet 280 | - Nulla volutpat aliquam velit 281 | ** Phasellus iaculis neque 282 | ** Purus sodales ultricies 283 | ** Vestibulum laoreet porttitor sem 284 | ** Ac tristique libero volutpat at 285 | - Faucibus porta lacus fringilla vel 286 | - Aenean sit amet erat nunc 287 | - Eget porttitor lorem 288 | ==== 289 | 290 | [options="linenums"] 291 | ---- 292 |
      293 |
    • ...
    • 294 |
    295 | ---- 296 | 297 | ==== Ordered 298 | 299 | A list of items in which the order 'does' explicitly matter. 300 | 301 | ==== 302 | . Lorem ipsum dolor sit amet 303 | . Consectetur adipiscing elit 304 | . Integer molestie lorem at massa 305 | . Facilisis in pretium nisl aliquet 306 | . Nulla volutpat aliquam velit 307 | . Faucibus porta lacus fringilla vel 308 | . Aenean sit amet erat nunc 309 | . Eget porttitor lorem 310 | ==== 311 | 312 | [options="linenums"] 313 | ---- 314 |
      315 |
    1. ...
    2. 316 |
    317 | ---- 318 | 319 | ==== Unstyled 320 | 321 | A list of items with no `list-style` or additional left padding. 322 | 323 | ==== 324 | [role="unstyled"] 325 | - Lorem ipsum dolor sit amet 326 | - Consectetur adipiscing elit 327 | - Integer molestie lorem at massa 328 | - Facilisis in pretium nisl aliquet 329 | - Nulla volutpat aliquam velit 330 | ** Phasellus iaculis neque 331 | ** Purus sodales ultricies 332 | ** Vestibulum laoreet porttitor sem 333 | ** Ac tristique libero volutpat at 334 | - Faucibus porta lacus fringilla vel 335 | - Aenean sit amet erat nunc 336 | - Eget porttitor lorem 337 | ==== 338 | 339 | [options="linenums"] 340 | ---- 341 |
      342 |
    • ...
    • 343 |
    344 | ---- 345 | 346 | ==== Description 347 | 348 | A list of terms with their associated descriptions. 349 | 350 | ==== 351 | Description lists:: A description list is perfect for defining terms. 352 | Euismod:: Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit. + 353 | Donec id elit non mi porta gravida at eget metus. 354 | Malesuada porta:: Etiam porta sem malesuada magna mollis euismod. 355 | ==== 356 | 357 | [options="linenums"] 358 | ---- 359 |
    360 |
    ...
    361 |
    ...
    362 |
    363 | ---- 364 | 365 | ===== Horizontal description 366 | 367 | Make terms and descriptions in `
    ` line up side-by-side. 368 | 369 | ==== 370 | [horizontal] 371 | Description lists:: A description list is perfect for defining terms. 372 | Euismod:: Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit. + 373 | Donec id elit non mi porta gravida at eget metus. 374 | Malesuada porta:: Etiam porta sem malesuada magna mollis euismod. 375 | Felis euismod semper eget lacinia:: Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. 376 | ==== 377 | 378 | [options="linenums"] 379 | ---- 380 |
    381 |
    ...
    382 |
    ...
    383 |
    384 | ---- 385 | 386 | [caption="Heads up!", name="info"] 387 | NOTE: Horizontal description lists will truncate terms that are too long to fit in the left column fix `text-overflow`. In narrower viewports, they will change to the default stacked layout. 388 | 389 | == Code 390 | 391 | === Inline 392 | 393 | Wrap inline snippets of code with ``. 394 | 395 | [quote] 396 | For example, `
    ` should be wrapped as inline. 397 | 398 | [options="linenums"] 399 | ---- 400 | For example,
    should be wrapped as inline. 401 | ---- 402 | 403 | === Basic block 404 | 405 | Use `
    ` for multiple lines of code. Be sure to escape any angle brackets in the code for proper rendering.
    406 | 
    407 | ====
    408 | ----
    409 | 

    Sample text here...

    410 | ---- 411 | ==== 412 | 413 | [options="linenums"] 414 | ---- 415 |
    416 |   

    Sample text here...

    417 |
    418 | ---- 419 | 420 | [caption="Heads up!", name="info"] 421 | NOTE: Be sure to keep code within `
    ` tags as close to the left as possible; it will render all tabs.
    422 | 
    423 | You may optionally add the `.pre-scrollable` class which will set a max-height of 350px and provide a y-axis scrollbar.
    424 | 
    425 | ==  Tables
    426 | 
    427 | ===  Default styles
    428 | 
    429 | For basic styling--light padding and only horizontal dividers--add the base class `.table` to any ``.
    430 | 
    431 | ====
    432 | [format="csv", options="header,autowidth", role="table"]
    433 | |==============================
    434 | #,First Name,Last Name,Username
    435 | 1,Mark,Otto,@mdo
    436 | 2,Jacob,Thornton,@fat
    437 | 3,Larry,the Bird,@twitter
    438 | |==============================
    439 | ====
    440 | 
    441 | [options="linenums"]
    442 | ----
    443 | 
    444 | ... 445 |
    446 | ---- 447 | 448 | '''' 449 | 450 | === Optional classes 451 | 452 | Add any of the following classes to the `.table` base class. 453 | 454 | ==== `.table-striped` 455 | 456 | Adds zebra-striping to any table row within the `` via the `:nth-child` CSS selector (not available in IE7-IE8). 457 | 458 | ==== 459 | [format="csv", options="header,autowidth", role="table table-striped"] 460 | |============================== 461 | #,First Name,Last Name,Username 462 | 1,Mark,Otto,@mdo 463 | 2,Jacob,Thornton,@fat 464 | 3,Larry,the Bird,@twitter 465 | |============================== 466 | ==== 467 | 468 | [options="linenums"] 469 | ---- 470 | 471 | ... 472 |
    473 | ---- 474 | 475 | ==== `.table-bordered` 476 | 477 | Add borders and rounded corners to the table. 478 | 479 | ==== 480 | [options="header,autowidth", role="table table-bordered"] 481 | |============================== 482 | |#|First Name|Last Name|Username 483 | .2+|1 |Mark |Otto |@mdo 484 | |Mark |Otto |@TwBootstrap 485 | |2 |Jacob |Thornton |@fat 486 | |3 2+|Larry the Bird |@twitter 487 | |============================== 488 | ==== 489 | 490 | [options="linenums"] 491 | ---- 492 | 493 | ... 494 |
    495 | ---- 496 | 497 | ==== `.table-hover` 498 | 499 | Enable a hover state on table rows within a ``. 500 | 501 | ==== 502 | [options="header,autowidth", role="table table-hover"] 503 | |============================== 504 | |#|First Name|Last Name|Username 505 | |1 |Mark |Otto |@TwBootstrap 506 | |2 |Jacob |Thornton |@fat 507 | |3 2+|Larry the Bird |@twitter 508 | |============================== 509 | ==== 510 | 511 | [options="linenums"] 512 | ---- 513 | 514 | ... 515 |
    516 | ---- 517 | 518 | ==== `.table-condensed` 519 | 520 | Makes tables more compact by cutting cell padding in half. 521 | 522 | ==== 523 | [options="header,autowidth", role="table table-condensed"] 524 | |============================== 525 | |#|First Name|Last Name|Username 526 | |1 |Mark |Otto |@TwBootstrap 527 | |2 |Jacob |Thornton |@fat 528 | |3 2+|Larry the Bird |@twitter 529 | |============================== 530 | ==== 531 | 532 | [options="linenums"] 533 | ---- 534 | 535 | ... 536 |
    537 | ---- 538 | 539 | '''' 540 | 541 | === Optional row classes 542 | 543 | Use contextual classes to color table rows. 544 | 545 | [format="csv", options="header", cols="1,7", role="table table-bordered table-striped"] 546 | |============================== 547 | Class,Description 548 | `.success`, Indicates a successful or positive action. 549 | `.error`, Indicates a dangerous or potentially negative action. 550 | `.warning`,Indicates a warning that might need attention. 551 | `.info`,Used as an alternative to the default styles. 552 | |============================== 553 | 554 | // can't do this one, asciidoc doesn't support it 555 | ==== 556 | [options="header,autowidth", role="table", bodyrows="success,error,warning,info"] 557 | |============================= 558 | |# |Product |Payment Taken |Status 559 | |{counter:payments} |TB - Monthly |01/04/2012 |Approved 560 | |{counter:payments} |TB - Monthly |02/04/2012 |Declined 561 | |{counter:payments} |TB - Monthly |03/04/2012 |Pending 562 | |{counter:payments} |TB - Monthly |04/04/2012 |Call in to confirm 563 | |============================= 564 | ==== 565 | 566 | [options="linenums"] 567 | ---- 568 | ... 569 | 570 | 1 571 | TB - Monthly 572 | 01/04/2012 573 | Approved 574 | 575 | ... 576 | ---- 577 | 578 | '''' 579 | 580 | === Supported table markup 581 | 582 | List of supported table HTML elements and how they should be used. 583 | 584 | [options="header", cols="1,7", role="table table-bordered table-striped"] 585 | |================ 586 | |Tag |Description 587 | |`table` |Wrapping element for displaying data in a tabular format 588 | |`thead` |Container element for table header rows (``) to label table columns 589 | |`tbody` |Container element for table rows (``) in the body of the table 590 | |`tr` |Container element for a set of table cells (`` or ``) that appears on a single row 591 | |`td` |Default table cell 592 | |`th` |Special table cell for column (or row, depending on scope and placement) labels + 593 | Must be used within a `` 594 | |`caption` |Description or summary of what the table holds, especially useful for screen readers 595 | |================ 596 | 597 | [options="linenums"] 598 | ---- 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 |
    ...
    ......
    ......
    614 | ---- 615 | 616 | '''' 617 | 618 | == Forms 619 | 620 | Not applicable to AsciiDoc. 621 | 622 | == Buttons 623 | 624 | Not applicable to AsciiDoc. 625 | 626 | [id="icons"] 627 | == Icons _by http://glyphicons.com[Glyphicons]_ 628 | 629 | === Icon glyphs 630 | 631 | 140 icons in sprite form, available in dark gray (default) and white, provided by {glyphicons}. 632 | 633 | [role="the-icons clearfix"] 634 | - [icon-glass]#{empty}# icon-glass 635 | - [icon-music]#{empty}# icon-music 636 | - [icon-search]#{empty}# icon-search 637 | - [icon-envelope]#{empty}# icon-envelope 638 | - [icon-heart]#{empty}# icon-heart 639 | - [icon-star]#{empty}# icon-star 640 | - [icon-star-empty]#{empty}# icon-star-empty 641 | - [icon-user]#{empty}# icon-user 642 | - [icon-film]#{empty}# icon-film 643 | - [icon-th-large]#{empty}# icon-th-large 644 | - [icon-th]#{empty}# icon-th 645 | - [icon-th-list]#{empty}# icon-th-list 646 | - [icon-ok]#{empty}# icon-ok 647 | - [icon-remove]#{empty}# icon-remove 648 | - [icon-zoom-in]#{empty}# icon-zoom-in 649 | - [icon-zoom-out]#{empty}# icon-zoom-out 650 | - [icon-off]#{empty}# icon-off 651 | - [icon-signal]#{empty}# icon-signal 652 | - [icon-cog]#{empty}# icon-cog 653 | - [icon-trash]#{empty}# icon-trash 654 | - [icon-home]#{empty}# icon-home 655 | - [icon-file]#{empty}# icon-file 656 | - [icon-time]#{empty}# icon-time 657 | - [icon-road]#{empty}# icon-road 658 | - [icon-download-alt]#{empty}# icon-download-alt 659 | - [icon-download]#{empty}# icon-download 660 | - [icon-upload]#{empty}# icon-upload 661 | - [icon-inbox]#{empty}# icon-inbox 662 | // break 663 | - [icon-play-circle]#{empty}# icon-play-circle 664 | - [icon-repeat]#{empty}# icon-repeat 665 | - [icon-refresh]#{empty}# icon-refresh 666 | - [icon-list-alt]#{empty}# icon-list-alt 667 | - [icon-lock]#{empty}# icon-lock 668 | - [icon-flag]#{empty}# icon-flag 669 | - [icon-headphones]#{empty}# icon-headphones 670 | - [icon-volume-off]#{empty}# icon-volume-off 671 | - [icon-volume-down]#{empty}# icon-volume-down 672 | - [icon-volume-up]#{empty}# icon-volume-up 673 | - [icon-qrcode]#{empty}# icon-qrcode 674 | - [icon-barcode]#{empty}# icon-barcode 675 | - [icon-tag]#{empty}# icon-tag 676 | - [icon-tags]#{empty}# icon-tags 677 | - [icon-book]#{empty}# icon-book 678 | - [icon-bookmark]#{empty}# icon-bookmark 679 | - [icon-print]#{empty}# icon-print 680 | - [icon-camera]#{empty}# icon-camera 681 | - [icon-font]#{empty}# icon-font 682 | - [icon-bold]#{empty}# icon-bold 683 | - [icon-italic]#{empty}# icon-italic 684 | - [icon-text-height]#{empty}# icon-text-height 685 | - [icon-text-width]#{empty}# icon-text-width 686 | - [icon-align-left]#{empty}# icon-align-left 687 | - [icon-align-center]#{empty}# icon-align-center 688 | - [icon-align-right]#{empty}# icon-align-right 689 | - [icon-align-justify]#{empty}# icon-align-justify 690 | - [icon-list]#{empty}# icon-list 691 | // break 692 | - [icon-indent-left]#{empty}# icon-indent-left 693 | - [icon-indent-right]#{empty}# icon-indent-right 694 | - [icon-facetime-video]#{empty}# icon-facetime-video 695 | - [icon-picture]#{empty}# icon-picture 696 | - [icon-pencil]#{empty}# icon-pencil 697 | - [icon-map-marker]#{empty}# icon-map-marker 698 | - [icon-adjust]#{empty}# icon-adjust 699 | - [icon-tint]#{empty}# icon-tint 700 | - [icon-edit]#{empty}# icon-edit 701 | - [icon-share]#{empty}# icon-share 702 | - [icon-check]#{empty}# icon-check 703 | - [icon-move]#{empty}# icon-move 704 | - [icon-step-backward]#{empty}# icon-step-backward 705 | - [icon-fast-backward]#{empty}# icon-fast-backward 706 | - [icon-backward]#{empty}# icon-backward 707 | - [icon-play]#{empty}# icon-play 708 | - [icon-pause]#{empty}# icon-pause 709 | - [icon-stop]#{empty}# icon-stop 710 | - [icon-forward]#{empty}# icon-forward 711 | - [icon-fast-forward]#{empty}# icon-fast-forward 712 | - [icon-step-forward]#{empty}# icon-step-forward 713 | - [icon-eject]#{empty}# icon-eject 714 | - [icon-chevron-left]#{empty}# icon-chevron-left 715 | - [icon-chevron-right]#{empty}# icon-chevron-right 716 | - [icon-plus-sign]#{empty}# icon-plus-sign 717 | - [icon-minus-sign]#{empty}# icon-minus-sign 718 | - [icon-remove-sign]#{empty}# icon-remove-sign 719 | - [icon-ok-sign]#{empty}# icon-ok-sign 720 | // break 721 | - [icon-question-sign]#{empty}# icon-question-sign 722 | - [icon-info-sign]#{empty}# icon-info-sign 723 | - [icon-screenshot]#{empty}# icon-screenshot 724 | - [icon-remove-circle]#{empty}# icon-remove-circle 725 | - [icon-ok-circle]#{empty}# icon-ok-circle 726 | - [icon-ban-circle]#{empty}# icon-ban-circle 727 | - [icon-arrow-left]#{empty}# icon-arrow-left 728 | - [icon-arrow-right]#{empty}# icon-arrow-right 729 | - [icon-arrow-up]#{empty}# icon-arrow-up 730 | - [icon-arrow-down]#{empty}# icon-arrow-down 731 | - [icon-share-alt]#{empty}# icon-share-alt 732 | - [icon-resize-full]#{empty}# icon-resize-full 733 | - [icon-resize-small]#{empty}# icon-resize-small 734 | - [icon-plus]#{empty}# icon-plus 735 | - [icon-minus]#{empty}# icon-minus 736 | - [icon-asterisk]#{empty}# icon-asterisk 737 | - [icon-exclamation-sign]#{empty}# icon-exclamation-sign 738 | - [icon-gift]#{empty}# icon-gift 739 | - [icon-leaf]#{empty}# icon-leaf 740 | - [icon-fire]#{empty}# icon-fire 741 | - [icon-eye-open]#{empty}# icon-eye-open 742 | - [icon-eye-close]#{empty}# icon-eye-close 743 | - [icon-warning-sign]#{empty}# icon-warning-sign 744 | - [icon-plane]#{empty}# icon-plane 745 | - [icon-calendar]#{empty}# icon-calendar 746 | - [icon-random]#{empty}# icon-random 747 | - [icon-comment]#{empty}# icon-comment 748 | - [icon-magnet]#{empty}# icon-magnet 749 | // break 750 | - [icon-chevron-up]#{empty}# icon-chevron-up 751 | - [icon-chevron-down]#{empty}# icon-chevron-down 752 | - [icon-retweet]#{empty}# icon-retweet 753 | - [icon-shopping-cart]#{empty}# icon-shopping-cart 754 | - [icon-folder-close]#{empty}# icon-folder-close 755 | - [icon-folder-open]#{empty}# icon-folder-open 756 | - [icon-resize-vertical]#{empty}# icon-resize-vertical 757 | - [icon-resize-horizontal]#{empty}# icon-resize-horizontal 758 | - [icon-hdd]#{empty}# icon-hdd 759 | - [icon-bullhorn]#{empty}# icon-bullhorn 760 | - [icon-bell]#{empty}# icon-bell 761 | - [icon-certificate]#{empty}# icon-certificate 762 | - [icon-thumbs-up]#{empty}# icon-thumbs-up 763 | - [icon-thumbs-down]#{empty}# icon-thumbs-down 764 | - [icon-hand-right]#{empty}# icon-hand-right 765 | - [icon-hand-left]#{empty}# icon-hand-left 766 | - [icon-hand-up]#{empty}# icon-hand-up 767 | - [icon-hand-down]#{empty}# icon-hand-down 768 | - [icon-circle-arrow-right]#{empty}# icon-circle-arrow-right 769 | - [icon-circle-arrow-left]#{empty}# icon-circle-arrow-left 770 | - [icon-circle-arrow-up]#{empty}# icon-circle-arrow-up 771 | - [icon-circle-arrow-down]#{empty}# icon-circle-arrow-down 772 | - [icon-globe]#{empty}# icon-globe 773 | - [icon-wrench]#{empty}# icon-wrench 774 | - [icon-tasks]#{empty}# icon-tasks 775 | - [icon-filter]#{empty}# icon-filter 776 | - [icon-briefcase]#{empty}# icon-briefcase 777 | - [icon-fullscreen]#{empty}# icon-fullscreen 778 | 779 | ==== Glyphicons attribution 780 | 781 | {glyphicons} Halflings are normally not available for free, but an arrangement between Bootstrap and the Glyphicons creators have made this possible at no cost to you as developers. As a thank you, we ask you to include an optional link back to {glyphicons} whenever practical. 782 | 783 | '''' 784 | 785 | === How to use 786 | 787 | All icons require an `` tag with a unique class, prefixed with `icon-`. To use, place the following code just about anywhere: 788 | 789 | [options="linenums"] 790 | ---- 791 | 792 | ---- 793 | 794 | There are also styles available for inverted (white) icons, made ready with one extra class. We will specifically enforce this class on hover and active states for nav and dropdown links. 795 | 796 | [options="linenums"] 797 | ---- 798 | 799 | ---- 800 | 801 | [caption="Heads up!", name="info"] 802 | When using beside strings of text, as in buttons or nav links, be sure to leave a space after the `` tag for proper spacing. 803 | 804 | '''' 805 | 806 | === Icon examples 807 | 808 | Use them in buttons, button groups for a toolbar, navigation, or prepended form inputs. 809 | 810 | ==== Buttons 811 | 812 | ===== Button group in a button toolbar 813 | 814 | ... 815 | 816 | [options="linenums"] 817 | ---- 818 |
    819 |
    820 | 821 | 822 | 823 | 824 | 825 |
    826 |
    827 | ---- 828 | 829 | ===== Dropdown in a button group 830 | 831 | ... 832 | -------------------------------------------------------------------------------- /examples/base-css-book.asciidoc: -------------------------------------------------------------------------------- 1 | Base · Bootstrap 2 | ================ 3 | Twitter 4 | :title: Base CSS 5 | :description: Fundamental HTML elements styled and enhanced with extensible classes. 6 | :footer: Designed and built with all the love in the world by @mdo and @fat. 7 | :brand: Bootstrap 8 | :doctype: book 9 | :toc: 10 | :backend: bootstrap-docs 11 | //:bootstrapdocsdir: {indir} 12 | :link-assets: 13 | :glyphicons: http://glyphicons.com[Glyphicons] 14 | 15 | = Typography 16 | 17 | == Headings 18 | 19 | All HTML headings, `

    ` through `

    ` are available. 20 | 21 | ========== 22 | [float] 23 | = h1. Heading 1 24 | [float] 25 | == h2. Heading 2 26 | [float] 27 | === h3. Heading 3 28 | [float] 29 | ==== h4. Heading 4 30 | [float] 31 | ===== h5. Heading 5 32 | ========== 33 | 34 | [caption="Heads up!", name="info"] 35 | NOTE: AsciiDoc only supports headings through `
    `. 36 | 37 | == Body copy 38 | 39 | Bootstrap's global default `font-size` is *14px*, with a `line-height` of *20px*. This is applied to the `` and all paragraphs. In addition, `

    ` (paragraphs) receive a bottom margin of half their line-height (10px by default). 40 | 41 | ==== 42 | Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula. 43 | 44 | Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec ullamcorper nulla non metus auctor fringilla. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Donec ullamcorper nulla non metus auctor fringilla. 45 | 46 | Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. 47 | ==== 48 | 49 | [listing] 50 |

    ...

    51 | 52 | === Lead body copy 53 | 54 | Make a paragraph stand out by adding `.lead`. 55 | 56 | ==== 57 | [role="lead"] 58 | Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus. 59 | ==== 60 | 61 | [listing] 62 |

    ...

    63 | 64 | === Built with Less 65 | 66 | The typographic scale is based on two LESS variables in *variables.less*: `@baseFontSize` and `@baseLineHeight`. The first is the base font-size used throughout and the second is the base line-height. We use those variables and some simple math to create the margins, paddings, and line-heights of all our type and more. Customize them and Bootstrap adapts. 67 | 68 | '''' 69 | 70 | == Emphasis 71 | 72 | Make use of HTML's default emphasis tags with lightweight styles. 73 | 74 | === `small` 75 | 76 | For de-emphasizing inline or blocks of text, _use the small tag._ 77 | 78 | ==== 79 | _This line of text is meant to be treated as fine print._ 80 | ==== 81 | 82 | [listing] 83 |

    84 | This line of text is meant to be treated as fine print. 85 |

    86 | 87 | === Bold 88 | 89 | For emphasizing a snippet of text with a heavier font-weight. 90 | 91 | ==== 92 | The following snippet of text is *rendered as bold text*. 93 | ==== 94 | 95 | [listing] 96 | rendered as bold text 97 | 98 | === Italics 99 | 100 | For emphasizing a snippet of text with italics. 101 | 102 | ==== 103 | The following snippet of text is 'rendered as italicized text'. 104 | ==== 105 | 106 | [listing] 107 | rendered as italicized text 108 | 109 | [caption="Heads up!", name="info"] 110 | NOTE: Feel free to use `` and `` in HTML5. `` is meant to highlight words or phrases without conveying additional importance while `` is mostly for voice, technical terms, etc. 111 | 112 | === Emphasis classes 113 | 114 | Convey meaning through color with a handful of emphasis utility classes. 115 | 116 | ==== 117 | [role="muted"] 118 | Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh. 119 | [role="text-warning"] 120 | Etiam porta sem malesuada magna mollis euismod. 121 | [role="text-error"] 122 | Donec ullamcorper nulla non metus auctor fringilla. 123 | [role="text-info"] 124 | Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis. 125 | [role="text-success"] 126 | Duis mollis, est non commodo luctus, nisi erat porttitor ligula. 127 | ==== 128 | 129 | [options="linenums"] 130 | ---- 131 |

    Fusce dapibus, tellus ac cursus commodo, tortor mauris nibh.

    132 |

    Etiam porta sem malesuada magna mollis euismod.

    133 |

    Donec ullamcorper nulla non metus auctor fringilla.

    134 |

    Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis.

    135 |

    Duis mollis, est non commodo luctus, nisi erat porttitor ligula.

    136 | ---- 137 | 138 | '''' 139 | 140 | == Abbreviations 141 | 142 | Stylized implemenation of HTML's `` element for abbreviations and acronyms to show the expanded version on hover. Abbreviations with a `title` attribute have a light dotted bottom border and a help cursor on hover, providing additional context on hover. 143 | 144 | === `` 145 | 146 | For expanded text on long hover of an abbreviation, include the `title` attribute. 147 | 148 | ==== 149 | An abbreviation of the word attribute is abbr:attr[attribute]. 150 | ==== 151 | 152 | [listing] 153 | attr 154 | 155 | === `` 156 | 157 | Add `.initialism` to an abbreviation for a slightly smaller font-size. 158 | 159 | ==== 160 | abbr:HTML[title="HyperText Markup Language", role="initialism"] is the best thing since sliced bread. 161 | ==== 162 | 163 | [listing] 164 | HTML 165 | 166 | '''' 167 | 168 | == Addresses 169 | 170 | Present contact information for the nearest ancestor or the entire body of work. 171 | 172 | === `
    ` 173 | 174 | Preserve formatting by ending all lines with `
    `. 175 | 176 | ==== 177 | [address] 178 | ---- 179 | *Twitter, Inc.* + 180 | 795 Folsom Ave, Suite 600 + 181 | San Francisco, CA 94107 + 182 | abbr:P[Phone]: (123) 456-7890 183 | ---- 184 | [address] 185 | ---- 186 | *Full Name* + 187 | first.last@gmail.com 188 | ---- 189 | ==== 190 | 191 | [options="linenums"] 192 | ---- 193 |
    194 | Twitter, Inc.
    195 | 795 Folsom Ave, Suite 600
    196 | San Francisco, CA 94107
    197 | P: (123) 456-7890 198 |
    199 | 200 |
    201 | Full Name
    202 | first.last@gmail.com 203 |
    204 | ---- 205 | 206 | '''' 207 | 208 | == Blockquotes 209 | 210 | For quoting blocks of content from another source within your document. 211 | 212 | === Default blockquote 213 | 214 | Wrap `
    ` around any abbr:HTML[HyperText Markup Language] as the quote. For straight quotes we recommend a `

    `. 215 | 216 | ==== 217 | [quote] 218 | ---- 219 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 220 | ---- 221 | ==== 222 | 223 | [options="linenums"] 224 | ---- 225 |

    226 |

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

    227 |
    228 | ---- 229 | 230 | === Blockquote options 231 | 232 | Style and content changes for simple variations on a standard blockquote. 233 | 234 | ==== Naming a source 235 | 236 | Add `` tag for identifying the source. Wrap the name of the source work in ``. 237 | 238 | [attribution="Someone famous in", citetitle="Source Title", options="exampleblock"] 239 | ____ 240 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 241 | ____ 242 | 243 | [options="linenums"] 244 | ---- 245 |
    246 |

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

    247 | Someone famous Source Title 248 |
    249 | ---- 250 | 251 | ==== Alternate displays 252 | 253 | Use `.pull-right` for a floated, right-aligned blockquote. 254 | 255 | [attribution="Someone famous in", citetitle="Source Title", options="exampleblock", role="pull-right"] 256 | ____ 257 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante. 258 | ____ 259 | 260 | [options="linenums"] 261 | ---- 262 |
    263 | ... 264 |
    265 | ---- 266 | 267 | '''' 268 | 269 | == Lists 270 | 271 | === Unordered 272 | 273 | A list of items in which the order does 'not' explicitly matter. 274 | 275 | ==== 276 | - Lorem ipsum dolor sit amet 277 | - Consectetur adipiscing elit 278 | - Integer molestie lorem at massa 279 | - Facilisis in pretium nisl aliquet 280 | - Nulla volutpat aliquam velit 281 | ** Phasellus iaculis neque 282 | ** Purus sodales ultricies 283 | ** Vestibulum laoreet porttitor sem 284 | ** Ac tristique libero volutpat at 285 | - Faucibus porta lacus fringilla vel 286 | - Aenean sit amet erat nunc 287 | - Eget porttitor lorem 288 | ==== 289 | 290 | [options="linenums"] 291 | ---- 292 |
      293 |
    • ...
    • 294 |
    295 | ---- 296 | 297 | === Ordered 298 | 299 | A list of items in which the order 'does' explicitly matter. 300 | 301 | ==== 302 | . Lorem ipsum dolor sit amet 303 | . Consectetur adipiscing elit 304 | . Integer molestie lorem at massa 305 | . Facilisis in pretium nisl aliquet 306 | . Nulla volutpat aliquam velit 307 | . Faucibus porta lacus fringilla vel 308 | . Aenean sit amet erat nunc 309 | . Eget porttitor lorem 310 | ==== 311 | 312 | [options="linenums"] 313 | ---- 314 |
      315 |
    1. ...
    2. 316 |
    317 | ---- 318 | 319 | === Unstyled 320 | 321 | A list of items with no `list-style` or additional left padding. 322 | 323 | ==== 324 | [role="unstyled"] 325 | - Lorem ipsum dolor sit amet 326 | - Consectetur adipiscing elit 327 | - Integer molestie lorem at massa 328 | - Facilisis in pretium nisl aliquet 329 | - Nulla volutpat aliquam velit 330 | ** Phasellus iaculis neque 331 | ** Purus sodales ultricies 332 | ** Vestibulum laoreet porttitor sem 333 | ** Ac tristique libero volutpat at 334 | - Faucibus porta lacus fringilla vel 335 | - Aenean sit amet erat nunc 336 | - Eget porttitor lorem 337 | ==== 338 | 339 | [options="linenums"] 340 | ---- 341 |
      342 |
    • ...
    • 343 |
    344 | ---- 345 | 346 | === Description 347 | 348 | A list of terms with their associated descriptions. 349 | 350 | ==== 351 | Description lists:: A description list is perfect for defining terms. 352 | Euismod:: Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit. + 353 | Donec id elit non mi porta gravida at eget metus. 354 | Malesuada porta:: Etiam porta sem malesuada magna mollis euismod. 355 | ==== 356 | 357 | [options="linenums"] 358 | ---- 359 |
    360 |
    ...
    361 |
    ...
    362 |
    363 | ---- 364 | 365 | ==== Horizontal description 366 | 367 | Make terms and descriptions in `
    ` line up side-by-side. 368 | 369 | ==== 370 | [horizontal] 371 | Description lists:: A description list is perfect for defining terms. 372 | Euismod:: Vestibulum id ligula porta felis euismod semper eget lacinia odio sem nec elit. + 373 | Donec id elit non mi porta gravida at eget metus. 374 | Malesuada porta:: Etiam porta sem malesuada magna mollis euismod. 375 | Felis euismod semper eget lacinia:: Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. 376 | ==== 377 | 378 | [options="linenums"] 379 | ---- 380 |
    381 |
    ...
    382 |
    ...
    383 |
    384 | ---- 385 | 386 | [caption="Heads up!", name="info"] 387 | NOTE: Horizontal description lists will truncate terms that are too long to fit in the left column fix `text-overflow`. In narrower viewports, they will change to the default stacked layout. 388 | 389 | = Code 390 | 391 | == Inline 392 | 393 | Wrap inline snippets of code with ``. 394 | 395 | [quote] 396 | For example, `
    ` should be wrapped as inline. 397 | 398 | [options="linenums"] 399 | ---- 400 | For example,
    should be wrapped as inline. 401 | ---- 402 | 403 | == Basic block 404 | 405 | Use `
    ` for multiple lines of code. Be sure to escape any angle brackets in the code for proper rendering.
    406 | 
    407 | ====
    408 | ----
    409 | 

    Sample text here...

    410 | ---- 411 | ==== 412 | 413 | [options="linenums"] 414 | ---- 415 |
    416 |   

    Sample text here...

    417 |
    418 | ---- 419 | 420 | [caption="Heads up!", name="info"] 421 | NOTE: Be sure to keep code within `
    ` tags as close to the left as possible; it will render all tabs.
    422 | 
    423 | You may optionally add the `.pre-scrollable` class which will set a max-height of 350px and provide a y-axis scrollbar.
    424 | 
    425 | = Tables
    426 | 
    427 | == Default styles
    428 | 
    429 | For basic styling--light padding and only horizontal dividers--add the base class `.table` to any ``.
    430 | 
    431 | ====
    432 | [format="csv", options="header,autowidth", role="table"]
    433 | |==============================
    434 | #,First Name,Last Name,Username
    435 | 1,Mark,Otto,@mdo
    436 | 2,Jacob,Thornton,@fat
    437 | 3,Larry,the Bird,@twitter
    438 | |==============================
    439 | ====
    440 | 
    441 | [options="linenums"]
    442 | ----
    443 | 
    444 | ... 445 |
    446 | ---- 447 | 448 | '''' 449 | 450 | == Optional classes 451 | 452 | Add any of the following classes to the `.table` base class. 453 | 454 | === `.table-striped` 455 | 456 | Adds zebra-striping to any table row within the `` via the `:nth-child` CSS selector (not available in IE7-IE8). 457 | 458 | ==== 459 | [format="csv", options="header,autowidth", role="table table-striped"] 460 | |============================== 461 | #,First Name,Last Name,Username 462 | 1,Mark,Otto,@mdo 463 | 2,Jacob,Thornton,@fat 464 | 3,Larry,the Bird,@twitter 465 | |============================== 466 | ==== 467 | 468 | [options="linenums"] 469 | ---- 470 | 471 | ... 472 |
    473 | ---- 474 | 475 | === `.table-bordered` 476 | 477 | Add borders and rounded corners to the table. 478 | 479 | ==== 480 | [options="header,autowidth", role="table table-bordered"] 481 | |============================== 482 | |#|First Name|Last Name|Username 483 | .2+|1 |Mark |Otto |@mdo 484 | |Mark |Otto |@TwBootstrap 485 | |2 |Jacob |Thornton |@fat 486 | |3 2+|Larry the Bird |@twitter 487 | |============================== 488 | ==== 489 | 490 | [options="linenums"] 491 | ---- 492 | 493 | ... 494 |
    495 | ---- 496 | 497 | === `.table-hover` 498 | 499 | Enable a hover state on table rows within a ``. 500 | 501 | ==== 502 | [options="header,autowidth", role="table table-hover"] 503 | |============================== 504 | |#|First Name|Last Name|Username 505 | |1 |Mark |Otto |@TwBootstrap 506 | |2 |Jacob |Thornton |@fat 507 | |3 2+|Larry the Bird |@twitter 508 | |============================== 509 | ==== 510 | 511 | [options="linenums"] 512 | ---- 513 | 514 | ... 515 |
    516 | ---- 517 | 518 | === `.table-condensed` 519 | 520 | Makes tables more compact by cutting cell padding in half. 521 | 522 | ==== 523 | [options="header,autowidth", role="table table-condensed"] 524 | |============================== 525 | |#|First Name|Last Name|Username 526 | |1 |Mark |Otto |@TwBootstrap 527 | |2 |Jacob |Thornton |@fat 528 | |3 2+|Larry the Bird |@twitter 529 | |============================== 530 | ==== 531 | 532 | [options="linenums"] 533 | ---- 534 | 535 | ... 536 |
    537 | ---- 538 | 539 | '''' 540 | 541 | == Optional row classes 542 | 543 | Use contextual classes to color table rows. 544 | 545 | [format="csv", options="header", cols="1,7", role="table table-bordered table-striped"] 546 | |============================== 547 | Class,Description 548 | `.success`, Indicates a successful or positive action. 549 | `.error`, Indicates a dangerous or potentially negative action. 550 | `.warning`,Indicates a warning that might need attention. 551 | `.info`,Used as an alternative to the default styles. 552 | |============================== 553 | 554 | // can't do this one, asciidoc doesn't support it 555 | ==== 556 | [options="header,autowidth", role="table", bodyrows="success,error,warning,info"] 557 | |============================= 558 | |# |Product |Payment Taken |Status 559 | |{counter:payments} |TB - Monthly |01/04/2012 |Approved 560 | |{counter:payments} |TB - Monthly |02/04/2012 |Declined 561 | |{counter:payments} |TB - Monthly |03/04/2012 |Pending 562 | |{counter:payments} |TB - Monthly |04/04/2012 |Call in to confirm 563 | |============================= 564 | ==== 565 | 566 | [options="linenums"] 567 | ---- 568 | ... 569 | 570 | 1 571 | TB - Monthly 572 | 01/04/2012 573 | Approved 574 | 575 | ... 576 | ---- 577 | 578 | '''' 579 | 580 | == Supported table markup 581 | 582 | List of supported table HTML elements and how they should be used. 583 | 584 | [options="header", cols="1,7", role="table table-bordered table-striped"] 585 | |================ 586 | |Tag |Description 587 | |`table` |Wrapping element for displaying data in a tabular format 588 | |`thead` |Container element for table header rows (``) to label table columns 589 | |`tbody` |Container element for table rows (``) in the body of the table 590 | |`tr` |Container element for a set of table cells (`` or ``) that appears on a single row 591 | |`td` |Default table cell 592 | |`th` |Special table cell for column (or row, depending on scope and placement) labels + 593 | Must be used within a `` 594 | |`caption` |Description or summary of what the table holds, especially useful for screen readers 595 | |================ 596 | 597 | [options="linenums"] 598 | ---- 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 |
    ...
    ......
    ......
    614 | ---- 615 | 616 | '''' 617 | 618 | = Forms 619 | 620 | Not applicable to AsciiDoc. 621 | 622 | = Buttons 623 | 624 | Not applicable to AsciiDoc. 625 | 626 | [id="icons"] 627 | = Icons _by http://glyphicons.com[Glyphicons]_ 628 | 629 | == Icon glyphs 630 | 631 | 140 icons in sprite form, available in dark gray (default) and white, provided by {glyphicons}. 632 | 633 | [role="the-icons clearfix"] 634 | - [icon-glass]#{empty}# icon-glass 635 | - [icon-music]#{empty}# icon-music 636 | - [icon-search]#{empty}# icon-search 637 | - [icon-envelope]#{empty}# icon-envelope 638 | - [icon-heart]#{empty}# icon-heart 639 | - [icon-star]#{empty}# icon-star 640 | - [icon-star-empty]#{empty}# icon-star-empty 641 | - [icon-user]#{empty}# icon-user 642 | - [icon-film]#{empty}# icon-film 643 | - [icon-th-large]#{empty}# icon-th-large 644 | - [icon-th]#{empty}# icon-th 645 | - [icon-th-list]#{empty}# icon-th-list 646 | - [icon-ok]#{empty}# icon-ok 647 | - [icon-remove]#{empty}# icon-remove 648 | - [icon-zoom-in]#{empty}# icon-zoom-in 649 | - [icon-zoom-out]#{empty}# icon-zoom-out 650 | - [icon-off]#{empty}# icon-off 651 | - [icon-signal]#{empty}# icon-signal 652 | - [icon-cog]#{empty}# icon-cog 653 | - [icon-trash]#{empty}# icon-trash 654 | - [icon-home]#{empty}# icon-home 655 | - [icon-file]#{empty}# icon-file 656 | - [icon-time]#{empty}# icon-time 657 | - [icon-road]#{empty}# icon-road 658 | - [icon-download-alt]#{empty}# icon-download-alt 659 | - [icon-download]#{empty}# icon-download 660 | - [icon-upload]#{empty}# icon-upload 661 | - [icon-inbox]#{empty}# icon-inbox 662 | // break 663 | - [icon-play-circle]#{empty}# icon-play-circle 664 | - [icon-repeat]#{empty}# icon-repeat 665 | - [icon-refresh]#{empty}# icon-refresh 666 | - [icon-list-alt]#{empty}# icon-list-alt 667 | - [icon-lock]#{empty}# icon-lock 668 | - [icon-flag]#{empty}# icon-flag 669 | - [icon-headphones]#{empty}# icon-headphones 670 | - [icon-volume-off]#{empty}# icon-volume-off 671 | - [icon-volume-down]#{empty}# icon-volume-down 672 | - [icon-volume-up]#{empty}# icon-volume-up 673 | - [icon-qrcode]#{empty}# icon-qrcode 674 | - [icon-barcode]#{empty}# icon-barcode 675 | - [icon-tag]#{empty}# icon-tag 676 | - [icon-tags]#{empty}# icon-tags 677 | - [icon-book]#{empty}# icon-book 678 | - [icon-bookmark]#{empty}# icon-bookmark 679 | - [icon-print]#{empty}# icon-print 680 | - [icon-camera]#{empty}# icon-camera 681 | - [icon-font]#{empty}# icon-font 682 | - [icon-bold]#{empty}# icon-bold 683 | - [icon-italic]#{empty}# icon-italic 684 | - [icon-text-height]#{empty}# icon-text-height 685 | - [icon-text-width]#{empty}# icon-text-width 686 | - [icon-align-left]#{empty}# icon-align-left 687 | - [icon-align-center]#{empty}# icon-align-center 688 | - [icon-align-right]#{empty}# icon-align-right 689 | - [icon-align-justify]#{empty}# icon-align-justify 690 | - [icon-list]#{empty}# icon-list 691 | // break 692 | - [icon-indent-left]#{empty}# icon-indent-left 693 | - [icon-indent-right]#{empty}# icon-indent-right 694 | - [icon-facetime-video]#{empty}# icon-facetime-video 695 | - [icon-picture]#{empty}# icon-picture 696 | - [icon-pencil]#{empty}# icon-pencil 697 | - [icon-map-marker]#{empty}# icon-map-marker 698 | - [icon-adjust]#{empty}# icon-adjust 699 | - [icon-tint]#{empty}# icon-tint 700 | - [icon-edit]#{empty}# icon-edit 701 | - [icon-share]#{empty}# icon-share 702 | - [icon-check]#{empty}# icon-check 703 | - [icon-move]#{empty}# icon-move 704 | - [icon-step-backward]#{empty}# icon-step-backward 705 | - [icon-fast-backward]#{empty}# icon-fast-backward 706 | - [icon-backward]#{empty}# icon-backward 707 | - [icon-play]#{empty}# icon-play 708 | - [icon-pause]#{empty}# icon-pause 709 | - [icon-stop]#{empty}# icon-stop 710 | - [icon-forward]#{empty}# icon-forward 711 | - [icon-fast-forward]#{empty}# icon-fast-forward 712 | - [icon-step-forward]#{empty}# icon-step-forward 713 | - [icon-eject]#{empty}# icon-eject 714 | - [icon-chevron-left]#{empty}# icon-chevron-left 715 | - [icon-chevron-right]#{empty}# icon-chevron-right 716 | - [icon-plus-sign]#{empty}# icon-plus-sign 717 | - [icon-minus-sign]#{empty}# icon-minus-sign 718 | - [icon-remove-sign]#{empty}# icon-remove-sign 719 | - [icon-ok-sign]#{empty}# icon-ok-sign 720 | // break 721 | - [icon-question-sign]#{empty}# icon-question-sign 722 | - [icon-info-sign]#{empty}# icon-info-sign 723 | - [icon-screenshot]#{empty}# icon-screenshot 724 | - [icon-remove-circle]#{empty}# icon-remove-circle 725 | - [icon-ok-circle]#{empty}# icon-ok-circle 726 | - [icon-ban-circle]#{empty}# icon-ban-circle 727 | - [icon-arrow-left]#{empty}# icon-arrow-left 728 | - [icon-arrow-right]#{empty}# icon-arrow-right 729 | - [icon-arrow-up]#{empty}# icon-arrow-up 730 | - [icon-arrow-down]#{empty}# icon-arrow-down 731 | - [icon-share-alt]#{empty}# icon-share-alt 732 | - [icon-resize-full]#{empty}# icon-resize-full 733 | - [icon-resize-small]#{empty}# icon-resize-small 734 | - [icon-plus]#{empty}# icon-plus 735 | - [icon-minus]#{empty}# icon-minus 736 | - [icon-asterisk]#{empty}# icon-asterisk 737 | - [icon-exclamation-sign]#{empty}# icon-exclamation-sign 738 | - [icon-gift]#{empty}# icon-gift 739 | - [icon-leaf]#{empty}# icon-leaf 740 | - [icon-fire]#{empty}# icon-fire 741 | - [icon-eye-open]#{empty}# icon-eye-open 742 | - [icon-eye-close]#{empty}# icon-eye-close 743 | - [icon-warning-sign]#{empty}# icon-warning-sign 744 | - [icon-plane]#{empty}# icon-plane 745 | - [icon-calendar]#{empty}# icon-calendar 746 | - [icon-random]#{empty}# icon-random 747 | - [icon-comment]#{empty}# icon-comment 748 | - [icon-magnet]#{empty}# icon-magnet 749 | // break 750 | - [icon-chevron-up]#{empty}# icon-chevron-up 751 | - [icon-chevron-down]#{empty}# icon-chevron-down 752 | - [icon-retweet]#{empty}# icon-retweet 753 | - [icon-shopping-cart]#{empty}# icon-shopping-cart 754 | - [icon-folder-close]#{empty}# icon-folder-close 755 | - [icon-folder-open]#{empty}# icon-folder-open 756 | - [icon-resize-vertical]#{empty}# icon-resize-vertical 757 | - [icon-resize-horizontal]#{empty}# icon-resize-horizontal 758 | - [icon-hdd]#{empty}# icon-hdd 759 | - [icon-bullhorn]#{empty}# icon-bullhorn 760 | - [icon-bell]#{empty}# icon-bell 761 | - [icon-certificate]#{empty}# icon-certificate 762 | - [icon-thumbs-up]#{empty}# icon-thumbs-up 763 | - [icon-thumbs-down]#{empty}# icon-thumbs-down 764 | - [icon-hand-right]#{empty}# icon-hand-right 765 | - [icon-hand-left]#{empty}# icon-hand-left 766 | - [icon-hand-up]#{empty}# icon-hand-up 767 | - [icon-hand-down]#{empty}# icon-hand-down 768 | - [icon-circle-arrow-right]#{empty}# icon-circle-arrow-right 769 | - [icon-circle-arrow-left]#{empty}# icon-circle-arrow-left 770 | - [icon-circle-arrow-up]#{empty}# icon-circle-arrow-up 771 | - [icon-circle-arrow-down]#{empty}# icon-circle-arrow-down 772 | - [icon-globe]#{empty}# icon-globe 773 | - [icon-wrench]#{empty}# icon-wrench 774 | - [icon-tasks]#{empty}# icon-tasks 775 | - [icon-filter]#{empty}# icon-filter 776 | - [icon-briefcase]#{empty}# icon-briefcase 777 | - [icon-fullscreen]#{empty}# icon-fullscreen 778 | 779 | === Glyphicons attribution 780 | 781 | {glyphicons} Halflings are normally not available for free, but an arrangement between Bootstrap and the Glyphicons creators have made this possible at no cost to you as developers. As a thank you, we ask you to include an optional link back to {glyphicons} whenever practical. 782 | 783 | '''' 784 | 785 | == How to use 786 | 787 | All icons require an `` tag with a unique class, prefixed with `icon-`. To use, place the following code just about anywhere: 788 | 789 | [options="linenums"] 790 | ---- 791 | 792 | ---- 793 | 794 | There are also styles available for inverted (white) icons, made ready with one extra class. We will specifically enforce this class on hover and active states for nav and dropdown links. 795 | 796 | [options="linenums"] 797 | ---- 798 | 799 | ---- 800 | 801 | [caption="Heads up!", name="info"] 802 | When using beside strings of text, as in buttons or nav links, be sure to leave a space after the `` tag for proper spacing. 803 | 804 | '''' 805 | 806 | == Icon examples 807 | 808 | Use them in buttons, button groups for a toolbar, navigation, or prepended form inputs. 809 | 810 | === Buttons 811 | 812 | ==== Button group in a button toolbar 813 | 814 | ... 815 | 816 | [options="linenums"] 817 | ---- 818 |
    819 |
    820 | 821 | 822 | 823 | 824 | 825 |
    826 |
    827 | ---- 828 | 829 | ==== Dropdown in a button group 830 | 831 | ... 832 | -------------------------------------------------------------------------------- /examples/javaeeworkshop.asciidoc: -------------------------------------------------------------------------------- 1 | // 2 | // Export Commands 3 | // =============== 4 | // to HTML5: 5 | // asciidoc -b html5 -a icons -a theme=default -a data-uri -a toc2 -a pygments -f javaeeworkshop.conf javaeeworkshop.asciidoc 6 | // 7 | // to DocBook: 8 | // asciidoc -b docbook -dbook -f javaeeworkshop.conf javaeeworkshop.asciidoc 9 | // 10 | // to PDF (using fop): 11 | // a2x -fpdf -dbook --fop --icons --icons-dir=$HOME/.asciidoc/themes/default/icons -f javaeeworkshop.conf javaeeworkshop.asciidoc 12 | // 13 | JBoss Java EE 6 Workshop 14 | ======================== 15 | Dan Allen 16 | v1.2.0, May 30, 2012 : Drop Express from OpenShift Express, local AS 7 deployment 17 | :Author Initials: DJA 18 | :description: Creating, testing and deploying an application using the JBoss Java EE tools and runtimes. 19 | :brand: JBoss 20 | :doctype: book 21 | :toc: 22 | :backend: bootstrap-docs 23 | :link-assets: 24 | :openshift: http://openshift.com 25 | :openshiftdashboard: https://openshift.redhat.com/app/console/applications 26 | :installingclienttools: https://redhat.com/openshift/community/kb/kb-e1000/installing-openshift-express-client-tools-on-non-rpm-based-systems 27 | :jbossforge: http://jboss.org/forge 28 | :jbossforgedownload: link:$$https://repository.jboss.org/nexus/index.html#nexus-search;gav~org.jboss.forge~forge-distribution~~~~kw,versionexpand$$ 29 | :jbossas7download: http://jboss.org/as7 30 | 31 | [role="lead"] 32 | This tutorial steps through creating, testing and deploying an application using the JBoss Java EE tools and runtimes. You can show up with nothing but Java and a passion to learn. By the end, you'll have a full application running in the cloud provided by OpenShift. 33 | 34 | Here's the development stack we'll be using: 35 | 36 | * OpenShift 37 | * git 38 | * JBoss Forge 39 | * JBoss Tools 40 | * JBoss AS 7 41 | * Arquillian 42 | 43 | Hang on, cause it's going to move 'fast!' 44 | 45 | = OpenShift Introduction 46 | 47 | == Why Java EE on OpenShift? 48 | 49 | You've probably been hearing a lot about cloud (``to the cloud!''). But, if you're like me, you just haven't been that motivated to try it, or it just seemed like too much effort. After all, taking a Java EE application to the cloud typically meant: 50 | 51 | * Breaking out a credit card (I hate being restricted from exploring) 52 | * Implementing tons of hacks to get a Java EE application running on a cloud provider 53 | * Not knowing how Java EE development is even compatible with cloud 54 | * Lack of crystal clear documentation and examples 55 | 56 | 'All that has changed'. I assure you, you're in for a pleasant surprise. 57 | 58 | {openshift}[OpenShift] provides a free, cloud-based application platform for Java, Perl, PHP, Python, and Ruby applications using a shared-hosting model. Exploring the cloud has never been simpler. You can deploy a Java EE compliant application without requiring any hacks or workarounds. Best of all, take as much time as you like, because it's all 'free'. (Oh, and you can show off your applications to your friends, or even run applications for your own purposes). 59 | 60 | It's time to get going! 61 | 62 | == Creating an OpenShift account 63 | 64 | Creating an OpenShift account is very straightforward. 65 | 66 | . Go to the {openshift}[OpenShift homepage] 67 | . Click on the "Signup and try it" button to open the registration form 68 | . Enter a valid email address, a password (twice) and pass the Captcha (I know, it's tough) 69 | . Check your email and follow instructions in the welcome email 70 | 71 | Welcome to OpenShift! 72 | 73 | == Installing Ruby-based OpenShift client tools 74 | 75 | To interact with the OpenShift Platform-as-a-Service (PaaS), you'll need one of the available OpenShift client tools installed. We'll be using the Ruby-based commandline tool, rhc, in this tutorial. 76 | 77 | To install the Ruby-based OpenShift client tools, you first need to install git and Ruby Gems. 78 | 79 | On a Debian-based Linux distribution, it's as easy as: 80 | 81 | [listing] 82 | $> sudo apt-get install ruby rubygems 83 | 84 | On a rpm-based Linux distribution, it's as easy as: 85 | 86 | [listing] 87 | $> sudo yum install ruby rubygems 88 | 89 | Next, install the Red Hat Cloud (rhc) gem: 90 | 91 | [listing] 92 | $> sudo gem install rhc 93 | 94 | This will add a set of commands to your shell prefixed with rhc- (e.g., rhc-create-domain). 95 | 96 | [name="info"] 97 | TIP: On some distributions the gem installation directory is not automatically added to the path. Find the location of your gems with gem environment and add it to you system's PATH environment variable. 98 | 99 | For more information see {installingclienttools}[Installing OpenShift client tools on Linux, Windows and Mac OSX]. 100 | 101 | == Creating a domain for your applications 102 | 103 | Before actually deploying an app to OpenShift, you first need to create a domain. A domain hosts one or more applications. The name of the domain will be used in the URL of your apps according to the following scheme: 104 | 105 | [role="text-info"] 106 | [icon-hand-right]#{empty}# +++http://[application name]-[domain name].rhcloud.com+++ 107 | 108 | Create a domain using the following command: 109 | 110 | [listing] 111 | $> rhc-create-domain -n [domain name] -l [openshift email] 112 | 113 | NOTE: Use the same email address you used to register for your OpenShift account and enter your OpenShift password when prompted. 114 | 115 | [name="info"] 116 | TIP: All OpenShift client tools prompt you for your OpenShift password (unless you supply it using the -p command flag) 117 | 118 | The command will then create a pair of private and public keys as 'libra_id_rsa' and 'libra_id_rsa.pub' in your '$HOME/.ssh/' directory. It will ask you for a password to access the private key. *Don't forget it!* 119 | 120 | [name="info"] 121 | TIP: If you want to use an existing ssh key file, you can specify it explicitly in the '$HOME/.openshift/express.conf' file. You'll also discover that your email is cached in this file, which means you don't have to specify it in subsequent commands. 122 | 123 | You can see a summary of your domain using the following command: 124 | 125 | [listing] 126 | $> rhc-domain-info 127 | 128 | You can also go to the {openshiftdashboard}[dashboard] to see your newly minted domain. You now have your own, free cloud. Woot! 129 | 130 | == Creating your first Java EE application on OpenShift 131 | 132 | We now want to create a new application that uses the JBoss AS 7 cartridge. This allows us to deploy Java EE-compliant applications to OpenShift. 133 | 134 | We'll assume you'll be developing the application in the following folder: '~/demos/apps/sellmore' 135 | 136 | Next, use the following command to create a slot in your OpenShift domain in which to run the application and the location where the local project should be created: 137 | 138 | [listing] 139 | $> rhc-create-app -a sellmore -t jbossas-7 -r ~/demos/apps/sellmore 140 | 141 | You'll be prompted for your ssh key password that you created in the previous step. 142 | 143 | Behind the scenes, OpenShift has created a git repository for you and cloned it locally. That's how you're going to "push" your application to the cloud. The cloned repository contains a Maven-based project structure (which you don't have to use): 144 | 145 | .Project layout 146 | ---- 147 | sellmore 148 | |- .git/ 149 | |- .openshift/ 150 | |- deployments/ 151 | |- src/ 152 | |- .gitignore 153 | |- pom.xml 154 | `- README 155 | ---- 156 | 157 | The 'README' describes all the special directories that pertain to OpenShift. 158 | 159 | The OpenShift setup leaves behind a sample application which is going to get in our way later on. So first, let's clear the path: 160 | 161 | ---- 162 | $> cd sellmore 163 | $> git rm -r pom.xml src 164 | $> git commit -m 'clear a path' 165 | $> cd .. 166 | ---- 167 | 168 | If you're working with another origin git repository (such as on github), we recommend renaming the OpenShift repository from origin to openshift: 169 | 170 | ---- 171 | $> cd sellmore 172 | $> git remote rename origin openshift 173 | $> cd .. 174 | ---- 175 | 176 | That separates the concern of managing your source code repository from deploying files to OpenShift. 177 | 178 | You can see a summary of your application configuration using the following command: 179 | 180 | [listing] 181 | $> rhc-domain-info 182 | 183 | You can also go to the {openshiftdashboard}[dashboard] to see your application slot. If you click on the URL, you'll see that a sample application is already running in the cloud. We'll be replacing that soon enough. 184 | 185 | If, for whatever reason, you need to delete your application, use this command: 186 | 187 | [listing] 188 | $> rhc-ctl-app -a sellmore -c destroy 189 | 190 | You'll also want to delete your local .git repository (unless you mean to save it). 191 | 192 | But now's not the time to delete, it's time to create! 193 | 194 | = JBoss Forge Introduction 195 | 196 | == Why JBoss Forge? 197 | 198 | Because starting a project is hard. It doesn't just take time, it takes mental energy. We want to save that energy for creating useful things. Trust me, even if copying and pasting 20 lines of build XML seems easy, somewhere along the line your going to find yourself roasting your brain. Let's toss the complexity over the wall and let a tool like Forge deal with it. 199 | 200 | Forge is your monkey, or 10,000 of them. 201 | 202 | == Setting up Forge 203 | 204 | To create our application, we're going to use {jbossforge}[JBoss Forge]. Forge is a plugin-based framework for rapid development of standards-based Java applications. 205 | 206 | Begin by grabbing Forge from the {jbossforgedownload}[download area]. Then, unpack the distribution: 207 | 208 | [listing] 209 | $> unzip forge-distribution-1.0.0.Beta5.zip 210 | 211 | Move the extracted folder to the location of your choice and change into that directory in your console: 212 | 213 | [listing] 214 | $> cd ~/opt/forge 215 | 216 | Finally, run Forge: 217 | 218 | [listing] 219 | $> ./bin/forge 220 | 221 | To be sure everything is working okay, run the about command in the Forge shell: 222 | 223 | ---- 224 | $forge> about 225 | 226 | _____ 227 | | ___|__ _ __ __ _ ___ 228 | | |_ / _ \| `__/ _` |/ _ \ \\ 229 | | _| (_) | | | (_| | __/ // 230 | |_| \___/|_| \__, |\___| 231 | |___/ 232 | 233 | JBoss Forge, version [ 1.0.2.Final ] - JBoss, by Red Hat, Inc. [ http://jboss.org/forge ] 234 | ---- 235 | 236 | NOTE: Any command in this document prefixed with `$forge>` is intended to be run in the Forge shell. 237 | 238 | Things look good. We're ready to create an application. 239 | 240 | == Generating an application with Forge 241 | 242 | Forge allows you to create a Java EE application from scratch. We're going to generate a point of sale application step-by-step in the Forge shell using the commands below (make sure Forge is running): 243 | 244 | .Forge commands to create a Java EE web project 245 | ---- 246 | new-project; <1> 247 | 248 | scaffold setup --scaffoldType faces; <2> 249 | persistence setup --provider HIBERNATE --container JBOSS_AS7; <3> 250 | validation setup --provider HIBERNATE_VALIDATOR; <4> 251 | 252 | entity --named Customer --package ~.domain; <5> 253 | field string --named firstName; 254 | field string --named lastName; 255 | field temporal --type DATE --named birthDate; 256 | entity --named Item; 257 | field string --named name; 258 | field number --named price --type java.lang.Double; 259 | field int --named stock; 260 | cd ..; 261 | 262 | entity --named ProductOrder; <6> 263 | field manyToOne --named customer --fieldType ~.domain.Customer.java --inverseFieldName orders; 264 | cd ../Customer.java; 265 | entity --named Profile; 266 | field string --named bio; 267 | field string --named preferredName; 268 | field string --named notes; 269 | entity --named Address; 270 | field string --named street; 271 | field string --named city; 272 | entity --named ZipCode; 273 | field int --named code; 274 | cd ../Address.java; 275 | 276 | field manyToOne --named zip --fieldType ~.domain.ZipCode.java; <7> 277 | cd ..; 278 | cd Customer.java; 279 | field manyToMany --named addresses --fieldType ~.domain.Address.java; 280 | cd ..; 281 | cd Address.java; 282 | cd ../Customer.java; 283 | field oneToOne --named profile --fieldType ~.domain.Profile.java; 284 | cd ..; 285 | cd ProductOrder.java; 286 | field manyToMany --named items --fieldType ~.domain.Item.java; 287 | cd ..; 288 | cd ProductOrder.java; 289 | field manyToOne --named shippingAddress --fieldType ~.domain.Address.java; 290 | cd ..; 291 | 292 | scaffold from-entity ~.domain.* --scaffoldType faces --overwrite; <8> 293 | cd ~~; 294 | 295 | rest setup; <9> 296 | rest endpoint-from-entity ~.domain.*; <10> 297 | 298 | build; <11> 299 | 300 | cd ~~; <12> 301 | echo "Project Info:"; project; 302 | ---- 303 | 304 | <1> Create a new project in the current directory 305 | <2> Turn our Java project into a Web project with abbr:JSF[JavaServer Faces], abbr:CDI[Contexts & Dependency Injection], abbr:EJB[Enterprise JavaBeans] 306 | <3> Setup abbr:JPA[Java Persistence API] 307 | <4> Setup Bean Validation 308 | <5> Create some JPA entities on which to base our application 309 | <6> Create more entities, also add a relationship between Customer and their Orders 310 | <7> Add more relationships between our entities 311 | <8> Generate the UI for all of our entities at once 312 | <9> Setup JAX-RS 313 | <10> Generate abbr:CRUD[Create, Read, Update & Delete] endpoints 314 | <11> Build the project 315 | <12> Return to the project root directory and leave it in your hands 316 | 317 | You've got a complete application, ready to deploy! 318 | 319 | But wait! That sure seemed like a lot of typing. What's really great about Forge is that it's fine-grained enough to perform simple operations, but it can also compose those operations inside plugins or scripts! 320 | 321 | You can take all of those commands and put them into a script ending in .fsh and run the script from the Forge shell. 322 | 323 | If you're going to try this approach, you should first wipe the slate clean. 324 | 325 | [listing] 326 | $> rm -Rf src/ pom.xml 327 | 328 | Then, copy all the Forge commands listed above into the file generate.fsh at the root of the project. 329 | 330 | You may also want to wrap the following two lines around the contents so that the commands run without pausing: 331 | 332 | .Use as first line 333 | ---- 334 | set ACCEPT_DEFAULTS true; <1> 335 | ---- 336 | 337 | <1> Disables interactive commands 338 | 339 | .Use as last line 340 | ---- 341 | set ACCEPT_DEFAULTS false; <1> 342 | ---- 343 | 344 | <1> Reenables interactive commands 345 | 346 | You can now build the application using a single command: 347 | 348 | [listing] 349 | $forge> run generate.fsh 350 | 351 | Alternatively, you can also run a prepared version of this script directly off the web 352 | 353 | [listing] 354 | $forge> run-url https://raw.github.com/gist/1666087/1cd6032090f66f6aa18b7bd2ce55c569be8ac454/generate.fsh 355 | 356 | That's more like it! Now, let's get the application running! 357 | 358 | = Application Deployment 359 | 360 | == Deploying the application to a local JBoss AS 7 instance 361 | 362 | Before we get all cloud happy, it's a good idea to make sure the application runs on our own machine. We want to make sure that we rule out any problems with the application before adding the cloud into the mix. 363 | 364 | If you don't have JBoss AS 7 yet, head on over to the {jbossas7download}[JBoss AS 7 download page] and grab the latest 7.1 version. When the download finishes, unpack the distribution 365 | 366 | [listing] 367 | $> unzip jboss-as-7.1.1.Final.zip 368 | 369 | Move the extracted folder to the location of your choice (we'll assume it's $HOME/opt/jboss-as) and change into that directory in your console: 370 | 371 | [listing] 372 | $> cd $HOME/opt/jboss-as 373 | 374 | Finally, run JBoss AS in standalone (single server) mode: 375 | 376 | [listing] 377 | $> ./bin/standalone.sh 378 | 379 | You shouldn't have to wait long to see: 380 | 381 | ---- 382 | JBoss AS 7.1.1.Final "Brontes" started in 1933ms - Started 133 of 208 services... 383 | ---- 384 | 385 | Now that's a speedy app server! 386 | 387 | Let's head back to Forge so we can give this eager server something to run. We'll start by adding the Maven plugin for JBoss AS 7 to the project (yes, there is a decent Maven plugin finally): 388 | 389 | [listing] 390 | $forge> setup as7 391 | 392 | If you don't have the as7 command yet, you can install it using this command, then go back and do the setup: 393 | 394 | [listing] 395 | $forge> forge install-plugin as7 396 | 397 | Okay, build the application and send it to JBoss AS: 398 | 399 | ---- 400 | $forge> build 401 | $forge> as7 deploy 402 | ---- 403 | 404 | The first deployment is always the slowest, so give it a few seconds. Then, have a look around the application you generated: 405 | 406 | [role="text-info"] 407 | [icon-hand-right]#{empty}# +++http://localhost:8080/sellmore+++ 408 | 409 | If everything looks good, then the application is cleared for take off. Let's now do the same deployment, but this time on OpenShift. 410 | 411 | == Deploying your first Java EE application to OpenShift 412 | 413 | There are two ways to deploy an application to OpenShift: 414 | 415 | . *Deploy the source* 416 | + 417 | You can commit your source files and push them to the remote server using git, at which point the application will be built and deployed on the remote host. Alternatively, you can use a Jenkins slave to handle the build and deploy steps on the server. More on that later. 418 | + 419 | . *Deploy a package* 420 | + 421 | You can copy a pre-built war into 'deployments/' (with the corresponding .dodeploy file for an exploded war) and use git to commit and push the file(s) to the remote server for deployment 422 | 423 | In the first scenarios, you edit the files locally and let OpenShift build the app using Maven and deploy it to JBoss AS 7 once you push the changes using git. In the second scenario, you build the application locally and just push the final package to OpenShift, which it will deploy to JBoss AS 7. 424 | 425 | We're going to take the source route. 426 | 427 | First, add the following profile to the end of the pom.xml file (inside the root element): 428 | 429 | .pom.xml (fragment) 430 | ---- 431 | 432 | 433 | 434 | 435 | 436 | 437 | openshift 438 | 439 | sellmore 440 | 441 | 442 | maven-war-plugin 443 | 2.1.1 444 | 445 | deployments 446 | ROOT 447 | 448 | 449 | 450 | 451 | 452 | 453 | ---- 454 | 455 | IMPORTANT: If you forget this profile, then the application will build on the OpenShift PaaS, but it will not be deployed to JBoss AS 7. 456 | 457 | [name="warning"] 458 | CAUTION: You may want to add the Eclipse project files to '.gitignore' so that they aren't committed. 459 | 460 | Next, we'll add all the new files to git, commit them and push them to the server. You can perform these operations directly inside the Forge shell: 461 | 462 | ---- 463 | $forge> git add pom.xml src 464 | $forge> git commit -a -m 'new project' 465 | $forge> git push openshift master 466 | ---- 467 | 468 | You'll see the OpenShift begin the build lifecycle on the server, which includes executing Maven and downloading the (nearby) internet. The console output you're seeing is from the remote server being echoed into your local console. 469 | 470 | == OpenShift Build Lifecycle 471 | 472 | The OpenShift build lifecycle comprises four steps: 473 | 474 | . *Pre-Receive* 475 | + 476 | Occurs when you run a git push command, but before the push is fully committed. 477 | + 478 | . *Build* 479 | + 480 | Builds your application, downloads required dependencies, executes the '.openshift/action_hooks/build' script and prepares everything for deployment. 481 | + 482 | . *Deploy* 483 | + 484 | Performs any required tasks necessary to prepare the application for starting, including running the '.openshift/action_hooks/deploy' script. This step occurs immediately before the application is issued a start command. 485 | + 486 | . *Post-Deploy* 487 | + 488 | Allows for interaction with the running application, including running the '.openshift/action_hooks/post_deploy' script. This step occurs immediately after the application is started. 489 | 490 | When the build is done, you'll notice that the application is deployed to JBoss AS 7. You can now visit the application URL again to see the application running. 491 | 492 | [role="text-info"] 493 | [icon-hand-right]#{empty}# +++http://sellmore-[domain name].rhcloud.com+++ 494 | 495 | You should see the Forge welcome page and a list of items in the sidebar you can create, read, update and delete (CRUD). 496 | 497 | If you want to push out a new change, simply update a file, then use git to commit and push again: 498 | 499 | ---- 500 | $forge> git commit -a -m 'first change' 501 | $forge> git push openshift master 502 | ---- 503 | 504 | The OpenShift build lifecycle will kick off again. Shortly after it completes, the change will be visible in the application. 505 | 506 | = Application Management 507 | 508 | == Managing OpenShift applications from a shell environment 509 | 510 | OpenShift isn't just a black box (black cloud?), it's Linux and it's open! That means you can shell into your cloud just as you would any (decent) hosting environment. 511 | 512 | So what's the login? It's embedded there in the git repository URL. Let's find it. 513 | 514 | [listing] 515 | $> git remote show -n openshift 516 | 517 | You can also get the same information using: 518 | 519 | [listing] 520 | $> rhc-domain-info -a 521 | 522 | You are looking for the ssh username and host in the form `username@hostname`. Once you've got that, just pass it to ssh and the authentication will be handled by the ssh key you setup earlier. Here's the syntax: 523 | 524 | [listing] 525 | $> ssh [UUID]@[application name]-[domain name].rhcloud.com 526 | 527 | There's a lot of power in that shell environment. You can type help to get a list of speciality commands (such as starting, stopping or restarting your app), or use just about any Linux shell command you know. Be sure to pay attention to what you're typing, though rest assured that the box is running on abbr:RHEL[Red Hat Enterprise Linux] secured with SELinux. 528 | 529 | == Viewing the log files 530 | 531 | There are two ways to view (tail) the log files of your application. You can use the client tool: 532 | 533 | [listing] 534 | $> rhc-tail-files -a sellmore 535 | 536 | Or you can shell into the server and use the built-in tail command: 537 | 538 | [listing] 539 | $> tail_all 540 | 541 | You can also use the regular tail command in the remote shell environment. 542 | 543 | == Restarting or stopping your application 544 | 545 | You can control your application directly without pushing files through git. One way is to use the client tool from your location machine: 546 | 547 | [listing] 548 | $> rhc-ctl-app -c restart 549 | 550 | You can also shell into your domain and execute a command using one of the special commands provided: 551 | 552 | [listing] 553 | $> ctl_app restart 554 | 555 | In addition to restart, you can use the commands start, stop, etc. 556 | 557 | = Persistence Storage 558 | 559 | == Preserving the database between restarts 560 | 561 | You may have noticed that each time we restart the application, the data gets lost. There are two ways to resolve this: 562 | 563 | . Update tables rather that dropping and recreating them on deployment 564 | . Save the data to a safe location on disk 565 | 566 | The first setting is a feature of Hibernate (or alternate JPA provider) and is changed using the following property in 'src/main/resources/META-INF/persistence.xml': 567 | 568 | .src/main/resources/META-INF/persistence.xml (fragment) 569 | [listing] 570 | 571 | 572 | The second feature depends on the database you are using. If you are using the provided H2 database, you'll likely want to change the configuration in '.openshift/config/standalone.xml' to use the OpenShift data directory: 573 | 574 | ..openshift/config/standalone.xml (fragment) 575 | [listing] 576 | jdbc:h2:${OPENSHIFT_DATA_DIR}/test;DB_CLOSE_DELAY=-1 577 | 578 | The other approach is just to use a regular client-server database (e.g., MySQL or PostgreSQL), which we'll do later. 579 | 580 | == Persisting data to a MySQL database 581 | 582 | OpenShift provides us with several add-on services (cartridges) we can use. To see the list of available cartridges, issue the following command: 583 | 584 | ---- 585 | $> rhc-ctl-app -a sellmore -L 586 | 587 | List of supported embedded cartridges: 588 | 589 | postgresql-8.4, metrics-0.1, mysql-5.1, jenkins-client-1.4, 590 | 10gen-mms-agent-0.1, phpmyadmin-3.4, rockmongo-1.1, mongodb-2.0 591 | ---- 592 | 593 | Oh goody! Lots of options :) 594 | 595 | Let's install mysql-5.1 cartridge: 596 | 597 | ---- 598 | $> rhc-ctl-app -a sellmore -e add-mysql-5.1 599 | 600 | Mysql 5.1 database added. Please make note of these credentials: 601 | 602 | Root User: admin 603 | Root Password: xxxxx 604 | Database Name: sellmore 605 | 606 | Connection URL: mysql://127.1.47.1:3306/ 607 | 608 | You can manage your new Mysql database by also embedding phpmyadmin-3.4. 609 | ---- 610 | 611 | NOTE: The name of the database is the same as the name of the application. 612 | 613 | OpenShift is telling us that the phpmyadmin cartridge is also available, so we'll add it as well. 614 | 615 | ---- 616 | $> rhc-ctl-app -a sellmore -e add-phpmyadmin-3.4 617 | 618 | phpMyAdmin 3.4 added. Please make note of these credentials: 619 | 620 | Root User: admin 621 | Root Password: xxxxx 622 | 623 | URL: https://sellmore-[domain name].rhcloud.com/phpmyadmin/ 624 | ---- 625 | 626 | Open a browser and go to the URL shown, then login as admin with the password reported by the previous command. 627 | 628 | [name="warning"] 629 | CAUTION: It's a good idea to create another user with limited privileges (select, insert, update, delete, create, index and drop) on the same database. 630 | 631 | You can also shell into the domain and control MySQL using the MySQL client. You'll need to connect using the hostname provided when you added the cartridge since it's running on a different interface (not through a local socket). 632 | 633 | [listing] 634 | $> mysql -u $OPENSHIFT_DB_USERNAME -p$OPENSHIFT_DB_PASSWORD -h $OPENSHIFT_DB_HOST 635 | 636 | Now we'll configure our application to use OpenShift's MySQL database when running in the cloud. 637 | 638 | == Switching the application datastore to MySQL 639 | 640 | The JBoss AS 7 cartridge comes configured out of the box with datasources for H2 (embedded), MySQL and PostgreSQL. The datasources for MySQL and PostgreSQL are enabled automatically when the respective cartridges are added. You can find this configuration in '.openshift/config/standalone.xml'. 641 | 642 | Here's the datasource name that cooresponds to the MySQL connection pool: 643 | 644 | ==== 645 | +++java:jboss/datasources/MysqlDS+++ 646 | ==== 647 | 648 | The connection URL uses values that are automatically populated via environment variables maintained by OpenShift. 649 | 650 | ==== 651 | +++jdbc:mysql://${OPENSHIFT_DB_HOST}:${OPENSHIFT_DB_PORT}/${OPENSHIFT_APP_NAME}+++ 652 | ==== 653 | 654 | All you need to do is open up the 'src/main/resources/META-INF/persistence.xml' and set the JTA datasource: 655 | 656 | .src/main/resources/META-INF/persistence.xml (fragment) 657 | [listing] 658 | java:jboss/datasources/MysqlDS 659 | 660 | If you want to use PostgreSQL, follow the steps above for setting up MySQL, but replace it with the PostgreSQL cartridge (postgresql-8.4). Then, you'll use this datasource in your persistence.xml: 661 | 662 | .src/main/resources/META-INF/persistence.xml (fragment) 663 | [listing] 664 | java:jboss/datasources/PostgreSQLDS 665 | 666 | You can connect to the PostgreSQL prompt on the domain using this command: 667 | 668 | [listing] 669 | $> psql -h $OPENSHIFT_DB_HOST -U $OPENSHIFT_DB_USERNAME -d $OPENSHIFT_APP_NAME 670 | 671 | = Advanced Deployment 672 | 673 | == Building with Jenkins 674 | 675 | Jenkins is a continous integration (CI) server. When installed in an OpenShift environment, Jenkins takes over as the build manager for your application. You now have two options for how to build and deploy on OpenShift: 676 | 677 | Building without Jenkins:: 678 | Uses your application space as part of the build and test process. Because of this, the application is stopped to free memory while the build is running. 679 | 680 | Building with Jenkins:: 681 | Uses dedicated application space that can be larger then the application runtime space. Because the build happens in its own dedicated jail, the running application is not shutdown or changed in any way until after the build is a success. 682 | 683 | Here are the benefits to using Jenkins: 684 | 685 | * Archived build information 686 | * No application downtime during the build process 687 | * Failed builds do not get deployed (leaving the previous working version in place). 688 | * Jenkins builders have additional resources like memory and storage 689 | * A large community of Jenkins plugins (300+) 690 | 691 | To enable Jenkins to use with an existing application, you first create a dedicated jenkins application: 692 | 693 | [listing] 694 | $> rhc-create-app -a builds -t jenkins-1.4 695 | 696 | Then you add the Jenkins client to your own application: 697 | 698 | [listing] 699 | $> rhc-ctl-app -a sellmore -e add-jenkins-client-1.4 700 | 701 | Make a note of the admin account password for Jenkins and point your browser at the following URL: 702 | 703 | [role="text-info"] 704 | [icon-hand-right]#{empty}# +++http://builds-[domain name].rhcloud.com+++ 705 | 706 | Once you are there, you can click "log in" in the top right of the Jenkins window to sign in and start tweaking the Jenkins configuration. 707 | 708 | Now you simply have to do a git push to remote branch and Jenkins will take over building and deploying your application. 709 | 710 | The pre-Jenkins way of doing this was to fire off a command line build and dump the output to the screen. You'll notice that this output is replaced with a URL where you can view the output and status of the build. 711 | 712 | = Integration Testing 713 | 714 | == Writing real cloud tests with Arquillian 715 | 716 | Bring your tests to the runtime instead of managing the runtime from your test. Isn't the cloud one of those runtimes? It sure is! 717 | 718 | Let's use Arquillian to write some tests that run on a local JBoss AS instance. Later, we'll get them running on OpenShift. 719 | 720 | Setting up Arquillian requires thought. Let's put those 10,000 monkeys to work again. Open up Forge and see if it can find a plugin to help us get started with Arquillian. 721 | 722 | ---- 723 | $forge> forge find-plugin arquillian 724 | ---- 725 | 726 | Sure enough, there it is! 727 | 728 | ---- 729 | - arquillian (org.arquillian.forge:arquillian-plugin:::1.0.0-SNAPSHOT) 730 | Author: Paul Bakker 731 | Website: http://www.jboss.org/arquillian 732 | Location: git://github.com/forge/plugin-arquillian.git 733 | Tags: arquillian, jboss, testing, junit, testng, integration testing, tests, CDI, java ee 734 | Description: Integration Testing Framework 735 | ---- 736 | 737 | Let's snag it. 738 | 739 | ---- 740 | $forge> forge install-plugin arquillian 741 | ---- 742 | 743 | That will clone the plugin source, build it and install it into the Forge shell. Once it's finished, we can get straight to the Arquillian setup. 744 | 745 | We'll first create a profile for testing on a running JBoss AS 7 instance on our own machine (here, the term *remote* refers to deployment protocol, not where the server is running). 746 | 747 | ---- 748 | $forge> setup arquillian --container JBOSS_AS_REMOTE_7.X 749 | ---- 750 | 751 | [NOTE] 752 | ==== 753 | At the time of writing, the plugin puts the Arquillian abbr:BOM[Bill of Materials] dependency in the wrong section. Move it into the dependencyManagement section below the others: 754 | 755 | .pom.xml 756 | ---- 757 | 758 | 759 | 760 | org.jboss.arquillian 761 | arquillian-bom 762 | 1.0.0.Final 763 | pom 764 | import 765 | 766 | 767 | 768 | ---- 769 | 770 | You can also remove the version from the `arquillian-junit-container` dependency. Both of these problems will be fixed in the next release of the plugin. 771 | ==== 772 | 773 | We can also use the Forge Arquillian plugin to create tests for us. Let's create an integration test for one of the services created earlier: 774 | 775 | ---- 776 | $forge> arquillian create-test --class com.acme.sellmore.rest.ItemEndpoint --enableJPA 777 | ---- 778 | 779 | This test is going to read and write to a database. You probably don't want to mix test data with application data, so first copy the JPA descriptor (persistence.xml) to the test classpath and prefix the file with test- so it doesn't get mixed up: 780 | 781 | ---- 782 | $forge> cd ~~ 783 | $forge> cp src/main/resources/META-INF/persistence.xml src/test/resources/test-persistence.xml 784 | ---- 785 | 786 | Make sure the 'test-persistence.xml' uses the ExampleDS datasource (or whatever you want to use for tests). 787 | 788 | Next, open up the test in your editor so we can work it into a useful test. Begin by updating the ShrinkWrap archive builder to snag the JPA descriptor from the test classpath (instead of the production one): 789 | 790 | .src/test/java/com/acme/sellmore/rest/ItemEndpointTest.java (fragment) 791 | ---- 792 | .addAsManifestResource("test-persistence.xml", "persistence.xml") 793 | ---- 794 | 795 | Assign the `@Test` method a meaninful name and replace the contents with logic to validate that an item can be created in one transaction and retrieved in another: 796 | 797 | .src/test/java/com/acme/sellmore/rest/ItemEndpointTest.java (fragment) 798 | ---- 799 | @Test 800 | public void should_insert_and_select_item() { 801 | Item item = new Item(); 802 | item.setName("Widget"); 803 | item.setPrice(5.0); 804 | item.setStock(100); 805 | item = itemendpoint.create(item); 806 | Long id = item.getId(); 807 | Assert.assertNotNull(id); 808 | Assert.assertTrue(id > 0); 809 | Assert.assertEquals(item.getVersion(), 0); 810 | 811 | item = itemendpoint.findById(id); 812 | Assert.assertNotNull(item); 813 | Assert.assertEquals("Widget", item.getName()); 814 | } 815 | ---- 816 | 817 | The test is ready to run. First, start JBoss AS 7. 818 | 819 | ---- 820 | $> cd $JBOSS_HOME 821 | $> ./bin/standalone.sh 822 | ---- 823 | 824 | Run the Arquillian test on this instance by activating the cooresponding profile when running the Maven test command: 825 | 826 | ---- 827 | $forge> test --profile JBOSS_AS_REMOTE_7.X 828 | ---- 829 | 830 | If things go we'll, the tests will pass and you'll see some Hibernate queries in the JBoss AS console. ``Green bar!'' 831 | 832 | The previous test runs inside the container. Let's write another test that acts as a client to the REST endpoint. To keep effort to a minimum, we'll use the http://hc.apache.org/httpcomponents-client-ga[Apache HttpComponents HttpClient] library to invoke the HTTP endpoints. We can get Forge to add it to our build: 833 | 834 | ---- 835 | $forge> project add-dependency org.apache.httpcomponents:httpclient:4.1.2:test 836 | ---- 837 | 838 | === Let's REST! 839 | 840 | Sigh. There's no better way to do this at the moment, so copy the previous test and rename it to `ItemEndpointClientTest` (rename both the file and the class name). Then, replace the class definition with the following source: 841 | 842 | .src/test/java/com/acme/sellmore/rest/ItemEndpointClientTest.java 843 | ---- 844 | @RunWith(Arquillian.class) 845 | public class ItemEndpointClientTest { 846 | @ArquillianResource 847 | private URL deploymentUrl; 848 | 849 | @Deployment(testable = false) 850 | public static WebArchive createDeployment() { 851 | return ShrinkWrap.create(WebArchive.class, "test.war") 852 | .addClasses(Item.class, ItemEndpoint.class) 853 | .addAsResource("META-INF/persistence.xml") 854 | .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") 855 | .setWebXML(new File("src/main/webapp/WEB-INF/web.xml")); 856 | } 857 | 858 | @Test 859 | public void should_post_update_and_get_item() { 860 | DefaultHttpClient client = new DefaultHttpClient(); 861 | String itemResourceUrl = deploymentUrl + "rest/item"; 862 | 863 | String ITEM_XML = "%1$sWidget5.0%3$d%1$s"; 864 | 865 | // POST new item 866 | HttpPost post = new HttpPost(itemResourceUrl); 867 | post.setEntity(createXmlEntity(String.format(ITEM_XML, "", "", 99))); 868 | 869 | String result = execute(post, client); 870 | assertEquals(String.format(ITEM_XML, "1", "0", 99), result); 871 | 872 | // PUT update to item 1 873 | HttpPut put = new HttpPut(itemResourceUrl + "/1"); 874 | put.setEntity(createXmlEntity(String.format(ITEM_XML, "", "", 98))); 875 | 876 | execute(put, client); 877 | 878 | // GET item 1 879 | HttpGet get = new HttpGet(itemResourceUrl + "/1"); 880 | get.setHeader("Accepts", MediaType.APPLICATION_XML); 881 | 882 | result = execute(get, client); 883 | assertEquals(String.format(ITEM_XML, "1", "1", 98), result); 884 | 885 | client.getConnectionManager().shutdown(); 886 | } 887 | } 888 | ---- 889 | 890 | Also add these two private helper methods (to hide away some of the boilerplate code): 891 | 892 | .src/test/java/com/acme/sellmore/rest/ItemEndpointClientTest.java (fragment) 893 | ---- 894 | private HttpEntity createXmlEntity(final String xml) { 895 | ContentProducer cp = new ContentProducer() { 896 | public void writeTo(OutputStream outstream) throws IOException { 897 | Writer writer = new OutputStreamWriter(outstream, "UTF-8"); 898 | writer.write(xml); 899 | writer.flush(); 900 | } 901 | }; 902 | 903 | AbstractHttpEntity entity = new EntityTemplate(cp); 904 | entity.setContentType(MediaType.APPLICATION_XML); 905 | return entity; 906 | } 907 | 908 | private String execute(final HttpUriRequest request, final HttpClient client) { 909 | try { 910 | System.out.println(request.getMethod() + " " + request.getURI()); 911 | return client.execute(request, new BasicResponseHandler()) 912 | .replaceFirst("<\\?xml.*\\?>", "").trim(); 913 | } 914 | catch (Exception e) { 915 | e.printStackTrace(); 916 | Assert.fail(e.getMessage()); 917 | return null; 918 | } 919 | finally { 920 | request.abort(); 921 | } 922 | } 923 | ---- 924 | 925 | Let's see if these endpoints do what they claim to do. 926 | 927 | ---- 928 | $forge> test --profile JBOSS_AS_REMOTE_7.X 929 | ---- 930 | 931 | If you get a test failure, it may be because the type the endpoints are configured to consume is incorrect. Open the `ItemEndpoint` class and replace all instances of `@Consumes` with: 932 | 933 | .src/main/java/com/acme/sellmore/rest/ItemEndpoint.java 934 | [listing] 935 | @Consumes(MediaType.APPLICATION_XML) 936 | 937 | Run the tests again. With any luck, this time you'll be chanting ``Green bar!'' 938 | 939 | == Running the Arquillian tests on OpenShift 940 | 941 | Okay, now you can say it. "Let's take it to the cloud!" If they work there, they'll work anywhere :) 942 | 943 | It's up to you whether you want to run the tests on the same OpenShift application as the production application or whether you want to create a dedicated application. We'll assume you're going to create a dedicated application. Let's call it ike. 944 | 945 | [listing] 946 | $> rhc-create-app -t jbossas-7 -a ike 947 | 948 | You'll also need an Arquillian profile. The Forge plugin doesn't honor the OpenShift adapter yet, so you'll have splice this profile into the pom.xml by hand: 949 | 950 | .pom.xml (fragment) 951 | ---- 952 | 953 | OPENSHIFT_1.X 954 | 955 | 956 | org.jboss.arquillian.container 957 | arquillian-openshift-express 958 | 1.0.0.Beta1 959 | test 960 | 961 | 962 | 963 | ---- 964 | 965 | The Arquillian OpenShift adapter also uses git push to deploy the test archive. In order for that to work, it needs to know where it's pushing. In other words, it needs a little configuration. 966 | 967 | Seed an arquillian.xml descriptor using a known container (in this case, JBoss AS 7 remote): 968 | 969 | ---- 970 | $forge> arquillian configure-container --profile JBOSS_AS_REMOTE_7.X 971 | ---- 972 | 973 | Next, replace the container element with the following XML: 974 | 975 | .src/test/resources/arquillian.xml (fragment) 976 | ---- 977 | 978 | 979 | mojavelinux 980 | ike 981 | 02b0951a5ed54c98b54c41a7f2efbda8 982 | 983 | 984 | dan.j.allen@gmail.com 985 | 986 | 987 | ---- 988 | 989 | You can either put the passphrase for your SSH key in the descriptor or you can export the `SSH_PASSPHRASE` environment variable: 990 | 991 | [listing] 992 | $> export SSH_PASSPHRASE=[libra_id_rsa passphrase] 993 | 994 | To activate this container configuration, write the name of the qualifier to the 'arquillian.launch' file (alternatively, you can select the configuration using the `-Darquillian.launch` flag when you run Maven): 995 | 996 | [listing] 997 | $> echo "OPENSHIFT_1.X" > src/test/resources/arquillian.launch 998 | 999 | Are you ready to see some tests run in the cloud? 1000 | 1001 | ---- 1002 | $forge> test --profile OPENSHIFT_1.X 1003 | ---- 1004 | 1005 | You may want to tail the log files in another terminal to moniter the progress: 1006 | 1007 | [listing] 1008 | $> rhc-tail-files -a ike 1009 | 1010 | If you can't see the green bar, look above you :) 1011 | 1012 | = Hosting Configuration 1013 | 1014 | == Making your application a top-level domain 1015 | 1016 | Do we expect that you'll use *.rhcloud.com for all of your public websites? Of course not! That's where the alias feature comes in. 1017 | 1018 | You can create a domain alias for any OpenShift application using this command: 1019 | 1020 | [listing] 1021 | $> rhc-ctl-app -a sellmore -c add-alias --alias sellmore.com 1022 | 1023 | Next, you point the DNS for your domain name to the IP address of your OpenShift server (or you can cheat by putting it in '/etc/hosts'). 1024 | 1025 | Now you can access the application from the following URL: 1026 | 1027 | [role="text-info"] 1028 | [icon-hand-right]#{empty}# +++http://sellmore.com+++ 1029 | 1030 | Congratulations! You're OpenShift-hosted. 1031 | 1032 | = Summary 1033 | 1034 | In this tutorial, we learned how to: 1035 | 1036 | * Register an account at OpenShift 1037 | * Install the Ruby-based OpenShift client tools 1038 | * Create our own OpenShift domain 1039 | * Create an OpenShift application using the JBoss AS 7 cartridge on that domain 1040 | * Add a remote OpenShift git repo to our own repo to deploy an existing app 1041 | * Deploy a Java EE application to OpenShift 1042 | * Work with the in-memory database 1043 | * Configure H2 to persist the database file to the application's data directory 1044 | * Configure MySQL and phpmyadmin cartridges in OpenShift 1045 | * Configure our Java EE application to use the MySQL database running on the OpenShift domain 1046 | 1047 | = Resources 1048 | 1049 | * Git repository for this tutorial + 1050 | http://tinyurl.com/dcjbug-jboss-workshop 1051 | * OpenShift homepage + 1052 | {openshift} 1053 | * OpenShift dashboard + 1054 | {openshiftdashboard} 1055 | * OpenShift Documentation + 1056 | http://docs.redhat.com/docs/en-US/OpenShift/2.0/html/User_Guide/index.html 1057 | * OpenShift Knowledge Base + 1058 | https://redhat.com/openshift/community/kb 1059 | * Installing OpenShift client tools on Linux, Windows and Mac OSX + 1060 | {installingclienttools} 1061 | * Apps prepared for rapid deployment to OpenShift + 1062 | https://www.redhat.com/openshift/community/kb/kb-e1021-rundown-on-the-github-hosted-git-repositories-available-for-rapid-deployment 1063 | * OpenShift resources for JBoss AS + 1064 | https://www.redhat.com/openshift/community/page/jboss-resources 1065 | * JBoss Forge homepage: + 1066 | http://jboss.org/forge 1067 | * JBoss AS 7 homepage: + 1068 | http://jboss.org/as7 1069 | * JBoss Java EE quickstarts repository + 1070 | https://github.com/jbossas/quickstart 1071 | * Deploy a Play! application on OpenShift (provided a lot of details for this workshop) + 1072 | https://github.com/opensas/play-demo/wiki/Step-12.5---deploy-to-openshift 1073 | * How JBoss AS 7 was configured for OpenShift + 1074 | https://community.jboss.org/blogs/scott.stark/2011/08/10/jbossas7-configuration-in-openshift-express 1075 | * OpenShift resources for JBoss AS + 1076 | https://www.redhat.com/openshift/community/page/jboss-resources 1077 | * Apache HttpComponents HttpClient + 1078 | http://hc.apache.org/httpcomponents-client-ga 1079 | 1080 | //// 1081 | Create a parallel tutorial that takes a JBoss Tools-centric approach, as in: http://www.commonj.com/blogs/?p=677 and http://deors.wordpress.com/2011/12/13/red-hat-openshift/ 1082 | //// 1083 | --------------------------------------------------------------------------------