├── .gitattributes ├── .gitignore ├── CHANGES.md ├── LICENSE ├── NOTES.md ├── README.md ├── src ├── chrome.manifest ├── chrome │ ├── background.html │ ├── backgroundscript.js │ └── contentscript.js ├── common │ ├── CHANGES.md │ ├── default.css │ ├── highlightjs │ │ ├── highlight.js │ │ └── styles │ │ │ ├── arta.css │ │ │ ├── ascetic.css │ │ │ ├── brown_paper.css │ │ │ ├── dark.css │ │ │ ├── default.css │ │ │ ├── far.css │ │ │ ├── github.css │ │ │ ├── googlecode.css │ │ │ ├── idea.css │ │ │ ├── ir_black.css │ │ │ ├── magula.css │ │ │ ├── monokai.css │ │ │ ├── pojoaque.css │ │ │ ├── rainbow.css │ │ │ ├── school_book.css │ │ │ ├── solarized_dark.css │ │ │ ├── solarized_light.css │ │ │ ├── styles.json │ │ │ ├── sunburst.css │ │ │ ├── tomorrow-night-blue.css │ │ │ ├── tomorrow-night-bright.css │ │ │ ├── tomorrow-night-eighties.css │ │ │ ├── tomorrow-night.css │ │ │ ├── tomorrow.css │ │ │ ├── vs.css │ │ │ ├── xcode.css │ │ │ └── zenburn.css │ ├── images │ │ ├── gary-arthur-donate-1.png │ │ ├── icon128.png │ │ ├── icon16-bw.png │ │ ├── icon16.png │ │ ├── icon19.png │ │ ├── icon24-bw.png │ │ ├── icon24.png │ │ ├── icon32.png │ │ ├── icon38.png │ │ ├── icon48.png │ │ ├── icon512.png │ │ ├── markdown-bw.png │ │ └── markdown.png │ ├── jsHtmlToText.js │ ├── markdown-here.js │ ├── markdown-render.js │ ├── marked.js │ ├── options-iframe.html │ ├── options-iframe.js │ ├── options-store.js │ ├── options.html │ ├── options.js │ ├── test │ │ ├── chai.js │ │ ├── index.html │ │ ├── markdown-render-test.js │ │ ├── mocha.css │ │ ├── mocha.js │ │ ├── options-store-test.js │ │ ├── test-prep.js │ │ ├── test-run.js │ │ ├── underscore.js │ │ └── utils-test.js │ ├── utils.js │ └── vendor │ │ └── jquery-1.9.1.js ├── firefox │ ├── chrome │ │ ├── content │ │ │ ├── background-services-overlay.xul │ │ │ ├── background-services.js │ │ │ ├── ff-overlay.js │ │ │ ├── ff-overlay.xul │ │ │ ├── tb-overlay.xul │ │ │ └── zotero-overlay.xul │ │ ├── locale │ │ │ └── en-US │ │ │ │ ├── overlay.dtd │ │ │ │ └── overlay.properties │ │ └── skin │ │ │ ├── overlay.css │ │ │ └── toolbar.css │ └── defaults │ │ └── preferences │ │ └── prefs.js ├── install.rdf └── manifest.json ├── store-assets ├── amo-reviewer-notes.txt ├── description.txt ├── dos-equis-MDH.jpg ├── markdown-here-chrome-options.gimp.png ├── markdown-here-chrome-options.gimp.xcf ├── markdown-here-image1.425x265.png ├── markdown-here-image1.gimp.png ├── markdown-here-image1.gimp.xcf ├── markdown-here-image2.gimp.png ├── markdown-here-image2.gimp.xcf ├── markdown-here-promo-small.gimp.png ├── markdown-here-promo-small.gimp.xcf └── md-for-screenshot.md └── test └── index.html /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | Thumbs.db 4 | 5 | .gitignore 6 | *.xpi 7 | *.sublime-project 8 | *.sublime-workspace 9 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | See [src/common/CHANGES.md](src/common/CHANGES.md) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2013 Adam Pritchard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | > This file is a catch-all for ideas, problems, plans, and other miscellaneous notes. If something should instead be an issue, it should be made an [issue](https://github.com/adam-p/markdown-here/issues). 4 | > Be aware that changes to this file might live in another branch until a release is done. (You're probably looking at the `master` branch right now.) 5 | 6 | 7 | ## Other tools/libs not used, but to keep an eye on 8 | 9 | * Markdown-to-HTML: 10 | * [evilstreak / markdown-js](https://github.com/evilstreak/markdown-js) (There's currently a GFM dialect that seems almost finished. See [issue #41](https://github.com/evilstreak/markdown-js/issues/41).) 11 | * [Pagedown](https://code.google.com/p/pagedown/) 12 | * [isaacs / github-flavored-markdown](https://github.com/isaacs/github-flavored-markdown) (A Showdown derivative) 13 | * [Showdown](https://github.com/coreyti/showdown) 14 | 15 | * HTML-to-Markdown 16 | * [domchristie / to-markdown](https://github.com/domchristie/to-markdown) 17 | * [leeoniya / reMarked.js](https://github.com/leeoniya/reMarked.js) 18 | 19 | * [CSSUtilities](http://www.brothercake.com/site/resources/scripts/cssutilities/): "...is a JavaScript library that provides unique and indispensible methods for querying CSS style sheets!" 20 | * Could maybe be used for better make-styles-explicit. 21 | 22 | ## Miscellaneous 23 | 24 | * Update selection conversion screenshot to not be all about replies. 25 | 26 | * Try out MDH in other web-based rich-edit tools -- it'll surely work in some of them. 27 | * Redactor: http://imperavi.com/support/ This seems to work at least nominally. Test and document. 28 | * http://www.tinymce.com/ 29 | * http://hallojs.org/ 30 | * https://github.com/xing/wysihtml5 31 | * http://jhollingworth.github.com/bootstrap-wysihtml5/ 32 | 33 | * Test in Google Sites. I know it works to some degree, but need to fully test and document. 34 | 35 | * Automated test suite. 36 | * This isn't sexy, but important. Stuff has broken in the past because of browser changes, and it's inevitable that I'll make a change without sufficient testing everywhere. Regression tests are badly needed. (And would be good experience for me...) 37 | 38 | * Add a visual cue as to what action took place. Sometimes converts and reverts may be a little surprising if the user's selection is off. And sometimes their viewport won't show the entirety of what change occurred. 39 | 40 | * Internationalization. 41 | * [Mozilla statistics](https://addons.mozilla.org/en-US/firefox/addon/markdown-here/statistics/) suggest that about 35% of Markdown Here users are not anglophones. 42 | 43 | * If a selection conversion is *inside* a paragraph, then it shouldn't add a paragraph to the newly rendered text. That way the text flow won't be totally broken, and the user could actually render just part of a sentence or paragraph. 44 | 45 | * I've talked to at least one person who wants Markdown Here to be able unrender an email *after it's sent*. This would allow him to modify and re-send it, or allow his recipients to modify and send it. 46 | * This is a bit tricky, since all webmail clients (not Thunderbird) strip the `data-md-original` attribute from the `markdown-here-wrapper` element. 47 | * Idea: base64-encode the original MD, then set it as an inline-data `src` attribute for a very small inline image. The image won't display properly, of course, but the data will be intact and extractable. 48 | 49 | * Briefly highlight rendered and reverted blocks/ranges. 50 | * Probably use [CSS transitions](https://developer.mozilla.org/en/CSS/CSS_transitions). 51 | * I started this in the `transitions` branch, but wasn't thrilled with how it worked. Might come back to it, though... 52 | 53 | * Add telemetry/usage statistics gathering. Optional, of course. It'd be nice to know how people use MDH. 54 | * Hotkey vs. button vs. context menu 55 | * Custom CSS? 56 | * Custom hotkey? 57 | 58 | * Detect unrendered MD when sending and warn. 59 | * Really not sure how to detect "when sending". Hooking into the send button will be very dependent on the platform and webmail brand. But even doing it just for Gmail and maybe Thunderbird would be good. 60 | * https://twitter.com/geopet/status/294294916685778944 61 | 62 | 63 | ## Project stuff 64 | 65 | * Create a nicer info site than just the README (not that the README is *bad*, but...). Probably using `gh_pages`. 66 | 67 | 68 | ## New renderers and render targets 69 | 70 | ### Description 71 | 72 | Right now Markdown Here takes content from a rich-edit element, turns it into plaintext, renders it from Markdown into HTML, and then replaces the content of the rich-edit element with the HTML. This flow is baked into the code. 73 | 74 | There are at least two aspects of that flow that could be customizable. 75 | 76 | The first is the source markup language, which is currently Github-flavored Markdown. There are many other excellent choices: Textile, ReST, LaTeX, and so on. There are also other flavors of Markdown, such as MultiMarkdown. 77 | 78 | The second aspect is the "target", by which I mean the language that the source markup is rendered into as well as the element that the rendered value is put into. The target language is currently HTML, and the target element is the `innerHTML` of a rich-compose (`contenteditable`, `designmode`) element. But there have been requests (issues [36](https://github.com/adam-p/markdown-here/issues/36) and [43](https://github.com/adam-p/markdown-here/issues/43)) for those aspects to be customizable: users would like to be able to render to BBCode or HTML and have the rendered value inserted as plaintext into a `textarea`. 79 | 80 | ### Work 81 | 82 | It will require a consider refactor to implement this, to say the least. 83 | 84 | It'll also require some UI/UX thought and work to present this to the user in a coherent way. This includes options changes and in-app commands. 85 | 86 | There might need to be some CSS-specific work as well, kind of how there's different CSS for syntax highlighting. Some markup languages will be special-purpose (like math stuff) and will need special/specific styles. 87 | 88 | Maybe there should be separate projects for some of the structurally distinct components? Maybe other people could leverage, say, an email mutator extension where they just need to drop in the mutation code. 89 | 90 | ### Links 91 | 92 | * [MathJax](http://www.mathjax.org/) is a JS LaTeX and MathML renderer. 93 | * [Fountain](http://fountain.io/dingus) is a screenplay markup language. 94 | 95 | 96 | ## Advanced styling 97 | 98 | My original intention with Markdown Here was make structurally complex emails easy to write and look pretty good, like I was getting with my `README.md` files on Github. 99 | 100 | After seeing user [Casey Watts's examples](https://groups.google.com/d/topic/markdown-here/XlsuTCHR4zE/discussion) of how he uses (and styles) Markdown Here, I realized that there's another axis of functionality that MDH begins to address but could do much, much more towards: making *stylistically* complex emails easy to write, look great, and be consistent (over time and across people). 101 | 102 | You still just write Markdown. While writing you might have your final styling in mind, but you have to make no extra effort. 103 | 104 | As can be seen from Casey's examples, quite a lot of cool custom styling can be done -- and I don't think he has pushed it nearly as far as it can be pushed. There are limits, since this still has to be accepted as an email, but I think there's a lot of room to grow. 105 | 106 | There's also an opportunity for users to share styles and themes. Casey does a rudimentary form of this by [sharing his CSS via Github](https://github.com/caseywatts/markdown-here-css) with the people he works with, so they can all send consistent looking email, but there's no feature in MDH at the present that facilitates this -- users are forced to copy and paste back and forth. 107 | 108 | A small-ish point, but: There should also be the ability to fairly easily switch between themes (style sets). Users send email in different contexts and need them to look different ways. 109 | 110 | The styling could also go beyond straight CSS: 111 | * Supporting LESS/SASS would be obviously good (I've wished for that already, while working on the default styles). 112 | * It would also be cool to provide the ability to JS pre/post-processing of the rendered output. For example, [Casey wants](https://groups.google.com/d/msg/markdown-here/XlsuTCHR4zE/-iny-t2kSuIJ) to style paragraphs that follow a `H1` differently from ones that follow a `H2`, but I don't think there's a way to do it without JS (although [I suggested](https://groups.google.com/d/msg/markdown-here/XlsuTCHR4zE/ycHikmx01DUJ) a horrible hack workaround to him). 113 | 114 | I don't have a good sense for how widespread the appeal of this might be, but I suspect that it's pretty significant. (Although likely not so much among the coder crowd that I believe makes up the current user base.) 115 | 116 | Lots of work. 117 | 118 | 119 | ## Random 120 | 121 | ### Clipboard Paste 122 | 123 | In a Google Docs support issue (#28), [a user suggested](https://github.com/adam-p/markdown-here/issues/28#issuecomment-13085498) using paste to get the rendered Markdown into a GDoc. This seemed interesting, so I did some investigation. 124 | 125 | * Paste does work fairly well to get rendered Markdown into a Google Doc. (Although Paste vs. Paste and Match Style give different results.) Some massaging of the Markdown (`
` vs. `

`, maybe) might improve results. 126 | 127 | * Googling and experimentation suggests that pasting cannot be triggered from a Chrome extension. (Not to be confused with reading from the clipboard, which [can be done in a background script](http://stackoverflow.com/questions/7144702/the-proper-use-of-execcommandpaste-in-a-chrome-extension).) 128 | 129 | * Pasting probably *can* be triggered in an old-style (non-Jetpack) Firefox/Thunderbird extension. But I suspect it can't be done in a Jetpack extension (as with Chrome). 130 | 131 | * (Probably also can't be done in a Safari extension.) 132 | 133 | * A common way for websites (including Github) to support copy-to-clipboard is to use Flash. The most popular seems to be [ZeroClipboard](https://github.com/jonrohan/ZeroClipboard) -- but it doesn't magically provide pasting (even if I could figure out how to use it in an extension). 134 | 135 | * When pasting, the `markdown-here-wrapper` is lost. This means that reverting may not be possible (at the very least, it'll require another approach). 136 | 137 | * Copying arbitrary HTML to the clipboard is probably doable on all platforms (it is on Chrome, at least). 138 | 139 | So, it seem that, at best, MDH could put the rendered Markdown HTML into the clipboard and then the user will have to manually paste it. This is not great, but is perhaps better than nothing. 140 | 141 | Another really big outstanding question: Can MDH detect what's selected in the GDoc? Can it get the text? Can it change the selection? Can it delete or replace the selection? (Some simple `getSelection()` tests are *not* hopeful.) 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![Markdown Here logo](https://raw.github.com/adam-p/markdown-here/master/src/common/images/icon48.png) Markdown Here 2 | 3 | [**Visit the website.**](http://markdown-here.com) 4 | [**Get it for Chrome.**](https://chrome.google.com/webstore/detail/elifhakcjgalahccnjkneoccemfahfoa) 5 | [**Get it for Firefox.**](https://addons.mozilla.org/en-US/firefox/addon/markdown-here/) 6 | [**Get it for Safari.**](https://s3.amazonaws.com/markdown-here/markdown-here.safariextz) 7 | [**Get it for Thunderbird and Postbox.**](https://addons.mozilla.org/en-US/thunderbird/addon/markdown-here/) 8 | [**Discuss it and ask questions in the Google Group.**](https://groups.google.com/forum/?fromgroups#!forum/markdown-here/) 9 | 10 | *Markdown Here* is a Google Chrome, Firefox, Safari, and Thunderbird extension that lets you write email in Markdown and render them before sending. It also supports syntax highlighting (just specify the language in a fenced code block). 11 | 12 | Writing email with code in it is pretty tedious. Writing Markdown with code in it is easy. I found myself writing email in Markdown in the Github in-browser editor, then copying the preview into email. This is a pretty absurd workflow, so I decided create a tool to write and render Markdown right in the email. 13 | 14 | To discover what can be done with Markdown in *Markdown Here*, check out the [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) and the other [wiki pages](https://github.com/adam-p/markdown-here/wiki). 15 | 16 | †: And Google Groups posts, and Wordpress posts, and Evernote notes, and Postbox! [See details](#compatibility). 17 | ‡: And TeX mathematical formulae! 18 | 19 | ![screenshot of conversion](https://raw.github.com/adam-p/markdown-here/master/store-assets/markdown-here-image1.gimp.png) 20 | 21 | ### Table of Contents 22 | **[Installation Instructions](#installation-instructions)** 23 | **[Usage Instructions](#usage-instructions)** 24 | **[Troubleshooting](#troubleshooting)** 25 | **[Compatibility](#compatibility)** 26 | **[Notes and Miscellaneous](#notes-and-miscellaneous)** 27 | **[Building the Extension Bundles](#building-the-extension-bundles)** 28 | **[Next Steps, Credits, Feedback, License](#next-steps)** 29 | 30 | ## Installation Instructions 31 | 32 | ### Chrome 33 | 34 | #### Chrome Web Store 35 | 36 | Go to the [Chrome Web Store page for *Markdown Here*](https://chrome.google.com/webstore/detail/elifhakcjgalahccnjkneoccemfahfoa) and install normally. 37 | 38 | After installing, make sure to reload your webmail or restart Chrome! 39 | 40 | #### Manual/Development 41 | 42 | 1. Clone this repo. 43 | 2. In Chrome, open the Extensions settings. (Wrench button, Tools, Extensions.) 44 | 3. On the Extensions settings page, click the "Developer Mode" checkbox. 45 | 4. Click the now-visible "Load unpacked extension…" button. Navigate to the directory where you cloned the repo, then the `src` directory under that. 46 | 5. The *Markdown Here* extension should now be visible in your extensions list. 47 | 6. Reload your webmail page (and maybe application) before trying to convert an email. 48 | 49 | ### Firefox and Thunderbird 50 | 51 | #### Mozilla Add-ons site 52 | 53 | Go to the [Firefox Add-ons page for *Markdown Here*](https://addons.mozilla.org/en-US/firefox/addon/markdown-here/) and install normally. 54 | 55 | Or go to the "Tools > Add-ons" menu and then search for "Markdown Here". 56 | 57 | After installing, make sure to restart Firefox/Thunderbird! 58 | 59 | **Note:** It takes up to a month for Mozilla to approve changes to the Firefox/Thunderbird extension, so updates (features, fixes) will lag behind what is shown here. You can manually choose to install the newest version before it's reviewed from the list of versions: [https://addons.mozilla.org/en-US/firefox/addon/markdown-here/versions/](https://addons.mozilla.org/en-US/firefox/addon/markdown-here/versions/) 60 | 61 | #### Manual/Development 62 | 63 | 1. Clone this repo. 64 | 2. Follow the instructions in the MDN ["Setting up an extension development environment"](https://developer.mozilla.org/en/Setting_up_extension_development_environment) article. 65 | 66 | ### Safari 67 | 68 | [Download the extension directly.](https://s3.amazonaws.com/markdown-here/markdown-here.safariextz) When it has finished downloading, double click it to install. 69 | 70 | #### Preferences 71 | 72 | To get to the Markdown Here preferences, open the Safari preferences and then go to the "Extensions" tab. Then click the "Click me to show Markdown Here options" box. 73 | 74 | ## Usage Instructions 75 | 76 | Install it, and then… 77 | 78 | 1. In Chrome and Safari, *make sure* you reload your web mail page before trying to use Markdown Here. 79 | 2. In Chrome/Firefox/Safari, log into your Gmail, Hotmail, or Yahoo account and start a new email. In Thunderbird, start a new message. 80 | 3. Make sure you're using the rich editor. 81 | * In Gmail, click the "Rich formatting" link, if it's visible. 82 | * In Thunderbird, make sure "Compose messages in HTML format" is enabled in your "Account Settings", "Composition & Addressing" pane. 83 | 4. Compose an email in Markdown. For example: 84 | 85 |

 86 |    **Hello** `world`.
 87 | 
 88 |    ```javascript
 89 |    alert('Hello syntax highlighting.');
 90 |    ```
 91 |    
92 | 93 | 5. Right-click in the compose box and choose the "Markdown Toggle" item from the context menu. Or click the button that appears in your address bar. Or use the hotkey (CTRL+ALT+M by default). 94 | 6. You should see your email rendered correctly from Markdown into rich HTML. 95 | 7. Send your awesome email to everyone you know. It will appear to them the same way it looks to you. 96 | 97 | ### Revert to Markdown 98 | 99 | After rendering your Markdown to pretty HTML, you can still get back to your original Markdown. Just right-click anywhere in the newly rendered Markdown and click "Markdown Toggle" -- your email compose body will change back to the Markdown you had written. 100 | 101 | Note that any changes you make to the pretty HTML will be lost when you revert to Markdown. 102 | 103 | In Gmail, you can also use the browser's Undo command (CTRL+Z / CMD+Z, or from the Edit menu). Be warned that you might also lose the last few characters you entered. 104 | 105 | ### Replies 106 | 107 | In Gmail, Thunderbird, and Google Groups, you can use "Markdown Toggle" normally: just write your reply (top, bottom, inline, wherever) and then convert. The original email that you're replying to will be left alone. (Technically: Existing `blockquote` blocks will be left intact.) 108 | 109 | In Hotmail and Yahoo (which don't put the original in a `blockquote`), and optionally in Gmail, Thunderbird, and Google Groups, you can ensure that only the part of the reply that you wrote gets converted by selecting what you want to convert and then clicking "Markdown Toggle" -- see the next section. 110 | 111 | ### Selection/Piecemeal Conversion 112 | 113 | Sometimes you don't want to convert the entire email; sometimes your email isn't entirely Markdown. To convert only part of the email, select the text (with your mouse or keyboard), right-click on it, and click the "Markdown Toggle" menu item. Your selection is magically rendered into pretty HTML. 114 | 115 | To revert back to Markdown, just put your cursor anywhere in the block of converted text, right click, and click the "Markdown Toggle" menu item again. Now it's magically back to the original Markdown. 116 | 117 | ![screenshot of selection conversion](https://raw.github.com/adam-p/markdown-here/master/store-assets/markdown-here-image2.gimp.png) 118 | 119 | #### Things to know about converting/reverting a selection 120 | 121 | * If you select only part of a block of text, only that text will be converted. The converted block will be wrapped in a paragraph element, so the original line will be broken up. You probably don't want to ever do this. 122 | 123 | * You can select and revert multiple converted blocks at the same time. One upshot of this is that you can select your entire email, click "Markdown Toggle", and all portions of it that you had converted will be reverted. 124 | 125 | * If you don't have anything selected when you click "Markdown Toggle", *Markdown Here* will check if there are converted blocks anywhere in the message and revert them. If there no converted blocks are found, it will convert the entire email. 126 | 127 | ### Options 128 | 129 | The *Markdown Here* Options page can be accessed via the Chrome, Firefox, Safari, or Thunderbird extensions list. The available options include: 130 | 131 | * Styling modifications for the rendered Markdown. 132 | * Syntax highlighting theme selection and modification. 133 | * TeX math formulae processing enabling and customization. 134 | * What the hotkey should be. 135 | 136 | For Chrome and Firefox, any changes made in the *Markdown Here* Options are automatically synchronized between your other installations of that browser (if you have the sync feature enabled in the browser). 137 | 138 | ![screenshot of options](https://raw.github.com/adam-p/markdown-here/master/store-assets/markdown-here-chrome-options.gimp.png) 139 | 140 | ## Troubleshooting 141 | 142 | Here are some common problems that people run into. 143 | 144 |
145 |
Chrome/Firefox/Safari/Thunderbird: I just installed Markdown Here and the context menu item isn't showing up.
146 |
Make sure you restarted Firefox or Thunderbird, and either restarted Chrome/Safari or reloaded your webmail page.
147 |
148 | 149 | ## Compatibility 150 | 151 | Short answer: Gmail and Thunderbird are great. More info about some clients can be found [in the wiki](https://github.com/adam-p/markdown-here/wiki/Compatibility). 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 |
ComposeSendReceiveNotes
Gmail
Thunderbird
Hotmail 180 | Email received from Yahoo does not display with properly separated paragraphs. (Hotmail strips styling off <p> and <div> tags, and Yahoo uses the latter for paragraphs.) 181 | No reply exclusion.
YahooNo reply exclusion.
Google GroupsRendered version doesn't show in digest email. But that's probably true of manually-rich-edited posts as well.
WordpressEditor not exactly WYSIWYG, but Preview is accurateSee the Compatibility wiki page for full details and tips
Evernote (web interface)Seems to strip newlines from <pre> blocks, which breaks display of code.
PostboxInserts newlines in raw email, which can mess up code blocks.No options page. No reply exclusion.
220 | 221 | *Compose* 222 | > How *Markdown Here* behaves when composing an email. E.g., if rendering and reverting looks correct, styling is good, etc. 223 | 224 | *Send* 225 | > Negative effect that may occur when sending a rendered email from this email client. E.g., stripped tags and styles. 226 | 227 | *Receive* 228 | > How well this email client displays rendered email that it receives (assuming the sender is perfect). 229 | 230 | ## Notes and Miscellaneous 231 | 232 | * *Markdown Here* uses [Github Flavored Markdown](http://github.github.com/github-flavored-markdown/), with the limitation that GFM special links are not supported ([issue #11](https://github.com/adam-p/markdown-here/issues/11)); nor will they be, as MDH is not Github-specific. 233 | 234 | * Available languages for syntax highlighting (and the way they should be written in the fenced code block) can be seen on the [highlight.js demo page](http://softwaremaniacs.org/media/soft/highlight/test.html). 235 | 236 | * Images embedded inline in your Markdown will be retained when you "Markdown Toggle". Gmail allows you to put images inline in your email -- this can be much easier than referencing an external image. 237 | 238 | * Email signatures are automatically excluded from conversion. Specifically, anything after the semi-standard `'-- '` (note the trailing space) is left alone. 239 | * Note that Hotmail and Yahoo do *not* automatically add the `'-- '` to signatures, so you have to add it yourself. 240 | 241 | * The "Markdown Toggle" menu item shows up for more element types than it can correctly render. This is intended to help people realize that they're not using a rich editor. Otherwise they just don't see the menu item and don't know why. 242 | 243 | * Styling: 244 | * The use of browser-specific styles (-moz-, -webkit-) should be avoided. If used, they may not render correctly for people reading the email in a different browser from the one where the email was sent. 245 | * The use of state-dependent styles (like `a:hover`) don't work because they don't match at the time the styles are made explicit. (In email, styles must be explicitly applied to all elements -- stylesheets get stripped.) 246 | 247 | ## Building the Extension Bundles 248 | 249 | "Building" is really just zipping. Create all archives relative to the `src` directory. 250 | 251 | An important preparatory step is to remove any system-generated hidden files that shouldn't be 252 | included in the release file (like Windows' `desktop.ini` and OS X's `.DS_Store`, etc.). This shell command will delete those unwanted files: 253 | 254 | ``` 255 | find . -name "desktop.ini" -or -name ".*" -and -not -name "." -and -not -name ".git*" -print0 | xargs -0 rm -rf 256 | ``` 257 | 258 | ### Chrome extension 259 | 260 | Create a file with a `.zip` extension containing these files and directories: 261 | 262 | ``` 263 | manifest.json 264 | common/ 265 | chrome/ 266 | ``` 267 | 268 | ### Firefox/Thunderbird extension 269 | 270 | Create a file with a `.xpi` extension containing these files and directories: 271 | 272 | ``` 273 | chrome.manifest 274 | install.rdf 275 | common/ 276 | firefox/ 277 | ``` 278 | 279 | ### Safari extension 280 | 281 | The browser-specific code is located in the [`markdown-here-safari`](https://github.com/adam-p/markdown-here-safari) project. 282 | 283 | Use the Safari Extension Builder. 284 | 285 | ## Next Steps 286 | 287 | See the [issues list](https://github.com/adam-p/markdown-here/issues) and the [Notes file](https://github.com/adam-p/markdown-here/blob/master/NOTES.md). All ideas, bugs, plans, complaints, and dreams will end up in one of those two places. 288 | 289 | Feel free to create a feature request issue if what you want isn't already there. If you'd prefer a less formal approach to floating an idea, post to the ["markdown-here" Google Group](https://groups.google.com/forum/?fromgroups=#!forum/markdown-here). 290 | 291 | It also takes a fair bit of work to stay up-to-date with the latest changes in all the applications and web sites where Markdown Here works. 292 | 293 | ## Credits 294 | 295 | *Markdown Here* was coded on the shoulders of giants. 296 | 297 | * Markdown-to-HTML: [chjj / marked](https://github.com/chjj/marked) 298 | * Syntax highlighting: [isagalaev / highlight.js](https://github.com/isagalaev/highlight.js) 299 | * HTML-to-text: [mtrimpe / jsHtmlToText](https://github.com/mtrimpe/jsHtmlToText) 300 | 301 | ## Feedback 302 | 303 | All bugs, feature requests, pull requests, feedback, etc., are welcome. [Create an issue](https://github.com/adam-p/markdown-here/issues). Or [post to the "markdown-here" Google Group](https://groups.google.com/forum/?fromgroups=#!forum/markdown-here). 304 | 305 | ## License 306 | 307 | ### Code 308 | 309 | MIT License: http://adampritchard.mit-license.org/ or see [the `LICENSE` file](https://github.com/adam-p/markdown-here/blob/master/LICENSE). 310 | 311 | ### Logo 312 | 313 | Copyright 2013, [Tatiana A. Fryntoff](http://tatianafryntoff.com/). Licensed under [Creative Commons Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by/3.0/). 314 | 315 | ### Other images 316 | 317 | [Creative Commons Attribution 3.0 Unported (CC BY 3.0) License](http://creativecommons.org/licenses/by/3.0/) 318 | 319 | --- 320 | 321 | ![Dos Equis man says](https://raw.github.com/adam-p/markdown-here/master/store-assets/dos-equis-MDH.jpg) 322 | -------------------------------------------------------------------------------- /src/chrome.manifest: -------------------------------------------------------------------------------- 1 | content markdown_here firefox/chrome/content/ 2 | skin markdown_here classic/1.0 firefox/chrome/skin/ 3 | locale markdown_here en-US firefox/chrome/locale/en-US/ 4 | resource markdown_here_common common/ 5 | 6 | style chrome://global/content/customizeToolbar.xul chrome://markdown_here/skin/toolbar.css 7 | 8 | overlay chrome://zotero/content/zoteroPane.xul chrome://markdown_here/content/zotero-overlay.xul 9 | 10 | overlay chrome://browser/content/browser.xul chrome://markdown_here/content/ff-overlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} 11 | overlay chrome://browser/content/browser.xul chrome://markdown_here/content/background-services-overlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} 12 | 13 | overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://markdown_here/content/tb-overlay.xul application={3550f703-e582-4d05-9a08-453d09bdfdc6} 14 | overlay chrome://messenger/content/specialTabs.xul chrome://markdown_here/content/background-services-overlay.xul application={3550f703-e582-4d05-9a08-453d09bdfdc6} 15 | 16 | overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://markdown_here/content/tb-overlay.xul application=postbox@postbox-inc.com 17 | overlay chrome://messenger/content/specialTabs.xul chrome://markdown_here/content/background-services-overlay.xul application=postbox@postbox-inc.com 18 | -------------------------------------------------------------------------------- /src/chrome/background.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/chrome/backgroundscript.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2012 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | "use strict"; 7 | /*global chrome:false, OptionsStore:false, markdownRender:false, 8 | htmlToText:false, marked:false, hljs:false*/ 9 | /*jshint devel:true*/ 10 | 11 | /* 12 | * Chrome background script. 13 | */ 14 | 15 | // On each load, check if we should show the options/changelist page. 16 | window.addEventListener('load', function() { 17 | OptionsStore.get(function(options) { 18 | var appDetails = chrome.app.getDetails(); 19 | 20 | // Have we been updated? 21 | if (options['last-version'] !== appDetails.version) { 22 | var optionsUrl = appDetails.options_page; 23 | 24 | // If this is an upgrade, open the options page in changelist mode 25 | if (options['last-version']) { 26 | optionsUrl += '?prevVer=' + options['last-version']; 27 | } 28 | 29 | // Open our options page 30 | chrome.tabs.create({ url: optionsUrl }); 31 | 32 | // Update out last version 33 | OptionsStore.set({ 'last-version': appDetails.version }); 34 | } 35 | }); 36 | }, false); 37 | 38 | // Create the context menu that will signal our main code. 39 | chrome.contextMenus.create({ 40 | contexts: ['editable'], 41 | title: 'Mar&kdown Toggle', 42 | onclick: function(info, tab) { 43 | chrome.tabs.sendRequest(tab.id, {action: 'context-click'}); 44 | } 45 | }); 46 | 47 | // Handle rendering requests from the content script. 48 | // See the comment in markdown-render.js for why we do this. 49 | chrome.extension.onRequest.addListener(function(request, sender, responseCallback) { 50 | // The content script can load in a not-real tab (like the search box), which 51 | // has a tab.id of -1. We should just ignore these pages. 52 | if (sender.tab.id < 0) { 53 | return; 54 | } 55 | 56 | if (request.action === 'render') { 57 | OptionsStore.get(function(prefs) { 58 | responseCallback({ 59 | html: markdownRender( 60 | prefs, 61 | htmlToText, 62 | marked, 63 | hljs, 64 | request.html, 65 | document, 66 | sender.tab.url), 67 | css: (prefs['main-css'] + prefs['syntax-css']) 68 | }); 69 | }); 70 | } 71 | else if (request.action === 'get-options') { 72 | OptionsStore.get(function(prefs) { responseCallback(prefs); }); 73 | } 74 | else if (request.action === 'show-toggle-button') { 75 | if (request.show) { 76 | chrome.browserAction.enable(sender.tab.id); 77 | } 78 | else { 79 | chrome.browserAction.disable(sender.tab.id); 80 | } 81 | } 82 | else { 83 | console.log('unmatched request action'); 84 | console.log(request.action); 85 | throw 'unmatched request action: ' + request.action; 86 | } 87 | }); 88 | 89 | // Add the browserAction (the button in the browser toolbar) listener. 90 | chrome.browserAction.onClicked.addListener(function(tab) { 91 | chrome.tabs.sendRequest(tab.id, {action: 'button-click'}); 92 | }); 93 | -------------------------------------------------------------------------------- /src/chrome/contentscript.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2012 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | "use strict"; 7 | /*global chrome:false, markdownHere:false*/ 8 | /*jshint devel:true, browser:true*/ 9 | 10 | 11 | /* 12 | * Chrome-specific code for responding to the context menu item and providing 13 | * rendering services. 14 | */ 15 | 16 | 17 | // Handle the menu-item click 18 | function requestHandler(event) { 19 | var focusedElem, mdReturn; 20 | 21 | if (event && (event.action === 'context-click' || 22 | event.action === 'hotkey' || 23 | event.action === 'button-click')) { 24 | 25 | // Check if the focused element is a valid render target 26 | focusedElem = markdownHere.findFocusedElem(window.document); 27 | if (!focusedElem) { 28 | // Shouldn't happen. But if it does, just silently abort. 29 | return; 30 | } 31 | 32 | if (!markdownHere.elementCanBeRendered(focusedElem)) { 33 | alert('The selected field is not valid for Markdown rendering. Please use a rich editor.'); 34 | return; 35 | } 36 | 37 | var logger = function() { console.log.apply(console, arguments); }; 38 | 39 | mdReturn = markdownHere(document, requestMarkdownConversion, logger); 40 | 41 | if (typeof(mdReturn) === 'string') { 42 | // Error message was returned. 43 | alert(mdReturn); 44 | return; 45 | } 46 | } 47 | } 48 | chrome.extension.onRequest.addListener(requestHandler); 49 | 50 | 51 | // The rendering service provided to the content script. 52 | // See the comment in markdown-render.js for why we do this. 53 | function requestMarkdownConversion(html, callback) { 54 | // Send a request to the add-on script to actually do the rendering. 55 | chrome.extension.sendRequest({action: 'render', html: html}, function(response) { 56 | callback(response.html, response.css); 57 | }); 58 | } 59 | 60 | 61 | /* 62 | * Show/hide the toggle button. 63 | */ 64 | 65 | // We're going to show the button depending on whether the currently focused 66 | // element is renderable or not. We'll keep track of what's "currently 67 | // focused" in two ways: 68 | // 1) Handling `focus` events. But that doesn't work for iframes, so we also 69 | // need... 70 | // 2) An interval timer. Every so often we'll check the current focus. 71 | // 72 | // In principle, the #2 is sufficient by itself, but it's nice to have the 73 | // immediate response of #1 where possible. (And I hesitate to make the timer 74 | // interval too small. I already find this approach distasteful.) The focus 75 | // event does actually work for the new Chrome+Gmail interface, which is an 76 | // important target. 77 | // 78 | // The problem with iframes is that they don't get focus/blur events when 79 | // moving between iframes. 80 | // 81 | // Regarding the `focus` event: Chrome seems to give us (bubbling) focus 82 | // events if `useCapture` is true. Firefox doesn't seem to give us focus 83 | // events at all (and it doesn't provide `focusin` or `DOMFocusIn`). So on FF 84 | // we're basically relaying entirely on the interval checks. 85 | 86 | 87 | // At this time, only this function differs between Chrome and Firefox. 88 | function showToggleButton(show) { 89 | chrome.extension.sendRequest({ action: 'show-toggle-button', show: show }); 90 | } 91 | 92 | 93 | var lastElemChecked, lastRenderable; 94 | function setToggleButtonVisibility(elem) { 95 | var renderable = false; 96 | 97 | // Assumption: An element does not change renderability. 98 | if (elem === lastElemChecked) { 99 | return; 100 | } 101 | lastElemChecked = elem; 102 | 103 | if (elem && elem.ownerDocument) { 104 | // We may have gotten here via the timer, so we'll add an event handler. 105 | // Setting the event handler like this lets us better deal with iframes. 106 | // It's okay to call `addEventListener` more than once with the exact same 107 | // arguments. 108 | elem.ownerDocument.addEventListener('focus', focusChange, true); 109 | 110 | renderable = markdownHere.elementCanBeRendered(elem); 111 | } 112 | 113 | if (renderable !== lastRenderable) { 114 | showToggleButton(renderable); 115 | lastRenderable = renderable; 116 | } 117 | } 118 | 119 | 120 | // When the focus in the page changes, check if the newly focused element is 121 | // a valid Markdown Toggle target. 122 | function focusChange(event) { 123 | setToggleButtonVisibility(event.target); 124 | } 125 | window.document.addEventListener('focus', focusChange, true); 126 | 127 | 128 | function buttonIntervalCheck(focusedElem) { 129 | setToggleButtonVisibility(focusedElem); 130 | } 131 | 132 | 133 | /* 134 | * Hotkey support 135 | */ 136 | 137 | // Default the hotkey check to a no-op until we get the necessary info from the 138 | // user options. 139 | var hotkeyIntervalCheck = function(focusedElem) {}; 140 | var hotkeyGetOptionsHandler = function(prefs) { 141 | // If the background script isn't properly loaded, it can happen that the 142 | // `prefs` argument is undefined. Detect this and try again. 143 | if (typeof(prefs) === 'undefined') { 144 | chrome.extension.sendRequest({action: 'get-options'}, hotkeyGetOptionsHandler); 145 | return; 146 | } 147 | 148 | // Only add a listener if a key is set 149 | if (prefs.hotkey.key.length === 1) { 150 | 151 | // HACK: In Chrome, we have to add a keydown listener to every iframe of interest, 152 | // otherwise the handler will only fire on the topmost window. It's difficult 153 | // to iterate (recursively) through iframes and add listeners to them (especially 154 | // for Yahoo, where there isn't a page change when the compose window appears, 155 | // so this content script doesn't get re-run). Instead we're going to use the 156 | // dirty hack of checking every few seconds if the user has focused a new iframe 157 | // and adding a handler to it. 158 | // Note that this will result in addEventListener being called on the same 159 | // iframe/document repeatedly, but that's okay -- duplicate handlers are discarded. 160 | // https://developer.mozilla.org/en-US/docs/DOM/element.addEventListener#Multiple_identical_event_listeners 161 | 162 | // The actual hotkey event handler. 163 | var hotkeyHandler = function(event) { 164 | if (event.shiftKey === prefs.hotkey.shiftKey && 165 | event.ctrlKey === prefs.hotkey.ctrlKey && 166 | event.altKey === prefs.hotkey.altKey && 167 | event.which === prefs.hotkey.key.toUpperCase().charCodeAt(0)) { 168 | requestHandler({action: 'hotkey'}); 169 | event.preventDefault(); 170 | return false; 171 | } 172 | }; 173 | 174 | // The hotkey option is enabled, and we've created our event handler function, 175 | // so now let's do real hotkey interval checking. 176 | hotkeyIntervalCheck = function(focusedElem) { 177 | if (focusedElem.ownerDocument) { 178 | focusedElem = focusedElem.ownerDocument; 179 | } 180 | 181 | // TODO: Chrome and Mozilla: Only add a hotkey handler on pages/iframes that 182 | // are valid targets. And/or let the hotkey match if the correct type of 183 | // control has focus. 184 | 185 | focusedElem.addEventListener('keydown', hotkeyHandler, false); 186 | }; 187 | } 188 | // else the hotkey is disabled and we'll leave hotkeyIntervalCheck as a no-op 189 | }; 190 | chrome.extension.sendRequest({action: 'get-options'}, hotkeyGetOptionsHandler); 191 | 192 | 193 | /* 194 | * Interval checks 195 | * See specific sections above for reasons why this is necessary. 196 | */ 197 | 198 | function intervalCheck() { 199 | var focusedElem = markdownHere.findFocusedElem(window.document); 200 | if (!focusedElem) { 201 | return; 202 | } 203 | 204 | hotkeyIntervalCheck(focusedElem); 205 | buttonIntervalCheck(focusedElem); 206 | } 207 | setInterval(intervalCheck, 2000); 208 | -------------------------------------------------------------------------------- /src/common/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: 3 | * - The use of browser-specific styles (-moz-, -webkit-) should be avoided. 4 | * If used, they may not render correctly for people reading the email in 5 | * a different browser than the one from which the email was sent. 6 | * - The use of state-dependent styles (like a:hover) don't work because they 7 | * don't match at the time the styles are made explicit. (In email, styles 8 | * must be explicitly applied to all elements -- stylesheets get stripped.) 9 | */ 10 | 11 | /* This is the overall wrapper, it should be treated as the `body` section. */ 12 | .markdown-here-wrapper { 13 | } 14 | 15 | pre, code { 16 | font-size: 0.85em; 17 | font-family: Consolas, Inconsolata, Courier, monospace; 18 | } 19 | 20 | code { 21 | margin: 0 0.15em; 22 | padding: 0 0.3em; 23 | white-space: pre-wrap; 24 | border: 1px solid #EAEAEA; 25 | background-color: #F8F8F8; 26 | border-radius: 3px; 27 | display: inline; /* adam-p: added to fix Yahoo block display */ 28 | } 29 | 30 | pre { 31 | font-size: 1em; 32 | line-height: 1.2em; 33 | } 34 | 35 | pre code { 36 | white-space: pre; 37 | overflow: auto; /* fixes issue #70: Firefox/Thunderbird: Code blocks with horizontal scroll would have bad background colour */ 38 | border-radius: 3px; 39 | border: 1px solid #CCC; 40 | padding: 0.5em 0.7em; 41 | } 42 | 43 | /* This spacing has been tweaked to closely match Gmail+Chrome "paragraph" (two line breaks) spacing. */ 44 | p { 45 | /* !important is needed here because Hotmail/Outlook.com uses !important to 46 | kill the margin in

. We need this to win. */ 47 | margin: 1.2em 0 !important; 48 | } 49 | 50 | table, pre, dl, blockquote, q, ul, ol { 51 | margin: 1.2em 0; 52 | } 53 | 54 | ul, ol { 55 | padding-left: 2em; 56 | } 57 | 58 | li { 59 | margin: 0.5em 0; 60 | } 61 | 62 | /* Space paragraphs in a list the same as the list itself. */ 63 | li p { 64 | /* Needs !important to override rule above. */ 65 | margin: 0.5em 0 !important; 66 | } 67 | 68 | /* Smaller spacing for sub-lists */ 69 | ul ul, ul ol, ol ul, ol ol { 70 | margin: 0; 71 | padding-left: 1em; 72 | } 73 | 74 | dl { 75 | padding: 0; 76 | } 77 | 78 | dl dt { 79 | font-size: 1em; 80 | font-weight: bold; 81 | font-style: italic; 82 | } 83 | 84 | dl dd { 85 | margin: 0 0 1em; 86 | padding: 0 1em; 87 | } 88 | 89 | blockquote, q { 90 | border-left: 4px solid #DDD; 91 | padding: 0 1em; 92 | color: #777; 93 | quotes: none; 94 | } 95 | 96 | blockquote::before, blockquote::after, q::before, q::after { 97 | content: none; 98 | } 99 | 100 | h1, h2, h3, h4, h5, h6 { 101 | margin: 1.3em 0 1em; 102 | padding: 0; 103 | font-weight: bold; 104 | } 105 | 106 | h1 { 107 | font-size: 1.6em; 108 | } 109 | 110 | h2 { 111 | font-size: 1.4em; 112 | border-bottom: 1px solid #CCC; 113 | } 114 | 115 | h3 { 116 | font-size: 1.3em; 117 | } 118 | 119 | h4 { 120 | font-size: 1.2em; 121 | } 122 | 123 | h5 { 124 | font-size: 1em; 125 | } 126 | 127 | h6 { 128 | font-size: 1em; 129 | color: #777; 130 | } 131 | 132 | table { 133 | padding: 0; 134 | border-collapse: collapse; 135 | border-spacing: 0; 136 | font-size: 1em; 137 | font: inherit; 138 | border: 0; 139 | } 140 | 141 | tbody { 142 | margin: 0; 143 | padding: 0; 144 | border: 0; 145 | } 146 | 147 | table tr { 148 | border: 0; 149 | border-top: 1px solid #CCC; 150 | background-color: white; 151 | margin: 0; 152 | padding: 0; 153 | } 154 | 155 | table tr:nth-child(2n) { 156 | background-color: #F8F8F8; 157 | } 158 | 159 | table tr th, table tr td { 160 | font-size: 1em; 161 | border: 1px solid #CCC; 162 | margin: 0; 163 | padding: 0.5em 1em; 164 | } 165 | 166 | table tr th { 167 | font-weight: bold; 168 | background-color: #F0F0F0; 169 | } 170 | 171 | table tr td[align="right"] { 172 | text-align: right; 173 | } 174 | 175 | table tr td[align="left"] { 176 | text-align: left; 177 | } 178 | 179 | table tr td[align="center"] { 180 | text-align: center; 181 | } 182 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/arta.css: -------------------------------------------------------------------------------- 1 | /* 2 | Date: 17.V.2011 3 | Author: pumbur 4 | */ 5 | 6 | pre code 7 | { 8 | display: block; padding: 0.5em; 9 | background: #222; 10 | } 11 | 12 | pre .profile .header *, 13 | pre .ini .title, 14 | pre .nginx .title 15 | { 16 | color: #fff; 17 | } 18 | 19 | pre .comment, 20 | pre .javadoc, 21 | pre .preprocessor, 22 | pre .preprocessor .title, 23 | pre .shebang, 24 | pre .profile .summary, 25 | pre .diff, 26 | pre .pi, 27 | pre .doctype, 28 | pre .tag, 29 | pre .template_comment, 30 | pre .css .rules, 31 | pre .tex .special 32 | { 33 | color: #444; 34 | } 35 | 36 | pre .string, 37 | pre .symbol, 38 | pre .diff .change, 39 | pre .regexp, 40 | pre .xml .attribute, 41 | pre .smalltalk .char, 42 | pre .xml .value, 43 | pre .ini .value, 44 | pre .clojure .attribute 45 | { 46 | color: #ffcc33; 47 | } 48 | 49 | pre .number, 50 | pre .addition 51 | { 52 | color: #00cc66; 53 | } 54 | 55 | pre .built_in, 56 | pre .literal, 57 | pre .vhdl .typename, 58 | pre .go .constant, 59 | pre .go .typename, 60 | pre .ini .keyword, 61 | pre .lua .title, 62 | pre .perl .variable, 63 | pre .php .variable, 64 | pre .mel .variable, 65 | pre .django .variable, 66 | pre .css .funtion, 67 | pre .smalltalk .method, 68 | pre .hexcolor, 69 | pre .important, 70 | pre .flow, 71 | pre .inheritance, 72 | pre .parser3 .variable 73 | { 74 | color: #32AAEE; 75 | } 76 | 77 | pre .keyword, 78 | pre .tag .title, 79 | pre .css .tag, 80 | pre .css .class, 81 | pre .css .id, 82 | pre .css .pseudo, 83 | pre .css .attr_selector, 84 | pre .lisp .title, 85 | pre .clojure .built_in, 86 | pre .winutils, 87 | pre .tex .command, 88 | pre .request, 89 | pre .status 90 | { 91 | color: #6644aa; 92 | } 93 | 94 | pre .title, 95 | pre .ruby .constant, 96 | pre .vala .constant, 97 | pre .parent, 98 | pre .deletion, 99 | pre .template_tag, 100 | pre .css .keyword, 101 | pre .objectivec .class .id, 102 | pre .smalltalk .class, 103 | pre .lisp .keyword, 104 | pre .apache .tag, 105 | pre .nginx .variable, 106 | pre .envvar, 107 | pre .bash .variable, 108 | pre .go .built_in, 109 | pre .vbscript .built_in, 110 | pre .lua .built_in, 111 | pre .rsl .built_in, 112 | pre .tail, 113 | pre .avrasm .label, 114 | pre .tex .formula, 115 | pre .tex .formula * 116 | { 117 | color: #bb1166; 118 | } 119 | 120 | pre .yardoctag, 121 | pre .phpdoc, 122 | pre .profile .header, 123 | pre .ini .title, 124 | pre .apache .tag, 125 | pre .parser3 .title 126 | { 127 | font-weight: bold; 128 | } 129 | 130 | pre .coffeescript .javascript, 131 | pre .xml .javascript, 132 | pre .xml .css, 133 | pre .xml .cdata 134 | { 135 | opacity: 0.6; 136 | } 137 | 138 | pre code, 139 | pre .javascript, 140 | pre .css, 141 | pre .xml, 142 | pre .subst, 143 | pre .diff .chunk, 144 | pre .css .value, 145 | pre .css .attribute, 146 | pre .lisp .string, 147 | pre .lisp .number, 148 | pre .tail .params, 149 | pre .container, 150 | pre .haskell *, 151 | pre .erlang *, 152 | pre .erlang_repl * 153 | { 154 | color: #aaa; 155 | } 156 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/ascetic.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Original style from softwaremaniacs.org (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: white; color: black; 10 | } 11 | 12 | pre .string, 13 | pre .tag .value, 14 | pre .filter .argument, 15 | pre .addition, 16 | pre .change, 17 | pre .apache .tag, 18 | pre .apache .cbracket, 19 | pre .nginx .built_in, 20 | pre .tex .formula { 21 | color: #888; 22 | } 23 | 24 | pre .comment, 25 | pre .template_comment, 26 | pre .shebang, 27 | pre .doctype, 28 | pre .pi, 29 | pre .javadoc, 30 | pre .deletion, 31 | pre .apache .sqbracket { 32 | color: #CCC; 33 | } 34 | 35 | pre .keyword, 36 | pre .tag .title, 37 | pre .ini .title, 38 | pre .lisp .title, 39 | pre .clojure .title, 40 | pre .http .title, 41 | pre .nginx .title, 42 | pre .css .tag, 43 | pre .winutils, 44 | pre .flow, 45 | pre .apache .tag, 46 | pre .tex .command, 47 | pre .request, 48 | pre .status { 49 | font-weight: bold; 50 | } 51 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/brown_paper.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Brown Paper style from goldblog.com.ua (c) Zaripov Yura 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background-color:#b7a68e; /* adam-p: removed background image */ 10 | } 11 | 12 | pre .keyword, 13 | pre .literal, 14 | pre .change, 15 | pre .winutils, 16 | pre .flow, 17 | pre .lisp .title, 18 | pre .clojure .built_in, 19 | pre .nginx .title, 20 | pre .tex .special, 21 | pre .request, 22 | pre .status { 23 | color:#005599; 24 | font-weight:bold; 25 | } 26 | 27 | pre code, 28 | pre .ruby .subst, 29 | pre .tag .keyword { 30 | color: #363C69; 31 | } 32 | 33 | pre .string, 34 | pre .title, 35 | pre .haskell .type, 36 | pre .tag .value, 37 | pre .css .rules .value, 38 | pre .preprocessor, 39 | pre .ruby .symbol, 40 | pre .ruby .symbol .string, 41 | pre .ruby .class .parent, 42 | pre .built_in, 43 | pre .sql .aggregate, 44 | pre .django .template_tag, 45 | pre .django .variable, 46 | pre .smalltalk .class, 47 | pre .javadoc, 48 | pre .ruby .string, 49 | pre .django .filter .argument, 50 | pre .smalltalk .localvars, 51 | pre .smalltalk .array, 52 | pre .attr_selector, 53 | pre .pseudo, 54 | pre .addition, 55 | pre .stream, 56 | pre .envvar, 57 | pre .apache .tag, 58 | pre .apache .cbracket, 59 | pre .tex .number { 60 | color: #2C009F; 61 | } 62 | 63 | pre .comment, 64 | pre .java .annotation, 65 | pre .python .decorator, 66 | pre .template_comment, 67 | pre .pi, 68 | pre .doctype, 69 | pre .deletion, 70 | pre .shebang, 71 | pre .apache .sqbracket, 72 | pre .nginx .built_in, 73 | pre .tex .formula { 74 | color: #802022; 75 | } 76 | 77 | pre .keyword, 78 | pre .literal, 79 | pre .css .id, 80 | pre .phpdoc, 81 | pre .title, 82 | pre .haskell .type, 83 | pre .vbscript .built_in, 84 | pre .sql .aggregate, 85 | pre .rsl .built_in, 86 | pre .smalltalk .class, 87 | pre .diff .header, 88 | pre .chunk, 89 | pre .winutils, 90 | pre .bash .variable, 91 | pre .apache .tag, 92 | pre .tex .command { 93 | font-weight: bold; 94 | } 95 | 96 | pre .coffeescript .javascript, 97 | pre .xml .css, 98 | pre .xml .javascript, 99 | pre .xml .vbscript, 100 | pre .tex .formula { 101 | opacity: 0.8; 102 | } 103 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Dark style from softwaremaniacs.org (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #444; 10 | } 11 | 12 | pre .keyword, 13 | pre .literal, 14 | pre .change, 15 | pre .winutils, 16 | pre .flow, 17 | pre .lisp .title, 18 | pre .clojure .built_in, 19 | pre .nginx .title, 20 | pre .tex .special { 21 | color: white; 22 | } 23 | 24 | pre code, 25 | pre .ruby .subst { 26 | color: #DDD; 27 | } 28 | 29 | pre .string, 30 | pre .title, 31 | pre .haskell .type, 32 | pre .ini .title, 33 | pre .tag .value, 34 | pre .css .rules .value, 35 | pre .preprocessor, 36 | pre .ruby .symbol, 37 | pre .ruby .symbol .string, 38 | pre .ruby .class .parent, 39 | pre .built_in, 40 | pre .sql .aggregate, 41 | pre .django .template_tag, 42 | pre .django .variable, 43 | pre .smalltalk .class, 44 | pre .javadoc, 45 | pre .ruby .string, 46 | pre .django .filter .argument, 47 | pre .smalltalk .localvars, 48 | pre .smalltalk .array, 49 | pre .attr_selector, 50 | pre .pseudo, 51 | pre .addition, 52 | pre .stream, 53 | pre .envvar, 54 | pre .apache .tag, 55 | pre .apache .cbracket, 56 | pre .tex .command, 57 | pre .input_number { 58 | color: #D88; 59 | } 60 | 61 | pre .comment, 62 | pre .java .annotation, 63 | pre .python .decorator, 64 | pre .template_comment, 65 | pre .pi, 66 | pre .doctype, 67 | pre .deletion, 68 | pre .shebang, 69 | pre .apache .sqbracket, 70 | pre .tex .formula { 71 | color: #777; 72 | } 73 | 74 | pre .keyword, 75 | pre .literal, 76 | pre .title, 77 | pre .css .id, 78 | pre .phpdoc, 79 | pre .haskell .type, 80 | pre .vbscript .built_in, 81 | pre .sql .aggregate, 82 | pre .rsl .built_in, 83 | pre .smalltalk .class, 84 | pre .diff .header, 85 | pre .chunk, 86 | pre .winutils, 87 | pre .bash .variable, 88 | pre .apache .tag, 89 | pre .tex .special, 90 | pre .request, 91 | pre .status { 92 | font-weight: bold; 93 | } 94 | 95 | pre .coffeescript .javascript, 96 | pre .xml .css, 97 | pre .xml .javascript, 98 | pre .xml .vbscript, 99 | pre .tex .formula { 100 | opacity: 0.5; 101 | } 102 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Original style from softwaremaniacs.org (c) Ivan Sagalaev 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #F0F0F0; 10 | } 11 | 12 | pre code, 13 | pre .ruby .subst, 14 | pre .tag .title, 15 | pre .lisp .title, 16 | pre .clojure .built_in, 17 | pre .nginx .title { 18 | color: black; 19 | } 20 | 21 | pre .string, 22 | pre .title, 23 | pre .constant, 24 | pre .parent, 25 | pre .tag .value, 26 | pre .rules .value, 27 | pre .rules .value .number, 28 | pre .preprocessor, 29 | pre .ruby .symbol, 30 | pre .ruby .symbol .string, 31 | pre .aggregate, 32 | pre .template_tag, 33 | pre .django .variable, 34 | pre .smalltalk .class, 35 | pre .addition, 36 | pre .flow, 37 | pre .stream, 38 | pre .bash .variable, 39 | pre .apache .tag, 40 | pre .apache .cbracket, 41 | pre .tex .command, 42 | pre .tex .special, 43 | pre .erlang_repl .function_or_atom, 44 | pre .markdown .header { 45 | color: #800; 46 | } 47 | 48 | pre .comment, 49 | pre .annotation, 50 | pre .template_comment, 51 | pre .diff .header, 52 | pre .chunk, 53 | pre .markdown .blockquote { 54 | color: #888; 55 | } 56 | 57 | pre .number, 58 | pre .date, 59 | pre .regexp, 60 | pre .literal, 61 | pre .smalltalk .symbol, 62 | pre .smalltalk .char, 63 | pre .go .constant, 64 | pre .change, 65 | pre .markdown .bullet, 66 | pre .markdown .link_url { 67 | color: #080; 68 | } 69 | 70 | pre .label, 71 | pre .javadoc, 72 | pre .ruby .string, 73 | pre .decorator, 74 | pre .filter .argument, 75 | pre .localvars, 76 | pre .array, 77 | pre .attr_selector, 78 | pre .important, 79 | pre .pseudo, 80 | pre .pi, 81 | pre .doctype, 82 | pre .deletion, 83 | pre .envvar, 84 | pre .shebang, 85 | pre .apache .sqbracket, 86 | pre .nginx .built_in, 87 | pre .tex .formula, 88 | pre .erlang_repl .reserved, 89 | pre .input_number, 90 | pre .markdown .link_label, 91 | pre .vhdl .attribute, 92 | pre .clojure .attribute { 93 | color: #88F 94 | } 95 | 96 | pre .keyword, 97 | pre .id, 98 | pre .phpdoc, 99 | pre .title, 100 | pre .built_in, 101 | pre .aggregate, 102 | pre .css .tag, 103 | pre .javadoctag, 104 | pre .phpdoc, 105 | pre .yardoctag, 106 | pre .smalltalk .class, 107 | pre .winutils, 108 | pre .bash .variable, 109 | pre .apache .tag, 110 | pre .go .typename, 111 | pre .tex .command, 112 | pre .markdown .strong, 113 | pre .request, 114 | pre .status { 115 | font-weight: bold; 116 | } 117 | 118 | pre .markdown .emphasis { 119 | font-style: italic; 120 | } 121 | 122 | pre .nginx .built_in { 123 | font-weight: normal; 124 | } 125 | 126 | pre .coffeescript .javascript, 127 | pre .xml .css, 128 | pre .xml .javascript, 129 | pre .xml .vbscript, 130 | pre .tex .formula { 131 | opacity: 0.5; 132 | } 133 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/far.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | FAR Style (c) MajestiC 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #000080; 10 | } 11 | 12 | pre code, 13 | .ruby .subst { 14 | color: #0FF; 15 | } 16 | 17 | pre .string, 18 | pre .ruby .string, 19 | pre .haskell .type, 20 | pre .tag .value, 21 | pre .css .rules .value, 22 | pre .css .rules .value .number, 23 | pre .preprocessor, 24 | pre .ruby .symbol, 25 | pre .ruby .symbol .string, 26 | pre .built_in, 27 | pre .sql .aggregate, 28 | pre .django .template_tag, 29 | pre .django .variable, 30 | pre .smalltalk .class, 31 | pre .addition, 32 | pre .apache .tag, 33 | pre .apache .cbracket, 34 | pre .tex .command, 35 | pre .clojure .title { 36 | color: #FF0; 37 | } 38 | 39 | pre .keyword, 40 | pre .css .id, 41 | pre .title, 42 | pre .haskell .type, 43 | pre .vbscript .built_in, 44 | pre .sql .aggregate, 45 | pre .rsl .built_in, 46 | pre .smalltalk .class, 47 | pre .xml .tag .title, 48 | pre .winutils, 49 | pre .flow, 50 | pre .change, 51 | pre .envvar, 52 | pre .bash .variable, 53 | pre .tex .special, 54 | pre .clojure .built_in { 55 | color: #FFF; 56 | } 57 | 58 | pre .comment, 59 | pre .phpdoc, 60 | pre .javadoc, 61 | pre .java .annotation, 62 | pre .template_comment, 63 | pre .deletion, 64 | pre .apache .sqbracket, 65 | pre .tex .formula { 66 | color: #888; 67 | } 68 | 69 | pre .number, 70 | pre .date, 71 | pre .regexp, 72 | pre .literal, 73 | pre .smalltalk .symbol, 74 | pre .smalltalk .char, 75 | pre .clojure .attribute { 76 | color: #0F0; 77 | } 78 | 79 | pre .python .decorator, 80 | pre .django .filter .argument, 81 | pre .smalltalk .localvars, 82 | pre .smalltalk .array, 83 | pre .attr_selector, 84 | pre .pseudo, 85 | pre .xml .pi, 86 | pre .diff .header, 87 | pre .chunk, 88 | pre .shebang, 89 | pre .nginx .built_in, 90 | pre .input_number { 91 | color: #008080; 92 | } 93 | 94 | pre .keyword, 95 | pre .css .id, 96 | pre .title, 97 | pre .haskell .type, 98 | pre .vbscript .built_in, 99 | pre .sql .aggregate, 100 | pre .rsl .built_in, 101 | pre .smalltalk .class, 102 | pre .winutils, 103 | pre .flow, 104 | pre .apache .tag, 105 | pre .nginx .built_in, 106 | pre .tex .command, 107 | pre .tex .special, 108 | pre .request, 109 | pre .status { 110 | font-weight: bold; 111 | } 112 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | color: #333; 10 | background: #f8f8ff 11 | } 12 | 13 | pre .comment, 14 | pre .template_comment, 15 | pre .diff .header, 16 | pre .javadoc { 17 | color: #998; 18 | font-style: italic 19 | } 20 | 21 | pre .keyword, 22 | pre .css .rule .keyword, 23 | pre .winutils, 24 | pre .javascript .title, 25 | pre .nginx .title, 26 | pre .subst, 27 | pre .request, 28 | pre .status { 29 | color: #333; 30 | font-weight: bold 31 | } 32 | 33 | pre .number, 34 | pre .hexcolor, 35 | pre .ruby .constant { 36 | color: #099; 37 | } 38 | 39 | pre .string, 40 | pre .tag .value, 41 | pre .phpdoc, 42 | pre .tex .formula { 43 | color: #d14 44 | } 45 | 46 | pre .title, 47 | pre .id { 48 | color: #900; 49 | font-weight: bold 50 | } 51 | 52 | pre .javascript .title, 53 | pre .lisp .title, 54 | pre .clojure .title, 55 | pre .subst { 56 | font-weight: normal 57 | } 58 | 59 | pre .class .title, 60 | pre .haskell .type, 61 | pre .vhdl .literal, 62 | pre .tex .command { 63 | color: #458; 64 | font-weight: bold 65 | } 66 | 67 | pre .tag, 68 | pre .tag .title, 69 | pre .rules .property, 70 | pre .django .tag .keyword { 71 | color: #000080; 72 | font-weight: normal 73 | } 74 | 75 | pre .attribute, 76 | pre .variable, 77 | pre .lisp .body { 78 | color: #008080 79 | } 80 | 81 | pre .regexp { 82 | color: #009926 83 | } 84 | 85 | pre .class { 86 | color: #458; 87 | font-weight: bold 88 | } 89 | 90 | pre .symbol, 91 | pre .ruby .symbol .string, 92 | pre .lisp .keyword, 93 | pre .tex .special, 94 | pre .input_number { 95 | color: #990073 96 | } 97 | 98 | pre .built_in, 99 | pre .lisp .title, 100 | pre .clojure .built_in { 101 | color: #0086b3 102 | } 103 | 104 | pre .preprocessor, 105 | pre .pi, 106 | pre .doctype, 107 | pre .shebang, 108 | pre .cdata { 109 | color: #999; 110 | font-weight: bold 111 | } 112 | 113 | pre .deletion { 114 | background: #fdd 115 | } 116 | 117 | pre .addition { 118 | background: #dfd 119 | } 120 | 121 | pre .diff .change { 122 | background: #0086b3 123 | } 124 | 125 | pre .chunk { 126 | color: #aaa 127 | } 128 | 129 | pre .tex .formula { 130 | opacity: 0.5; 131 | } 132 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/googlecode.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Google Code style (c) Aahan Krish 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: white; color: black; 10 | } 11 | 12 | pre .comment, 13 | pre .template_comment, 14 | pre .javadoc, 15 | pre .comment * { 16 | color: #800; 17 | } 18 | 19 | pre .keyword, 20 | pre .method, 21 | pre .list .title, 22 | pre .clojure .built_in, 23 | pre .nginx .title, 24 | pre .tag .title, 25 | pre .setting .value, 26 | pre .winutils, 27 | pre .tex .command, 28 | pre .http .title, 29 | pre .request, 30 | pre .status { 31 | color: #008; 32 | } 33 | 34 | pre .envvar, 35 | pre .tex .special { 36 | color: #660; 37 | } 38 | 39 | pre .string, 40 | pre .tag .value, 41 | pre .cdata, 42 | pre .filter .argument, 43 | pre .attr_selector, 44 | pre .apache .cbracket, 45 | pre .date, 46 | pre .regexp { 47 | color: #080; 48 | } 49 | 50 | pre .sub .identifier, 51 | pre .pi, 52 | pre .tag, 53 | pre .tag .keyword, 54 | pre .decorator, 55 | pre .ini .title, 56 | pre .shebang, 57 | pre .input_number, 58 | pre .hexcolor, 59 | pre .rules .value, 60 | pre .css .value .number, 61 | pre .literal, 62 | pre .symbol, 63 | pre .ruby .symbol .string, 64 | pre .number, 65 | pre .css .function, 66 | pre .clojure .attribute { 67 | color: #066; 68 | } 69 | 70 | pre .class .title, 71 | pre .haskell .type, 72 | pre .smalltalk .class, 73 | pre .javadoctag, 74 | pre .yardoctag, 75 | pre .phpdoc, 76 | pre .typename, 77 | pre .tag .attribute, 78 | pre .doctype, 79 | pre .class .id, 80 | pre .built_in, 81 | pre .setting, 82 | pre .params, 83 | pre .variable, 84 | pre .clojure .title { 85 | color: #606; 86 | } 87 | 88 | pre .css .tag, 89 | pre .rules .property, 90 | pre .pseudo, 91 | pre .subst { 92 | color: #000; 93 | } 94 | 95 | pre .css .class, pre .css .id { 96 | color: #9B703F; 97 | } 98 | 99 | pre .value .important { 100 | color: #ff7700; 101 | font-weight: bold; 102 | } 103 | 104 | pre .rules .keyword { 105 | color: #C5AF75; 106 | } 107 | 108 | pre .annotation, 109 | pre .apache .sqbracket, 110 | pre .nginx .built_in { 111 | color: #9B859D; 112 | } 113 | 114 | pre .preprocessor, 115 | pre .preprocessor * { 116 | color: #444; 117 | } 118 | 119 | pre .tex .formula { 120 | background-color: #EEE; 121 | font-style: italic; 122 | } 123 | 124 | pre .diff .header, 125 | pre .chunk { 126 | color: #808080; 127 | font-weight: bold; 128 | } 129 | 130 | pre .diff .change { 131 | background-color: #BCCFF9; 132 | } 133 | 134 | pre .addition { 135 | background-color: #BAEEBA; 136 | } 137 | 138 | pre .deletion { 139 | background-color: #FFC8BD; 140 | } 141 | 142 | pre .comment .yardoctag { 143 | font-weight: bold; 144 | } 145 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/idea.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Intellij Idea-like styling (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | color: #000; 10 | background: #fff; 11 | } 12 | 13 | pre .subst, 14 | pre .title { 15 | font-weight: normal; 16 | color: #000; 17 | } 18 | 19 | pre .comment, 20 | pre .template_comment, 21 | pre .javadoc, 22 | pre .diff .header { 23 | color: #808080; 24 | font-style: italic; 25 | } 26 | 27 | pre .annotation, 28 | pre .decorator, 29 | pre .preprocessor, 30 | pre .doctype, 31 | pre .pi, 32 | pre .chunk, 33 | pre .shebang, 34 | pre .apache .cbracket, 35 | pre .input_number, 36 | pre .http .title { 37 | color: #808000; 38 | } 39 | 40 | pre .tag, 41 | pre .pi { 42 | background: #efefef; 43 | } 44 | 45 | pre .tag .title, 46 | pre .id, 47 | pre .attr_selector, 48 | pre .pseudo, 49 | pre .literal, 50 | pre .keyword, 51 | pre .hexcolor, 52 | pre .css .function, 53 | pre .ini .title, 54 | pre .css .class, 55 | pre .list .title, 56 | pre .clojure .title, 57 | pre .nginx .title, 58 | pre .tex .command, 59 | pre .request, 60 | pre .status { 61 | font-weight: bold; 62 | color: #000080; 63 | } 64 | 65 | pre .attribute, 66 | pre .rules .keyword, 67 | pre .number, 68 | pre .date, 69 | pre .regexp, 70 | pre .tex .special { 71 | font-weight: bold; 72 | color: #0000ff; 73 | } 74 | 75 | pre .number, 76 | pre .regexp { 77 | font-weight: normal; 78 | } 79 | 80 | pre .string, 81 | pre .value, 82 | pre .filter .argument, 83 | pre .css .function .params, 84 | pre .apache .tag { 85 | color: #008000; 86 | font-weight: bold; 87 | } 88 | 89 | pre .symbol, 90 | pre .ruby .symbol .string, 91 | pre .char, 92 | pre .tex .formula { 93 | color: #000; 94 | background: #d0eded; 95 | font-style: italic; 96 | } 97 | 98 | pre .phpdoc, 99 | pre .yardoctag, 100 | pre .javadoctag { 101 | text-decoration: underline; 102 | } 103 | 104 | pre .variable, 105 | pre .envvar, 106 | pre .apache .sqbracket, 107 | pre .nginx .built_in { 108 | color: #660e7a; 109 | } 110 | 111 | pre .addition { 112 | background: #baeeba; 113 | } 114 | 115 | pre .deletion { 116 | background: #ffc8bd; 117 | } 118 | 119 | pre .diff .change { 120 | background: #bccff9; 121 | } 122 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/ir_black.css: -------------------------------------------------------------------------------- 1 | /* 2 | IR_Black style (c) Vasily Mikhailitchenko 3 | */ 4 | 5 | pre code { 6 | display: block; padding: 0.5em; 7 | background: #000; color: #f8f8f8; 8 | } 9 | 10 | pre .shebang, 11 | pre .comment, 12 | pre .template_comment, 13 | pre .javadoc { 14 | color: #7c7c7c; 15 | } 16 | 17 | pre .keyword, 18 | pre .tag, 19 | pre .tex .command, 20 | pre .request, 21 | pre .status, 22 | pre .clojure .attribute { 23 | color: #96CBFE; 24 | } 25 | 26 | pre .sub .keyword, 27 | pre .method, 28 | pre .list .title, 29 | pre .nginx .title { 30 | color: #FFFFB6; 31 | } 32 | 33 | pre .string, 34 | pre .tag .value, 35 | pre .cdata, 36 | pre .filter .argument, 37 | pre .attr_selector, 38 | pre .apache .cbracket, 39 | pre .date { 40 | color: #A8FF60; 41 | } 42 | 43 | pre .subst { 44 | color: #DAEFA3; 45 | } 46 | 47 | pre .regexp { 48 | color: #E9C062; 49 | } 50 | 51 | pre .title, 52 | pre .sub .identifier, 53 | pre .pi, 54 | pre .decorator, 55 | pre .tex .special, 56 | pre .haskell .type, 57 | pre .constant, 58 | pre .smalltalk .class, 59 | pre .javadoctag, 60 | pre .yardoctag, 61 | pre .phpdoc, 62 | pre .nginx .built_in { 63 | color: #FFFFB6; 64 | } 65 | 66 | pre .symbol, 67 | pre .ruby .symbol .string, 68 | pre .number, 69 | pre .variable, 70 | pre .vbscript, 71 | pre .literal { 72 | color: #C6C5FE; 73 | } 74 | 75 | pre .css .tag { 76 | color: #96CBFE; 77 | } 78 | 79 | pre .css .rules .property, 80 | pre .css .id { 81 | color: #FFFFB6; 82 | } 83 | 84 | pre .css .class { 85 | color: #FFF; 86 | } 87 | 88 | pre .hexcolor { 89 | color: #C6C5FE; 90 | } 91 | 92 | pre .number { 93 | color:#FF73FD; 94 | } 95 | 96 | pre .tex .formula { 97 | opacity: 0.7; 98 | } 99 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/magula.css: -------------------------------------------------------------------------------- 1 | /* 2 | Description: Magula style for highligh.js 3 | Author: Ruslan Keba 4 | Website: http://rukeba.com/ 5 | Version: 1.0 6 | Date: 2009-01-03 7 | Music: Aphex Twin / Xtal 8 | */ 9 | 10 | pre code { 11 | display: block; padding: 0.5em; 12 | background-color: #f4f4f4; 13 | } 14 | 15 | pre code, 16 | pre .ruby .subst, 17 | pre .lisp .title, 18 | pre .clojure .built_in { 19 | color: black; 20 | } 21 | 22 | pre .string, 23 | pre .title, 24 | pre .parent, 25 | pre .tag .value, 26 | pre .rules .value, 27 | pre .rules .value .number, 28 | pre .preprocessor, 29 | pre .ruby .symbol, 30 | pre .ruby .symbol .string, 31 | pre .aggregate, 32 | pre .template_tag, 33 | pre .django .variable, 34 | pre .smalltalk .class, 35 | pre .addition, 36 | pre .flow, 37 | pre .stream, 38 | pre .bash .variable, 39 | pre .apache .cbracket { 40 | color: #050; 41 | } 42 | 43 | pre .comment, 44 | pre .annotation, 45 | pre .template_comment, 46 | pre .diff .header, 47 | pre .chunk { 48 | color: #777; 49 | } 50 | 51 | pre .number, 52 | pre .date, 53 | pre .regexp, 54 | pre .literal, 55 | pre .smalltalk .symbol, 56 | pre .smalltalk .char, 57 | pre .change, 58 | pre .tex .special { 59 | color: #800; 60 | } 61 | 62 | pre .label, 63 | pre .javadoc, 64 | pre .ruby .string, 65 | pre .decorator, 66 | pre .filter .argument, 67 | pre .localvars, 68 | pre .array, 69 | pre .attr_selector, 70 | pre .pseudo, 71 | pre .pi, 72 | pre .doctype, 73 | pre .deletion, 74 | pre .envvar, 75 | pre .shebang, 76 | pre .apache .sqbracket, 77 | pre .nginx .built_in, 78 | pre .tex .formula, 79 | pre .input_number, 80 | pre .clojure .attribute { 81 | color: #00e; 82 | } 83 | 84 | pre .keyword, 85 | pre .id, 86 | pre .phpdoc, 87 | pre .title, 88 | pre .built_in, 89 | pre .aggregate, 90 | pre .smalltalk .class, 91 | pre .winutils, 92 | pre .bash .variable, 93 | pre .apache .tag, 94 | pre .xml .tag, 95 | pre .tex .command, 96 | pre .request, 97 | pre .status { 98 | font-weight: bold; 99 | color: navy; 100 | } 101 | 102 | pre .nginx .built_in { 103 | font-weight: normal; 104 | } 105 | 106 | pre .coffeescript .javascript, 107 | pre .xml .css, 108 | pre .xml .javascript, 109 | pre .xml .vbscript, 110 | pre .tex .formula { 111 | opacity: 0.5; 112 | } 113 | 114 | /* --- */ 115 | pre .apache .tag { 116 | font-weight: bold; 117 | color: blue; 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/monokai.css: -------------------------------------------------------------------------------- 1 | /* 2 | Monokai style - ported by Luigi Maselli - http://grigio.org 3 | */ 4 | 5 | pre code { 6 | display: block; padding: 0.5em; 7 | background: #272822; 8 | } 9 | 10 | pre .tag, 11 | pre .tag .title, 12 | pre .keyword, 13 | pre .literal, 14 | pre .change, 15 | pre .winutils, 16 | pre .flow, 17 | pre .lisp .title, 18 | pre .clojure .built_in, 19 | pre .nginx .title, 20 | pre .tex .special { 21 | color: #F92672; 22 | } 23 | 24 | pre code { 25 | color: #DDD; 26 | } 27 | 28 | pre code .constant { 29 | color: #66D9EF; 30 | } 31 | 32 | pre .class .title { 33 | color: white; 34 | } 35 | 36 | pre .attribute, 37 | pre .symbol, 38 | pre .symbol .string, 39 | pre .value, 40 | pre .regexp { 41 | color: #BF79DB; 42 | } 43 | 44 | pre .tag .value, 45 | pre .string, 46 | pre .ruby .subst, 47 | pre .title, 48 | pre .haskell .type, 49 | pre .preprocessor, 50 | pre .ruby .class .parent, 51 | pre .built_in, 52 | pre .sql .aggregate, 53 | pre .django .template_tag, 54 | pre .django .variable, 55 | pre .smalltalk .class, 56 | pre .javadoc, 57 | pre .django .filter .argument, 58 | pre .smalltalk .localvars, 59 | pre .smalltalk .array, 60 | pre .attr_selector, 61 | pre .pseudo, 62 | pre .addition, 63 | pre .stream, 64 | pre .envvar, 65 | pre .apache .tag, 66 | pre .apache .cbracket, 67 | pre .tex .command, 68 | pre .input_number { 69 | color: #A6E22E; 70 | } 71 | 72 | pre .comment, 73 | pre .java .annotation, 74 | pre .python .decorator, 75 | pre .template_comment, 76 | pre .pi, 77 | pre .doctype, 78 | pre .deletion, 79 | pre .shebang, 80 | pre .apache .sqbracket, 81 | pre .tex .formula { 82 | color: #75715E; 83 | } 84 | 85 | pre .keyword, 86 | pre .literal, 87 | pre .css .id, 88 | pre .phpdoc, 89 | pre .title, 90 | pre .haskell .type, 91 | pre .vbscript .built_in, 92 | pre .sql .aggregate, 93 | pre .rsl .built_in, 94 | pre .smalltalk .class, 95 | pre .diff .header, 96 | pre .chunk, 97 | pre .winutils, 98 | pre .bash .variable, 99 | pre .apache .tag, 100 | pre .tex .special, 101 | pre .request, 102 | pre .status { 103 | font-weight: bold; 104 | } 105 | 106 | pre .coffeescript .javascript, 107 | pre .xml .css, 108 | pre .xml .javascript, 109 | pre .xml .vbscript, 110 | pre .tex .formula { 111 | opacity: 0.5; 112 | } 113 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/pojoaque.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Pojoaque Style by Jason Tate 4 | http://web-cms-designs.com/ftopict-10-pojoaque-style-for-highlight-js-code-highlighter.html 5 | Based on Solarized Style from http://ethanschoonover.com/solarized 6 | 7 | */ 8 | 9 | pre code { 10 | display: block; padding: 0.5em; 11 | color: #DCCF8F; 12 | background-color: #181914; /* adam-p: removed background image */ 13 | } 14 | 15 | pre .comment, 16 | pre .template_comment, 17 | pre .diff .header, 18 | pre .doctype, 19 | pre .lisp .string, 20 | pre .javadoc { 21 | color: #586e75; 22 | font-style: italic; 23 | } 24 | 25 | pre .keyword, 26 | pre .css .rule .keyword, 27 | pre .winutils, 28 | pre .javascript .title, 29 | pre .method, 30 | pre .addition, 31 | pre .css .tag, 32 | pre .clojure .title, 33 | pre .nginx .title { 34 | color: #B64926; 35 | } 36 | 37 | pre .number, 38 | pre .command, 39 | pre .string, 40 | pre .tag .value, 41 | pre .phpdoc, 42 | pre .tex .formula, 43 | pre .regexp, 44 | pre .hexcolor { 45 | color: #468966; 46 | } 47 | 48 | pre .title, 49 | pre .localvars, 50 | pre .function .title, 51 | pre .chunk, 52 | pre .decorator, 53 | pre .built_in, 54 | pre .lisp .title, 55 | pre .clojure .built_in, 56 | pre .identifier, 57 | pre .id { 58 | color: #FFB03B; 59 | } 60 | 61 | pre .attribute, 62 | pre .variable, 63 | pre .lisp .body, 64 | pre .smalltalk .number, 65 | pre .constant, 66 | pre .class .title, 67 | pre .parent, 68 | pre .haskell .type { 69 | color: #b58900; 70 | } 71 | 72 | pre .css .attribute { 73 | color: #b89859; 74 | } 75 | 76 | pre .css .number,pre .css .hexcolor{ 77 | color: #DCCF8F; 78 | } 79 | 80 | pre .css .class { 81 | color: #d3a60c; 82 | } 83 | 84 | pre .preprocessor, 85 | pre .pi, 86 | pre .shebang, 87 | pre .symbol, 88 | pre .symbol .string, 89 | pre .diff .change, 90 | pre .special, 91 | pre .attr_selector, 92 | pre .important, 93 | pre .subst, 94 | pre .cdata { 95 | color: #cb4b16; 96 | } 97 | 98 | pre .deletion { 99 | color: #dc322f; 100 | } 101 | 102 | pre .tex .formula { 103 | background: #073642; 104 | } 105 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/rainbow.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Style with support for rainbow parens 4 | 5 | */ 6 | 7 | /* adam-p: commented these out -- the first line causes an error in Chrome, 8 | and the selection style doesn't seem to be working quite right anyway. 9 | pre ::-moz-selection{ background: #FF5E99; color:#fff; text-shadow: none; } 10 | pre ::selection { background:#FF5E99; color:#fff; text-shadow: none; } 11 | */ 12 | 13 | pre code { 14 | display: block; padding: 0.5em; 15 | background: #474949; color: #D1D9E1; 16 | } 17 | 18 | 19 | pre .body, 20 | pre .collection { 21 | color: #D1D9E1; 22 | } 23 | 24 | pre .comment, 25 | pre .template_comment, 26 | pre .diff .header, 27 | pre .doctype, 28 | pre .lisp .string, 29 | pre .javadoc { 30 | color: #969896; 31 | font-style: italic; 32 | } 33 | 34 | pre .keyword, 35 | pre .clojure .attribute, 36 | pre .winutils, 37 | pre .javascript .title, 38 | pre .addition, 39 | pre .css .tag { 40 | color: #cc99cc; 41 | } 42 | 43 | pre .number { color: #f99157; } 44 | 45 | pre .command, 46 | pre .string, 47 | pre .tag .value, 48 | pre .phpdoc, 49 | pre .tex .formula, 50 | pre .regexp, 51 | pre .hexcolor { 52 | color: #8abeb7; 53 | } 54 | 55 | pre .title, 56 | pre .localvars, 57 | pre .function .title, 58 | pre .chunk, 59 | pre .decorator, 60 | pre .built_in, 61 | pre .lisp .title, 62 | pre .identifier 63 | { 64 | color: #b5bd68; 65 | } 66 | 67 | pre .class .keyword 68 | { 69 | color: #f2777a; 70 | } 71 | 72 | pre .variable, 73 | pre .lisp .body, 74 | pre .smalltalk .number, 75 | pre .constant, 76 | pre .class .title, 77 | pre .parent, 78 | pre .haskell .label, 79 | pre .id, 80 | pre .lisp .title, 81 | pre .clojure .title .built_in { 82 | color: #ffcc66; 83 | } 84 | 85 | pre .tag .title, 86 | pre .rules .property, 87 | pre .django .tag .keyword, 88 | pre .clojure .title .built_in { 89 | font-weight: bold; 90 | } 91 | 92 | pre .attribute, 93 | pre .clojure .title { 94 | color: #81a2be; 95 | } 96 | 97 | pre .preprocessor, 98 | pre .pi, 99 | pre .shebang, 100 | pre .symbol, 101 | pre .symbol .string, 102 | pre .diff .change, 103 | pre .special, 104 | pre .attr_selector, 105 | pre .important, 106 | pre .subst, 107 | pre .cdata { 108 | color: #f99157; 109 | } 110 | 111 | pre .deletion { 112 | color: #dc322f; 113 | } 114 | 115 | pre .tex .formula { 116 | background: #eee8d5; 117 | } 118 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/school_book.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | School Book style from goldblog.com.ua (c) Zaripov Yura 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 15px 0.5em 0.5em 30px; 9 | font-size: 11px !important; 10 | line-height:16px !important; 11 | } 12 | 13 | pre{ 14 | background-color:#f6f6ae; /* adam-p: removed background image */ 15 | border-top: solid 2px #d2e8b9; 16 | border-bottom: solid 1px #d2e8b9; 17 | } 18 | 19 | pre .keyword, 20 | pre .literal, 21 | pre .change, 22 | pre .winutils, 23 | pre .flow, 24 | pre .lisp .title, 25 | pre .clojure .built_in, 26 | pre .nginx .title, 27 | pre .tex .special { 28 | color:#005599; 29 | font-weight:bold; 30 | } 31 | 32 | pre code, 33 | pre .ruby .subst, 34 | pre .tag .keyword { 35 | color: #3E5915; 36 | } 37 | 38 | pre .string, 39 | pre .title, 40 | pre .haskell .type, 41 | pre .tag .value, 42 | pre .css .rules .value, 43 | pre .preprocessor, 44 | pre .ruby .symbol, 45 | pre .ruby .symbol .string, 46 | pre .ruby .class .parent, 47 | pre .built_in, 48 | pre .sql .aggregate, 49 | pre .django .template_tag, 50 | pre .django .variable, 51 | pre .smalltalk .class, 52 | pre .javadoc, 53 | pre .ruby .string, 54 | pre .django .filter .argument, 55 | pre .smalltalk .localvars, 56 | pre .smalltalk .array, 57 | pre .attr_selector, 58 | pre .pseudo, 59 | pre .addition, 60 | pre .stream, 61 | pre .envvar, 62 | pre .apache .tag, 63 | pre .apache .cbracket, 64 | pre .nginx .built_in, 65 | pre .tex .command { 66 | color: #2C009F; 67 | } 68 | 69 | pre .comment, 70 | pre .java .annotation, 71 | pre .python .decorator, 72 | pre .template_comment, 73 | pre .pi, 74 | pre .doctype, 75 | pre .deletion, 76 | pre .shebang, 77 | pre .apache .sqbracket { 78 | color: #E60415; 79 | } 80 | 81 | pre .keyword, 82 | pre .literal, 83 | pre .css .id, 84 | pre .phpdoc, 85 | pre .title, 86 | pre .haskell .type, 87 | pre .vbscript .built_in, 88 | pre .sql .aggregate, 89 | pre .rsl .built_in, 90 | pre .smalltalk .class, 91 | pre .xml .tag .title, 92 | pre .diff .header, 93 | pre .chunk, 94 | pre .winutils, 95 | pre .bash .variable, 96 | pre .apache .tag, 97 | pre .tex .command, 98 | pre .request, 99 | pre .status { 100 | font-weight: bold; 101 | } 102 | 103 | pre .coffeescript .javascript, 104 | pre .xml .css, 105 | pre .xml .javascript, 106 | pre .xml .vbscript, 107 | pre .tex .formula { 108 | opacity: 0.5; 109 | } 110 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/solarized_dark.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #002b36; color: #839496; 10 | } 11 | 12 | pre .comment, 13 | pre .template_comment, 14 | pre .diff .header, 15 | pre .doctype, 16 | pre .pi, 17 | pre .lisp .string, 18 | pre .javadoc { 19 | color: #586e75; 20 | font-style: italic; 21 | } 22 | 23 | pre .keyword, 24 | pre .winutils, 25 | pre .method, 26 | pre .addition, 27 | pre .css .tag, 28 | pre .request, 29 | pre .status, 30 | pre .nginx .title { 31 | color: #859900; 32 | } 33 | 34 | pre .number, 35 | pre .command, 36 | pre .string, 37 | pre .tag .value, 38 | pre .phpdoc, 39 | pre .tex .formula, 40 | pre .regexp, 41 | pre .hexcolor { 42 | color: #2aa198; 43 | } 44 | 45 | pre .title, 46 | pre .localvars, 47 | pre .chunk, 48 | pre .decorator, 49 | pre .built_in, 50 | pre .identifier, 51 | pre .vhdl .literal, 52 | pre .id { 53 | color: #268bd2; 54 | } 55 | 56 | pre .attribute, 57 | pre .variable, 58 | pre .lisp .body, 59 | pre .smalltalk .number, 60 | pre .constant, 61 | pre .class .title, 62 | pre .parent, 63 | pre .haskell .type { 64 | color: #b58900; 65 | } 66 | 67 | pre .preprocessor, 68 | pre .preprocessor .keyword, 69 | pre .shebang, 70 | pre .symbol, 71 | pre .symbol .string, 72 | pre .diff .change, 73 | pre .special, 74 | pre .attr_selector, 75 | pre .important, 76 | pre .subst, 77 | pre .cdata, 78 | pre .clojure .title { 79 | color: #cb4b16; 80 | } 81 | 82 | pre .deletion { 83 | color: #dc322f; 84 | } 85 | 86 | pre .tex .formula { 87 | background: #073642; 88 | } 89 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/solarized_light.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #fdf6e3; color: #657b83; 10 | } 11 | 12 | pre .comment, 13 | pre .template_comment, 14 | pre .diff .header, 15 | pre .doctype, 16 | pre .pi, 17 | pre .lisp .string, 18 | pre .javadoc { 19 | color: #93a1a1; 20 | font-style: italic; 21 | } 22 | 23 | pre .keyword, 24 | pre .winutils, 25 | pre .method, 26 | pre .addition, 27 | pre .css .tag, 28 | pre .request, 29 | pre .status, 30 | pre .nginx .title { 31 | color: #859900; 32 | } 33 | 34 | pre .number, 35 | pre .command, 36 | pre .string, 37 | pre .tag .value, 38 | pre .phpdoc, 39 | pre .tex .formula, 40 | pre .regexp, 41 | pre .hexcolor { 42 | color: #2aa198; 43 | } 44 | 45 | pre .title, 46 | pre .localvars, 47 | pre .chunk, 48 | pre .decorator, 49 | pre .built_in, 50 | pre .identifier, 51 | pre .vhdl .literal, 52 | pre .id { 53 | color: #268bd2; 54 | } 55 | 56 | pre .attribute, 57 | pre .variable, 58 | pre .lisp .body, 59 | pre .smalltalk .number, 60 | pre .constant, 61 | pre .class .title, 62 | pre .parent, 63 | pre .haskell .type { 64 | color: #b58900; 65 | } 66 | 67 | pre .preprocessor, 68 | pre .preprocessor .keyword, 69 | pre .shebang, 70 | pre .symbol, 71 | pre .symbol .string, 72 | pre .diff .change, 73 | pre .special, 74 | pre .attr_selector, 75 | pre .important, 76 | pre .subst, 77 | pre .cdata, 78 | pre .clojure .title { 79 | color: #cb4b16; 80 | } 81 | 82 | pre .deletion { 83 | color: #dc322f; 84 | } 85 | 86 | pre .tex .formula { 87 | background: #eee8d5; 88 | } 89 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/styles.json: -------------------------------------------------------------------------------- 1 | { 2 | "Default (Github)": "github.css", 3 | "Arta": "arta.css", 4 | "Ascetic": "ascetic.css", 5 | "Brown Paper": "brown_paper.css", 6 | "Dark": "dark.css", 7 | "Highlight.js Default": "default.css", 8 | "Far": "far.css", 9 | "Googlecode": "googlecode.css", 10 | "Idea": "idea.css", 11 | "IR Black": "ir_black.css", 12 | "Magula": "magula.css", 13 | "Monokai": "monokai.css", 14 | "Pojoaque": "pojoaque.css", 15 | "Rainbow": "rainbow.css", 16 | "School Book": "school_book.css", 17 | "Solarized Dark": "solarized_dark.css", 18 | "Solarized Light": "solarized_light.css", 19 | "Sunburst": "sunburst.css", 20 | "Tomorrow Night Blue": "tomorrow-night-blue.css", 21 | "Tomorrow Night Bright": "tomorrow-night-bright.css", 22 | "Tomorrow Night Eighties": "tomorrow-night-eighties.css", 23 | "Tomorrow Night": "tomorrow-night.css", 24 | "Tomorrow": "tomorrow.css", 25 | "VS": "vs.css", 26 | "Xcode": "xcode.css", 27 | "Zenburn": "zenburn.css" 28 | } 29 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/sunburst.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Sunburst-like style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #000; color: #f8f8f8; 10 | } 11 | 12 | pre .comment, 13 | pre .template_comment, 14 | pre .javadoc { 15 | color: #aeaeae; 16 | font-style: italic; 17 | } 18 | 19 | pre .keyword, 20 | pre .ruby .function .keyword, 21 | pre .request, 22 | pre .status, 23 | pre .nginx .title { 24 | color: #E28964; 25 | } 26 | 27 | pre .function .keyword, 28 | pre .sub .keyword, 29 | pre .method, 30 | pre .list .title { 31 | color: #99CF50; 32 | } 33 | 34 | pre .string, 35 | pre .tag .value, 36 | pre .cdata, 37 | pre .filter .argument, 38 | pre .attr_selector, 39 | pre .apache .cbracket, 40 | pre .date, 41 | pre .tex .command { 42 | color: #65B042; 43 | } 44 | 45 | pre .subst { 46 | color: #DAEFA3; 47 | } 48 | 49 | pre .regexp { 50 | color: #E9C062; 51 | } 52 | 53 | pre .title, 54 | pre .sub .identifier, 55 | pre .pi, 56 | pre .tag, 57 | pre .tag .keyword, 58 | pre .decorator, 59 | pre .shebang, 60 | pre .input_number { 61 | color: #89BDFF; 62 | } 63 | 64 | pre .class .title, 65 | pre .haskell .type, 66 | pre .smalltalk .class, 67 | pre .javadoctag, 68 | pre .yardoctag, 69 | pre .phpdoc { 70 | text-decoration: underline; 71 | } 72 | 73 | pre .symbol, 74 | pre .ruby .symbol .string, 75 | pre .number { 76 | color: #3387CC; 77 | } 78 | 79 | pre .params, 80 | pre .variable, 81 | pre .clojure .attribute { 82 | color: #3E87E3; 83 | } 84 | 85 | pre .css .tag, 86 | pre .rules .property, 87 | pre .pseudo, 88 | pre .tex .special { 89 | color: #CDA869; 90 | } 91 | 92 | pre .css .class { 93 | color: #9B703F; 94 | } 95 | 96 | pre .rules .keyword { 97 | color: #C5AF75; 98 | } 99 | 100 | pre .rules .value { 101 | color: #CF6A4C; 102 | } 103 | 104 | pre .css .id { 105 | color: #8B98AB; 106 | } 107 | 108 | pre .annotation, 109 | pre .apache .sqbracket, 110 | pre .nginx .built_in { 111 | color: #9B859D; 112 | } 113 | 114 | pre .preprocessor { 115 | color: #8996A8; 116 | } 117 | 118 | pre .hexcolor, 119 | pre .css .value .number { 120 | color: #DD7B3B; 121 | } 122 | 123 | pre .css .function { 124 | color: #DAD085; 125 | } 126 | 127 | pre .diff .header, 128 | pre .chunk, 129 | pre .tex .formula { 130 | background-color: #0E2231; 131 | color: #F8F8F8; 132 | font-style: italic; 133 | } 134 | 135 | pre .diff .change { 136 | background-color: #4A410D; 137 | color: #F8F8F8; 138 | } 139 | 140 | pre .addition { 141 | background-color: #253B22; 142 | color: #F8F8F8; 143 | } 144 | 145 | pre .deletion { 146 | background-color: #420E09; 147 | color: #F8F8F8; 148 | } 149 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/tomorrow-night-blue.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Blue Theme */ 2 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 3 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 4 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 5 | .tomorrow-comment, pre .comment, pre .title { 6 | color: #7285b7; 7 | } 8 | 9 | .tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { 10 | color: #ff9da4; 11 | } 12 | 13 | .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { 14 | color: #ffc58f; 15 | } 16 | 17 | .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { 18 | color: #ffeead; 19 | } 20 | 21 | .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { 22 | color: #d1f1a9; 23 | } 24 | 25 | .tomorrow-aqua, pre .css .hexcolor { 26 | color: #99ffff; 27 | } 28 | 29 | .tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { 30 | color: #bbdaff; 31 | } 32 | 33 | .tomorrow-purple, pre .keyword, pre .javascript .function { 34 | color: #ebbbff; 35 | } 36 | 37 | pre code { 38 | display: block; 39 | background: #002451; 40 | color: white; 41 | padding: 0.5em; 42 | } 43 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/tomorrow-night-bright.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Bright Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 4 | .tomorrow-comment, pre .comment, pre .title { 5 | color: #969896; 6 | } 7 | 8 | .tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { 9 | color: #d54e53; 10 | } 11 | 12 | .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { 13 | color: #e78c45; 14 | } 15 | 16 | .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { 17 | color: #e7c547; 18 | } 19 | 20 | .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { 21 | color: #b9ca4a; 22 | } 23 | 24 | .tomorrow-aqua, pre .css .hexcolor { 25 | color: #70c0b1; 26 | } 27 | 28 | .tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { 29 | color: #7aa6da; 30 | } 31 | 32 | .tomorrow-purple, pre .keyword, pre .javascript .function { 33 | color: #c397d8; 34 | } 35 | 36 | pre code { 37 | display: block; 38 | background: black; 39 | color: #eaeaea; 40 | padding: 0.5em; 41 | } 42 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/tomorrow-night-eighties.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Eighties Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 4 | .tomorrow-comment, pre .comment, pre .title { 5 | color: #999999; 6 | } 7 | 8 | .tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { 9 | color: #f2777a; 10 | } 11 | 12 | .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { 13 | color: #f99157; 14 | } 15 | 16 | .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { 17 | color: #ffcc66; 18 | } 19 | 20 | .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { 21 | color: #99cc99; 22 | } 23 | 24 | .tomorrow-aqua, pre .css .hexcolor { 25 | color: #66cccc; 26 | } 27 | 28 | .tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { 29 | color: #6699cc; 30 | } 31 | 32 | .tomorrow-purple, pre .keyword, pre .javascript .function { 33 | color: #cc99cc; 34 | } 35 | 36 | pre code { 37 | display: block; 38 | background: #2d2d2d; 39 | color: #cccccc; 40 | padding: 0.5em; 41 | } 42 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/tomorrow-night.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Theme */ 2 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 3 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 4 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 5 | .tomorrow-comment, pre .comment, pre .title { 6 | color: #969896; 7 | } 8 | 9 | .tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { 10 | color: #cc6666; 11 | } 12 | 13 | .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { 14 | color: #de935f; 15 | } 16 | 17 | .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { 18 | color: #f0c674; 19 | } 20 | 21 | .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { 22 | color: #b5bd68; 23 | } 24 | 25 | .tomorrow-aqua, pre .css .hexcolor { 26 | color: #8abeb7; 27 | } 28 | 29 | .tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { 30 | color: #81a2be; 31 | } 32 | 33 | .tomorrow-purple, pre .keyword, pre .javascript .function { 34 | color: #b294bb; 35 | } 36 | 37 | pre code { 38 | display: block; 39 | background: #1d1f21; 40 | color: #c5c8c6; 41 | padding: 0.5em; 42 | } 43 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/tomorrow.css: -------------------------------------------------------------------------------- 1 | /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ 2 | .tomorrow-comment, pre .comment, pre .title { 3 | color: #8e908c; 4 | } 5 | 6 | .tomorrow-red, pre .variable, pre .attribute, pre .tag, pre .regexp, pre .ruby .constant, pre .xml .tag .title, pre .xml .pi, pre .xml .doctype, pre .html .doctype, pre .css .id, pre .css .class, pre .css .pseudo { 7 | color: #c82829; 8 | } 9 | 10 | .tomorrow-orange, pre .number, pre .preprocessor, pre .built_in, pre .literal, pre .params, pre .constant { 11 | color: #f5871f; 12 | } 13 | 14 | .tomorrow-yellow, pre .class, pre .ruby .class .title, pre .css .rules .attribute { 15 | color: #eab700; 16 | } 17 | 18 | .tomorrow-green, pre .string, pre .value, pre .inheritance, pre .header, pre .ruby .symbol, pre .xml .cdata { 19 | color: #718c00; 20 | } 21 | 22 | .tomorrow-aqua, pre .css .hexcolor { 23 | color: #3e999f; 24 | } 25 | 26 | .tomorrow-blue, pre .function, pre .python .decorator, pre .python .title, pre .ruby .function .title, pre .ruby .title .keyword, pre .perl .sub, pre .javascript .title, pre .coffeescript .title { 27 | color: #4271ae; 28 | } 29 | 30 | .tomorrow-purple, pre .keyword, pre .javascript .function { 31 | color: #8959a8; 32 | } 33 | 34 | pre code { 35 | display: block; 36 | background: white; 37 | color: #4d4d4c; 38 | padding: 0.5em; 39 | } 40 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/vs.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Visual Studio-like style based on original C# coloring by Jason Diamond 4 | 5 | */ 6 | pre code { 7 | display: block; padding: 0.5em; 8 | } 9 | 10 | pre .comment, 11 | pre .annotation, 12 | pre .template_comment, 13 | pre .diff .header, 14 | pre .chunk, 15 | pre .apache .cbracket { 16 | color: rgb(0, 128, 0); 17 | } 18 | 19 | pre .keyword, 20 | pre .id, 21 | pre .built_in, 22 | pre .smalltalk .class, 23 | pre .winutils, 24 | pre .bash .variable, 25 | pre .tex .command, 26 | pre .request, 27 | pre .status, 28 | pre .nginx .title, 29 | pre .xml .tag, 30 | pre .xml .tag .value { 31 | color: rgb(0, 0, 255); 32 | } 33 | 34 | pre .string, 35 | pre .title, 36 | pre .parent, 37 | pre .tag .value, 38 | pre .rules .value, 39 | pre .rules .value .number, 40 | pre .ruby .symbol, 41 | pre .ruby .symbol .string, 42 | pre .aggregate, 43 | pre .template_tag, 44 | pre .django .variable, 45 | pre .addition, 46 | pre .flow, 47 | pre .stream, 48 | pre .apache .tag, 49 | pre .date, 50 | pre .tex .formula { 51 | color: rgb(163, 21, 21); 52 | } 53 | 54 | pre .ruby .string, 55 | pre .decorator, 56 | pre .filter .argument, 57 | pre .localvars, 58 | pre .array, 59 | pre .attr_selector, 60 | pre .pseudo, 61 | pre .pi, 62 | pre .doctype, 63 | pre .deletion, 64 | pre .envvar, 65 | pre .shebang, 66 | pre .preprocessor, 67 | pre .userType, 68 | pre .apache .sqbracket, 69 | pre .nginx .built_in, 70 | pre .tex .special, 71 | pre .input_number { 72 | color: rgb(43, 145, 175); 73 | } 74 | 75 | pre .phpdoc, 76 | pre .javadoc, 77 | pre .xmlDocTag { 78 | color: rgb(128, 128, 128); 79 | } 80 | 81 | pre .vhdl .typename { font-weight: bold; } 82 | pre .vhdl .string { color: #666666; } 83 | pre .vhdl .literal { color: rgb(163, 21, 21); } 84 | pre .vhdl .attribute { color: #00B0E8; } 85 | 86 | pre .xml .attribute { color: rgb(255, 0, 0); } 87 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/xcode.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | XCode style (c) Angel Garcia 4 | 5 | */ 6 | 7 | pre code { 8 | display: block; padding: 0.5em; 9 | background: #fff; color: black; 10 | } 11 | 12 | pre .comment, 13 | pre .template_comment, 14 | pre .javadoc, 15 | pre .comment * { 16 | color: rgb(0,106,0); 17 | } 18 | 19 | pre .keyword, 20 | pre .literal, 21 | pre .nginx .title { 22 | color: rgb(170,13,145); 23 | } 24 | pre .method, 25 | pre .list .title, 26 | pre .tag .title, 27 | pre .setting .value, 28 | pre .winutils, 29 | pre .tex .command, 30 | pre .http .title, 31 | pre .request, 32 | pre .status { 33 | color: #008; 34 | } 35 | 36 | pre .envvar, 37 | pre .tex .special { 38 | color: #660; 39 | } 40 | 41 | pre .string { 42 | color: rgb(196,26,22); 43 | } 44 | pre .tag .value, 45 | pre .cdata, 46 | pre .filter .argument, 47 | pre .attr_selector, 48 | pre .apache .cbracket, 49 | pre .date, 50 | pre .regexp { 51 | color: #080; 52 | } 53 | 54 | pre .sub .identifier, 55 | pre .pi, 56 | pre .tag, 57 | pre .tag .keyword, 58 | pre .decorator, 59 | pre .ini .title, 60 | pre .shebang, 61 | pre .input_number, 62 | pre .hexcolor, 63 | pre .rules .value, 64 | pre .css .value .number, 65 | pre .symbol, 66 | pre .symbol .string, 67 | pre .number, 68 | pre .css .function, 69 | pre .clojure .title, 70 | pre .clojure .built_in { 71 | color: rgb(28,0,207); 72 | } 73 | 74 | pre .class .title, 75 | pre .haskell .type, 76 | pre .smalltalk .class, 77 | pre .javadoctag, 78 | pre .yardoctag, 79 | pre .phpdoc, 80 | pre .typename, 81 | pre .tag .attribute, 82 | pre .doctype, 83 | pre .class .id, 84 | pre .built_in, 85 | pre .setting, 86 | pre .params, 87 | pre .clojure .attribute { 88 | color: rgb(92,38,153); 89 | } 90 | 91 | pre .variable { 92 | color: rgb(63,110,116); 93 | } 94 | pre .css .tag, 95 | pre .rules .property, 96 | pre .pseudo, 97 | pre .subst { 98 | color: #000; 99 | } 100 | 101 | pre .css .class, pre .css .id { 102 | color: #9B703F; 103 | } 104 | 105 | pre .value .important { 106 | color: #ff7700; 107 | font-weight: bold; 108 | } 109 | 110 | pre .rules .keyword { 111 | color: #C5AF75; 112 | } 113 | 114 | pre .annotation, 115 | pre .apache .sqbracket, 116 | pre .nginx .built_in { 117 | color: #9B859D; 118 | } 119 | 120 | pre .preprocessor, 121 | pre .preprocessor * { 122 | color: rgb(100,56,32); 123 | } 124 | 125 | pre .tex .formula { 126 | background-color: #EEE; 127 | font-style: italic; 128 | } 129 | 130 | pre .diff .header, 131 | pre .chunk { 132 | color: #808080; 133 | font-weight: bold; 134 | } 135 | 136 | pre .diff .change { 137 | background-color: #BCCFF9; 138 | } 139 | 140 | pre .addition { 141 | background-color: #BAEEBA; 142 | } 143 | 144 | pre .deletion { 145 | background-color: #FFC8BD; 146 | } 147 | 148 | pre .comment .yardoctag { 149 | font-weight: bold; 150 | } 151 | 152 | pre .method .id { 153 | color: #000; 154 | } 155 | -------------------------------------------------------------------------------- /src/common/highlightjs/styles/zenburn.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Zenburn style from voldmar.ru (c) Vladimir Epifanov 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | pre code { 9 | display: block; padding: 0.5em; 10 | background: #3F3F3F; 11 | color: #DCDCDC; 12 | } 13 | 14 | pre .keyword, 15 | pre .tag, 16 | pre .css .class, 17 | pre .css .id, 18 | pre .lisp .title, 19 | pre .nginx .title, 20 | pre .request, 21 | pre .status, 22 | pre .clojure .attribute { 23 | color: #E3CEAB; 24 | } 25 | 26 | pre .django .template_tag, 27 | pre .django .variable, 28 | pre .django .filter .argument { 29 | color: #DCDCDC; 30 | } 31 | 32 | pre .number, 33 | pre .date { 34 | color: #8CD0D3; 35 | } 36 | 37 | pre .dos .envvar, 38 | pre .dos .stream, 39 | pre .variable, 40 | pre .apache .sqbracket { 41 | color: #EFDCBC; 42 | } 43 | 44 | pre .dos .flow, 45 | pre .diff .change, 46 | pre .python .exception, 47 | pre .python .built_in, 48 | pre .literal, 49 | pre .tex .special { 50 | color: #EFEFAF; 51 | } 52 | 53 | pre .diff .chunk, 54 | pre .ruby .subst { 55 | color: #8F8F8F; 56 | } 57 | 58 | pre .dos .keyword, 59 | pre .python .decorator, 60 | pre .title, 61 | pre .haskell .type, 62 | pre .diff .header, 63 | pre .ruby .class .parent, 64 | pre .apache .tag, 65 | pre .nginx .built_in, 66 | pre .tex .command, 67 | pre .input_number { 68 | color: #efef8f; 69 | } 70 | 71 | pre .dos .winutils, 72 | pre .ruby .symbol, 73 | pre .ruby .symbol .string, 74 | pre .ruby .string { 75 | color: #DCA3A3; 76 | } 77 | 78 | pre .diff .deletion, 79 | pre .string, 80 | pre .tag .value, 81 | pre .preprocessor, 82 | pre .built_in, 83 | pre .sql .aggregate, 84 | pre .javadoc, 85 | pre .smalltalk .class, 86 | pre .smalltalk .localvars, 87 | pre .smalltalk .array, 88 | pre .css .rules .value, 89 | pre .attr_selector, 90 | pre .pseudo, 91 | pre .apache .cbracket, 92 | pre .tex .formula { 93 | color: #CC9393; 94 | } 95 | 96 | pre .shebang, 97 | pre .diff .addition, 98 | pre .comment, 99 | pre .java .annotation, 100 | pre .template_comment, 101 | pre .pi, 102 | pre .doctype { 103 | color: #7F9F7F; 104 | } 105 | 106 | pre .coffeescript .javascript, 107 | pre .xml .css, 108 | pre .xml .javascript, 109 | pre .xml .vbscript, 110 | pre .tex .formula { 111 | opacity: 0.5; 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/common/images/gary-arthur-donate-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/gary-arthur-donate-1.png -------------------------------------------------------------------------------- /src/common/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon128.png -------------------------------------------------------------------------------- /src/common/images/icon16-bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon16-bw.png -------------------------------------------------------------------------------- /src/common/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon16.png -------------------------------------------------------------------------------- /src/common/images/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon19.png -------------------------------------------------------------------------------- /src/common/images/icon24-bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon24-bw.png -------------------------------------------------------------------------------- /src/common/images/icon24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon24.png -------------------------------------------------------------------------------- /src/common/images/icon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon32.png -------------------------------------------------------------------------------- /src/common/images/icon38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon38.png -------------------------------------------------------------------------------- /src/common/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon48.png -------------------------------------------------------------------------------- /src/common/images/icon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/icon512.png -------------------------------------------------------------------------------- /src/common/images/markdown-bw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/markdown-bw.png -------------------------------------------------------------------------------- /src/common/images/markdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jlegewie/markdown-here/8b97a0b83594864fb8a05b165c955e44fd678840/src/common/images/markdown.png -------------------------------------------------------------------------------- /src/common/jsHtmlToText.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Google Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | HTML decoding functionality provided by: http://code.google.com/p/google-trekker/ 17 | */ 18 | 19 | /* 20 | adam-p: modified to be a module 21 | */ 22 | 23 | ;(function() { 24 | 25 | 26 | function htmlToText(html, extensions) { 27 | var text = html, i; 28 | 29 | if (extensions && extensions['preprocessing']) 30 | text = extensions['preprocessing'](text); 31 | 32 | text = text 33 | // Remove line breaks 34 | .replace(/(?:\n|\r\n|\r)/ig, " ") 35 | // Remove content in script tags. 36 | .replace(/<\s*script[^>]*>[\s\S]*?<\/script>/mig, "") 37 | // Remove content in style tags. 38 | .replace(/<\s*style[^>]*>[\s\S]*?<\/style>/mig, "") 39 | // Remove content in comments. 40 | .replace(//mig, "") 41 | // Remove !DOCTYPE 42 | .replace(//ig, ""); 43 | 44 | /* I scanned http://en.wikipedia.org/wiki/HTML_element for all html tags. 45 | I put those tags that should affect plain text formatting in two categories: 46 | those that should be replaced with two newlines and those that should be 47 | replaced with one newline. */ 48 | 49 | if (extensions && extensions['tagreplacement']) 50 | text = extensions['tagreplacement'](text); 51 | 52 | var doubleNewlineTags = ['p', 'h[1-6]', 'dl', 'dt', 'dd', 'ol', 'ul', 53 | 'dir', 'address', 'blockquote', 'center', 'div', 'hr', 'pre', 'form', 54 | 'textarea', 'table']; 55 | 56 | var singleNewlineTags = ['li', 'del', 'ins', 'fieldset', 'legend', 57 | 'tr', 'th', 'caption', 'thead', 'tbody', 'tfoot']; 58 | 59 | for (i = 0; i < doubleNewlineTags.length; i++) { 60 | var r = RegExp(']*>', 'ig'); 61 | text = text.replace(r, '\n\n'); 62 | } 63 | 64 | for (i = 0; i < singleNewlineTags.length; i++) { 65 | var r = RegExp('<\\s*' + singleNewlineTags[i] + '[^>]*>', 'ig'); 66 | text = text.replace(r, '\n'); 67 | } 68 | 69 | // Replace
and
with a single newline 70 | text = text.replace(/<\s*br[^>]*\/?\s*>/ig, '\n'); 71 | 72 | text = text 73 | // Remove all remaining tags. 74 | .replace(/(<([^>]+)>)/ig,"") 75 | // Make sure there are never more than two 76 | // consecutive linebreaks. 77 | .replace(/\n{2,}/g,"\n\n") 78 | // Remove newlines at the beginning of the text. 79 | .replace(/^\n+/,"") 80 | // Remove newlines at the end of the text. 81 | .replace(/\n+$/,"") 82 | // Decode HTML entities. 83 | .replace(/&([^;]+);/g, decodeHtmlEntity); 84 | 85 | /* adam-p: make trailing whitespace stripping optional */ 86 | 87 | if (!extensions || !extensions['allowTrailingWhitespace']) { 88 | text = text 89 | // Trim rightmost whitespaces for all lines 90 | .replace(/([^\n\S]+)\n/g,"\n") 91 | .replace(/([^\n\S]+)$/,""); 92 | } 93 | 94 | if (extensions && extensions['postprocessing']) 95 | text = extensions['postprocessing'](text); 96 | 97 | return text; 98 | } 99 | 100 | function decodeHtmlEntity(m, n) { 101 | // Determine the character code of the entity. Range is 0 to 65535 102 | // (characters in JavaScript are Unicode, and entities can represent 103 | // Unicode characters). 104 | var code; 105 | 106 | // Try to parse as numeric entity. This is done before named entities for 107 | // speed because associative array lookup in many JavaScript implementations 108 | // is a linear search. 109 | if (n.substr(0, 1) == '#') { 110 | // Try to parse as numeric entity 111 | if (n.substr(1, 1) == 'x') { 112 | // Try to parse as hexadecimal 113 | code = parseInt(n.substr(2), 16); 114 | } else { 115 | // Try to parse as decimal 116 | code = parseInt(n.substr(1), 10); 117 | } 118 | } else { 119 | // Try to parse as named entity 120 | code = ENTITIES_MAP[n]; 121 | } 122 | 123 | // If still nothing, pass entity through 124 | return (code === undefined || code === NaN) ? 125 | '&' + n + ';' : String.fromCharCode(code); 126 | } 127 | 128 | var ENTITIES_MAP = { 129 | 'nbsp' : 160, 130 | 'iexcl' : 161, 131 | 'cent' : 162, 132 | 'pound' : 163, 133 | 'curren' : 164, 134 | 'yen' : 165, 135 | 'brvbar' : 166, 136 | 'sect' : 167, 137 | 'uml' : 168, 138 | 'copy' : 169, 139 | 'ordf' : 170, 140 | 'laquo' : 171, 141 | 'not' : 172, 142 | 'shy' : 173, 143 | 'reg' : 174, 144 | 'macr' : 175, 145 | 'deg' : 176, 146 | 'plusmn' : 177, 147 | 'sup2' : 178, 148 | 'sup3' : 179, 149 | 'acute' : 180, 150 | 'micro' : 181, 151 | 'para' : 182, 152 | 'middot' : 183, 153 | 'cedil' : 184, 154 | 'sup1' : 185, 155 | 'ordm' : 186, 156 | 'raquo' : 187, 157 | 'frac14' : 188, 158 | 'frac12' : 189, 159 | 'frac34' : 190, 160 | 'iquest' : 191, 161 | 'Agrave' : 192, 162 | 'Aacute' : 193, 163 | 'Acirc' : 194, 164 | 'Atilde' : 195, 165 | 'Auml' : 196, 166 | 'Aring' : 197, 167 | 'AElig' : 198, 168 | 'Ccedil' : 199, 169 | 'Egrave' : 200, 170 | 'Eacute' : 201, 171 | 'Ecirc' : 202, 172 | 'Euml' : 203, 173 | 'Igrave' : 204, 174 | 'Iacute' : 205, 175 | 'Icirc' : 206, 176 | 'Iuml' : 207, 177 | 'ETH' : 208, 178 | 'Ntilde' : 209, 179 | 'Ograve' : 210, 180 | 'Oacute' : 211, 181 | 'Ocirc' : 212, 182 | 'Otilde' : 213, 183 | 'Ouml' : 214, 184 | 'times' : 215, 185 | 'Oslash' : 216, 186 | 'Ugrave' : 217, 187 | 'Uacute' : 218, 188 | 'Ucirc' : 219, 189 | 'Uuml' : 220, 190 | 'Yacute' : 221, 191 | 'THORN' : 222, 192 | 'szlig' : 223, 193 | 'agrave' : 224, 194 | 'aacute' : 225, 195 | 'acirc' : 226, 196 | 'atilde' : 227, 197 | 'auml' : 228, 198 | 'aring' : 229, 199 | 'aelig' : 230, 200 | 'ccedil' : 231, 201 | 'egrave' : 232, 202 | 'eacute' : 233, 203 | 'ecirc' : 234, 204 | 'euml' : 235, 205 | 'igrave' : 236, 206 | 'iacute' : 237, 207 | 'icirc' : 238, 208 | 'iuml' : 239, 209 | 'eth' : 240, 210 | 'ntilde' : 241, 211 | 'ograve' : 242, 212 | 'oacute' : 243, 213 | 'ocirc' : 244, 214 | 'otilde' : 245, 215 | 'ouml' : 246, 216 | 'divide' : 247, 217 | 'oslash' : 248, 218 | 'ugrave' : 249, 219 | 'uacute' : 250, 220 | 'ucirc' : 251, 221 | 'uuml' : 252, 222 | 'yacute' : 253, 223 | 'thorn' : 254, 224 | 'yuml' : 255, 225 | 'quot' : 34, 226 | 'amp' : 38, 227 | 'lt' : 60, 228 | 'gt' : 62, 229 | 'OElig' : 338, 230 | 'oelig' : 339, 231 | 'Scaron' : 352, 232 | 'scaron' : 353, 233 | 'Yuml' : 376, 234 | 'circ' : 710, 235 | 'tilde' : 732, 236 | 'ensp' : 8194, 237 | 'emsp' : 8195, 238 | 'thinsp' : 8201, 239 | 'zwnj' : 8204, 240 | 'zwj' : 8205, 241 | 'lrm' : 8206, 242 | 'rlm' : 8207, 243 | 'ndash' : 8211, 244 | 'mdash' : 8212, 245 | 'lsquo' : 8216, 246 | 'rsquo' : 8217, 247 | 'sbquo' : 8218, 248 | 'ldquo' : 8220, 249 | 'rdquo' : 8221, 250 | 'bdquo' : 8222, 251 | 'dagger' : 8224, 252 | 'Dagger' : 8225, 253 | 'permil' : 8240, 254 | 'lsaquo' : 8249, 255 | 'rsaquo' : 8250, 256 | 'euro' : 8364 257 | }; 258 | 259 | var EXPORTED_SYMBOLS = ['htmlToText']; 260 | 261 | if (typeof module !== 'undefined') { 262 | module.exports = htmlToText; 263 | } else { 264 | this.htmlToText = htmlToText; 265 | this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS; 266 | } 267 | 268 | }).call(function() { 269 | return this || (typeof window !== 'undefined' ? window : global); 270 | }()); 271 | -------------------------------------------------------------------------------- /src/common/markdown-render.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | /* 7 | * The function that does the basic raw-Markdown-in-HTML to rendered-HTML 8 | * conversion. 9 | * The reason we keep this function -- specifically, the function that uses our 10 | * external markdown renderer (marked.js), text-from-HTML module (jsHtmlToText.js), 11 | * and CSS -- separate is that it allows us to keep the bulk of the rendering 12 | * code (and the bulk of the code in our extension) out of the content script. 13 | * That way, we minimize the amount of code that needs to be loaded in every page. 14 | */ 15 | 16 | ;(function() { 17 | 18 | "use strict"; 19 | /*global module:false*/ 20 | 21 | /** 22 | Using the functionality provided by the functions htmlToText and markdownToHtml, 23 | render html into pretty text. 24 | @param targetDocument The document object where the action is taking place. 25 | It will be used to create elements, but those elements 26 | will not be inserted into the DOM. 27 | */ 28 | function markdownRender(userprefs, htmlToText, markdownToHtml, 29 | syntaxHighlighter, html, targetDocument, url) { 30 | var extractedText, markedOptions, keepTags, i, processed; 31 | 32 | processed = preprocessHtml(html, url); 33 | 34 | extractedText = htmlToText(processed.html, {allowTrailingWhitespace: true}); 35 | 36 | function mathify(mathcode) { 37 | return userprefs['math-value'] 38 | .replace(/\{mathcode\}/ig, mathcode) 39 | .replace(/\{urlmathcode\}/ig, encodeURIComponent(mathcode)); 40 | } 41 | 42 | markedOptions = { 43 | gfm: true, 44 | pedantic: false, 45 | sanitize: false, 46 | tables: true, 47 | smartLists: true, 48 | breaks: true, 49 | smartypants: true, 50 | langPrefix: 'language-', 51 | math: userprefs['math-enabled'] ? mathify : null, 52 | highlight: function(codeText, codeLanguage) { 53 | return highlightSyntax( 54 | targetDocument, 55 | syntaxHighlighter, 56 | codeText, 57 | codeLanguage); } 58 | }; 59 | 60 | var renderedMarkdown = markdownToHtml(extractedText, markedOptions); 61 | 62 | // Re-insert the excluded content that we removed in preprocessHtml 63 | html = postprocessHtml(renderedMarkdown, processed); 64 | 65 | return html; 66 | } 67 | 68 | /* 69 | We need to tweak the html-to-text processing to get the results we want. 70 | We also want to exclude some stuff (like reply blocks) from any processing. 71 | Returns an object that looks like this: 72 | { 73 | html: the HTML to render, 74 | exclusions: [array of { 75 | placeholder: the string added as placeholder for the excluded content 76 | content: the excluded content 77 | }] 78 | } 79 | 80 | NOTE: Maybe it would be better to do this stuff in markdown-here.js, where 81 | we have the DOM available? String-processing the HTML seems suboptimal. 82 | */ 83 | function preprocessHtml(html, url) { 84 | 85 | /* 86 | Historical note: At one time we kept lot of stuff intact: , , 87 | , -with-style-attr,

, and so on. This was nice, because 88 | it let users do some rich-edit-control formatting that would be retained 89 | when rendering. 90 | But it was a pain to get/keep working properly in Yahoo mail, and it 91 | introduced issue #18. So I tore out the feature, and now we 92 | only keep a few probably-not-problematic tags. 93 | */ 94 | 95 | var preprocessInfo = { html: html, exclusions: [] }; 96 | 97 | // The default behaviour for `htmlToText` is to strip out tags (and their 98 | // inner text/html) that it doesn't expect/want. But we want some tag blocks 99 | // to remain intact. 100 | preprocessInfo = excludeTagBlocks('blockquote', preprocessInfo, true); 101 | 102 | // Try to leave intact the line that Gmail adds that says: 103 | // On such-a-date, such-a-person wrote: 104 | preprocessInfo.html = preprocessInfo.html.replace( 105 | /<)((?!]*>)/ig, '$1
$2
$3') // a raw text node without an enclosing
won't be handled properly, so add one 136 | .replace(/(<\/div>)]*><\/div>(]*>)/ig, '$1$2') // empty
between other
elems gets removed 137 | .replace(/]*>
<\/div>/ig, '
') //

-->
138 | .replace(/(]*>)+/ig, '
') // opening
-->
(but nested
just gets one
) 139 | .replace(/<\/div>/ig, '') // closing
--> nothing 140 | .replace(/<(img[^>]*)>/ig, '<$1>') // tags --> textual tags 141 | .replace(/ /ig, ' '); //   --> space 142 | 143 | return preprocessInfo; 144 | 145 | // Escape all tags between tags of type `tagName`, inclusive. Also add a 146 | // special "exclude" class to them. 147 | // If `wrapInPara` is true, `

` tags will be added before and after each 148 | // tag block found. 149 | // If `ifHasAttribute` is non-null, tags will only be matched if they have 150 | // that attribute. 151 | // If `ifNotHasString` is non-null, tags that contain that string will not 152 | // be matched. Note that `ifNotHasString` will be used in a regex. 153 | // TODO: This function is pretty flawed. Wrapping block elements in paras 154 | // doesn't make much sense. And if we're going to support inline 155 | // elements, then we can't unconditionally put linebreaks around the 156 | // the wrapped elements. 157 | function excludeTagBlocks(tagName, preprocessInfo, wrapInPara, ifHasAttribute, ifNotHasString) { 158 | var depth, startIndex, openIndex, closeIndex, currentOpenIndex, 159 | openTagRegex, closeTagRegex, remainder, closeTagLength, regexFiller; 160 | 161 | regexFiller = ifNotHasString ? '(((?!'+ifNotHasString+')[^>])*)' : '[^>]*'; 162 | if (ifHasAttribute) { 163 | openTagRegex = new RegExp('<'+tagName+'\\b'+regexFiller+'\\b'+ifHasAttribute+'\\b'+regexFiller+'>', 'i'); 164 | } 165 | else { 166 | openTagRegex = new RegExp('<'+tagName+'\\b'+regexFiller+'>', 'i'); 167 | } 168 | 169 | closeTagRegex = new RegExp('= 0 && openIndex < closeIndex)) { 185 | // Process an open tag next. 186 | 187 | // Make the index relative to the beginning of the string. 188 | openIndex += startIndex; 189 | 190 | if (depth === 0) { 191 | // Not a nested tag. Start the escape here. 192 | currentOpenIndex = openIndex; 193 | } 194 | 195 | startIndex = openIndex + 1; 196 | depth += 1; 197 | } 198 | else { 199 | // Process a close tag next. 200 | 201 | if (depth > 0) { 202 | // Make the index relative to the beginning of the string. 203 | closeIndex += startIndex; 204 | 205 | if (depth === 1) { 206 | // Not a nested tag. Time to escape. 207 | // Because we've mangled the opening and closing tags, we need to 208 | // put around them so that they don't get mashed together with the 209 | // preceeding and following Markdown. 210 | 211 | closeTagLength = ('').length; 212 | 213 | var placeholder = String(Math.random()); 214 | preprocessInfo.exclusions.push({ 215 | placeholder: placeholder, 216 | content: 217 | '

' + 218 | (wrapInPara ? '

' : '') + 219 | preprocessInfo.html.slice(currentOpenIndex, closeIndex+closeTagLength) + 220 | (wrapInPara ? '

' : '') + 221 | '
' 222 | }); 223 | 224 | // We need to insert some empty lines when we extract something, 225 | // otherwise the stuff above and below would be rendered as if they 226 | // were together. 227 | 228 | preprocessInfo.html = 229 | preprocessInfo.html.slice(0, currentOpenIndex) + 230 | '


' + // three empty lines is "guaranteed" to break a Markdown block (like a bullet list) 231 | placeholder + 232 | '


' + 233 | preprocessInfo.html.slice(closeIndex+closeTagLength); 234 | 235 | // Start from the beginning again. The length of the string has 236 | // changed (so our indexes are meaningless), and we'll only find 237 | // unescaped/unprocessed tags of interest anyway. 238 | startIndex = 0; 239 | } 240 | else { 241 | startIndex = closeIndex + 1; 242 | } 243 | 244 | depth -= 1; 245 | } 246 | else { 247 | // Depth is 0. So we've found a closing tag while not in an opening 248 | // tag -- this can happen normally if `ifHasAttribute` is non-null. 249 | // Just advance the startIndex. 250 | startIndex += closeIndex + 1; 251 | } 252 | } 253 | } 254 | 255 | return preprocessInfo; 256 | } 257 | 258 | // Add the class `className` to all tags in `html`. 259 | function addClassToAllTags(className, html) { 260 | return html 261 | .replace( 262 | /<(\w+\b)(([^>]*)(class=("|')([^>]*?)\5)([^>]*))>/ig, 263 | '<$1$3class="$6 ' + className + '"$7>') 264 | .replace( 265 | /<(\w+\b)(((?!class)[^>])*)>/ig, 266 | '<$1 class="' + className + '"$2>'); 267 | } 268 | } 269 | 270 | /** 271 | Converts instances of `tag` in `html` to Markdown and returns the 272 | resulting HTML. 273 | */ 274 | function convertHTMLtoMarkdown(tag, html) { 275 | if (tag === 'a') { 276 | /* 277 | Make sure we do *not* convert HTML links that are inside of MD links. 278 | Otherwise we'll have problems like issue #69. 279 | We're going to use a regex that mimics a negative lookbehind. For details see: http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript 280 | Here's an attempt at an explanation of the regex: 281 | ( // begin optional prefix capture group 282 | (?:\]\([^\)]*) // match an unclosed URL portion of a MD link -- like "...](..." 283 | |(?:\[[^\]]*) // match an unclosed name portion of a MD link -- like "...[..." 284 | )? // capture group is optional so that we do the "negative" lookbehind -- that is, we can match links that are *not* preceded by the stuff we *don't* want 285 | ]*href="([^"]*)"[^>]*>(.*?)<\/a> // an HTML link 286 | Then the replace callback looks like this: 287 | return $1 ? $0 : '['+$3+']('+$2+')' 288 | So, if the first capture group is matched (i.e., $1 has value), then we've 289 | matched the bad thing -- the indication that the HTML is inside a MD link. 290 | In that case, we don't modify anything. Otherwise we use our other capture 291 | groups to create the desired MD link. 292 | */ 293 | html = html.replace( 294 | /((?:\]\([^\)]*)|(?:\[[^\]]*))?]*href="([^"]*)"[^>]*>(.*?)<\/a>/ig, 295 | function($0, $1, $2, $3) { 296 | return $1 ? $0 : '['+$3+']('+$2+')'; 297 | }); 298 | } 299 | else { 300 | throw new Error('convertHTMLtoMarkdown: ' + tag + ' is not a supported tag'); 301 | return; 302 | } 303 | 304 | return html; 305 | } 306 | 307 | // Restore the content that we extracted so that it wouldn't be processed. 308 | function postprocessHtml(renderedMarkdown, preprocessInfo) { 309 | var i; 310 | for (i = 0; i < preprocessInfo.exclusions.length; i++) { 311 | renderedMarkdown = renderedMarkdown.replace(preprocessInfo.exclusions[i].placeholder, 312 | preprocessInfo.exclusions[i].content); 313 | } 314 | 315 | return renderedMarkdown; 316 | } 317 | 318 | // Using `syntaxHighlighter`, highlight the code in `codeText` that is of 319 | // language `codeLanguage` (may be falsy). 320 | // `syntaxHighlighter` is expected to behave like (i.e., to be) highlight.js. 321 | function highlightSyntax(targetDocument, syntaxHighlighter, codeText, codeLanguage) { 322 | var codeElem, preElem, textNode; 323 | 324 | // highlight.js requires a `` element to be passed in that has a 325 | // `
` parent element.
326 | 
327 |     preElem = targetDocument.createElement('pre');
328 |     codeElem = targetDocument.createElement('code');
329 |     textNode = targetDocument.createTextNode(codeText);
330 |     codeElem.appendChild(textNode);
331 |     preElem.appendChild(codeElem);
332 | 
333 |     // If we're told the language, set it as a class so that the highlighter
334 |     // doesn't have to guess it. This is part of the HTML5 standard. See:
335 |     // http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-code-element
336 |     if (codeLanguage && codeLanguage.length > 0) {
337 |       codeElem.setAttribute('class', 'language-'+codeLanguage);
338 |     }
339 |     else {
340 |       codeElem.setAttribute('class', 'no-highlight');
341 |     }
342 | 
343 |     syntaxHighlighter.highlightBlock(codeElem);
344 | 
345 |     return codeElem.innerHTML;
346 |   }
347 | 
348 |   markdownRender._testExports = {
349 |     convertHTMLtoMarkdown: convertHTMLtoMarkdown,
350 |     preprocessHtml: preprocessHtml
351 |   };
352 | 
353 |   var EXPORTED_SYMBOLS = ['markdownRender'];
354 | 
355 |   if (typeof module !== 'undefined') {
356 |     module.exports = markdownRender;
357 |   } else {
358 |     this.markdownRender = markdownRender;
359 |     this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS;
360 |   }
361 | 
362 | }).call(function() {
363 |   return this || (typeof window !== 'undefined' ? window : global);
364 | }());
365 | 


--------------------------------------------------------------------------------
/src/common/options-iframe.html:
--------------------------------------------------------------------------------
 1 | 
 5 | 
 6 | 
 7 | 
 8 | 
 9 | 
10 | 
11 |   
12 |   
13 |   
14 |   
15 |   
16 | 
17 |   
27 | 
28 | 
29 | 
31 | 
32 | 
33 | ```javascript
34 | function syntaxHighlighting() {
35 |   var n = 33;
36 |   var s = "hi";
37 |   console.log(s);
38 | }
39 | ```
40 |
41 | * plain
42 | * *emphasis*
43 |   * **strong emphasis**
44 | * `inline code`
45 |
46 | 1. Numbered list
47 | 2. [Link](https://www.google.com)
48 |
49 |
50 | > Block quote. 
51 | > *With* **some** `markdown`.
52 |
53 | If **TeX Math** support is enabled, this is the quadratic equation: 
54 | $-b \pm \sqrt{b^2 - 4ac} \over 2a$
55 |
56 | # Header 1
57 | ## Header 2
58 | ### Header 3
59 | #### Header 4
60 | ##### Header 5
61 | ###### Header 6
62 |  
63 | | Tables | Are | Cool |
64 | | ------------- |:-------------:| -----:|
65 | | col 3 is | right-aligned | $1600 |
66 | | col 2 is | centered | $12 |
67 | | zebra stripes | are neat | $1 |
68 |
69 | Horizontal rule
70 |
71 | ---
72 |
73 | <dl>
74 | <dt>Definition list</dt>
75 | <dd>Is something people use sometimes.</dd>
76 | </dl>
77 |
78 | ```
79 | code block
80 | with no highlighting
81 | ```
82 |
83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/common/options-iframe.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | function onLoad() { 7 | // Chrome and Safari require us to manually load our content script in order 8 | // to use the button and context menu in the iframe. 9 | if (typeof(safari) !== 'undefined' || typeof(chrome) !== 'undefined') { 10 | window.LOAD_MARKDOWN_HERE_CONTENT_SCRIPT = true; 11 | var contentscript = document.createElement('script'); 12 | if (typeof(safari) !== 'undefined') { 13 | contentscript.src = '../../../contentscript.js'; 14 | } 15 | else if (typeof(chrome) !== 'undefined') { 16 | contentscript.src = '../chrome/contentscript.js'; 17 | } 18 | document.body.appendChild(contentscript); 19 | } 20 | 21 | // The body of the iframe needs to have a (collapsed) selection range for 22 | // Markdown Here to work (simulating focus/cursor). 23 | var range = document.createRange(); 24 | range.setStart(document.body, 0); 25 | var sel = document.getSelection(); 26 | sel.removeAllRanges(); 27 | sel.addRange(range); 28 | 29 | // Let our owner page know that we've loaded. 30 | var e = top.document.createEvent('HTMLEvents'); 31 | e.initEvent('options-iframe-loaded', true, true); 32 | top.document.dispatchEvent(e); 33 | } 34 | document.addEventListener('DOMContentLoaded', onLoad, false); 35 | -------------------------------------------------------------------------------- /src/common/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Markdown Here Autotests 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/common/test/markdown-render-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | "use strict"; 7 | /* jshint curly:true, noempty:true, newcap:true, eqeqeq:true, eqnull:true, es5:true, undef:true, devel:true, browser:true, node:true, evil:false, latedef:false, nonew:true, trailing:false, immed:false, smarttabs:true, expr:true */ 8 | /* global describe, expect, it, before, beforeEach, after, afterEach */ 9 | /* global _, $, markdownRender, htmlToText, marked, hljs, Utils */ 10 | 11 | 12 | describe('Markdown-Render', function() { 13 | it('should exist', function() { 14 | expect(markdownRender).to.exist; 15 | }); 16 | 17 | describe('convertHTMLtoMarkdown', function() { 18 | var convertHTMLtoMarkdown = markdownRender._testExports.convertHTMLtoMarkdown; 19 | 20 | it('should throw an exception for unsupported tags', function() { 21 | expect(_.partial(convertHTMLtoMarkdown, 'badtag')).to.throw(Error); 22 | }); 23 | 24 | it('should not modify the string if there is no match', function() { 25 | var s = 'aaa bbb ccc
ddd
eee'; 26 | expect(convertHTMLtoMarkdown('a', s)).to.equal(s); 27 | }); 28 | 29 | it('should replace the given tag', function() { 30 | var s, target; 31 | 32 | s = 'aaa bbb ccc
ddd
eee
ggg hhh'; 33 | target = 'aaa bbb ccc
ddd
eee [ggg](fff) hhh'; 34 | expect(convertHTMLtoMarkdown('a', s)).to.equal(target); 35 | 36 | s = 'aaa bbb ccc
ddd
eee ggg hhh jjj kkk lll'; 37 | target = 'aaa bbb ccc
ddd
eee [ggg](fff) hhh [jjj kkk](iii) lll'; 38 | expect(convertHTMLtoMarkdown('a', s)).to.equal(target); 39 | }); 40 | }); 41 | 42 | describe('preprocessHtml', function() { 43 | var preprocessHtml = markdownRender._testExports.preprocessHtml; 44 | 45 | it ('should be okay with an empty string', function() { 46 | expect(preprocessHtml('', null).html).to.equal(''); 47 | }); 48 | }); 49 | 50 | describe('markdownRender', function() { 51 | var userprefs = {}; 52 | 53 | beforeEach(function() { 54 | userprefs = { 55 | 'math-value': null, 56 | 'math-enabled': false 57 | }; 58 | }); 59 | 60 | it('should be okay with an empty string', function() { 61 | expect(markdownRender(userprefs, htmlToText, marked, hljs, '', document, null)).to.equal(''); 62 | }); 63 | 64 | // Busted due to https://github.com/adam-p/markdown-here/issues/51, which 65 | // is busted due to https://github.com/chjj/marked/issues/56 66 | it('should NOT correctly handle links with URL text (busted due to issue #51)', function() { 67 | var s = '[http://example1.com](http://example2.com)'; 68 | 69 | // Real target 70 | //var target = 'http://example1.com'; 72 | expect(markdownRender(userprefs, htmlToText, marked, hljs, s, document, null)).to.contain(target); 73 | }); 74 | 75 | it('should NOT quite correctly handle pre-formatted links with URL text (busted due to issue #51)', function() { 76 | var s = 'http://example2.com'; 77 | 78 | // Real target 79 | //var target = 'http://example2.com'; 81 | expect(markdownRender(userprefs, htmlToText, marked, hljs, s, document, null)).to.contain(target); 82 | }); 83 | 84 | it('should retain pre-formatted links', function() { 85 | var s = 'aaa'; 86 | expect(markdownRender(userprefs, htmlToText, marked, hljs, s, document, null)).to.contain(s); 87 | }); 88 | 89 | // Test that issue #69 hasn't come back: https://github.com/adam-p/markdown-here/issues/69 90 | it('should properly render MD links that contain pre-formatted HTML links', function() { 91 | var md = '[aaa](ccc)'; 92 | var html = '

aaa

'; 93 | 94 | var tests = [], i; 95 | 96 | // NOTE: The expected results are affected by other content massaging, 97 | // such as adding missing links schemas. 98 | 99 | // Begin tests where the link should be converted 100 | 101 | tests.push(['asdf bbb asdf', 102 | '

asdf bbb asdf

\n']); 103 | 104 | tests.push(['bbb', 105 | '

bbb

\n']); 106 | 107 | tests.push(['[xxx](yyy) bbb', 108 | '

xxx bbb

\n']); 109 | 110 | tests.push(['asdf (bbb)', 111 | '

asdf (bbb)

\n']); 112 | 113 | // Begin tests where the link should *not* be converted 114 | 115 | tests.push(['asdf [yyy](bbb) asdf', 116 | '

asdf yyy asdf

\n']); 117 | 118 | tests.push(['asdf [bbb](ccc) asdf', 119 | '

asdf bbb asdf

\n']); 120 | 121 | tests.push(['[yyy](bbb)', 122 | '

yyy

\n']); 123 | 124 | tests.push(['[yyy]( bbb)', 125 | '

yyy

\n']); 126 | 127 | tests.push(['asdf [qwer bbb](ccc) asdf', 128 | '

asdf qwer bbb asdf

\n']); 129 | 130 | // Begin mixed tests 131 | 132 | tests.push(['asdf [aaa](bbb) asdf bbb asdf [yyy](bbb) asdf', 133 | '

asdf aaa asdf bbb asdf yyy asdf

\n']); 134 | 135 | // Begin tests that don't work quite right 136 | 137 | tests.push(['asdf [bbb] asdf', 138 | '

asdf [bbb] asdf

\n']); 139 | 140 | tests.push(['asdf ](bbb) asdf', 141 | '

asdf ](bbb) asdf

\n']); 142 | 143 | for (i = 0; i < tests.length; i++) { 144 | expect(markdownRender(userprefs, htmlToText, marked, hljs, tests[i][0], document, null)).to.equal(tests[i][1]); 145 | } 146 | }); 147 | 148 | // Test issue #57: https://github.com/adam-p/markdown-here/issues/57 149 | it('should add the schema to links missing it', function() { 150 | var md = 'asdf [aaa](bbb) asdf [ccc](ftp://ddd) asdf'; 151 | var target = '

asdf aaa asdf ccc asdf

\n'; 152 | expect(markdownRender(userprefs, htmlToText, marked, hljs, md, document, null)).to.equal(target); 153 | }); 154 | 155 | it('should *not* add the schema to anchor links', function() { 156 | var md = 'asdf [aaa](#bbb) asdf [ccc](ftp://ddd) asdf'; 157 | var target = '

asdf aaa asdf ccc asdf

\n'; 158 | expect(markdownRender(userprefs, htmlToText, marked, hljs, md, document, null)).to.equal(target); 159 | }); 160 | 161 | }); 162 | 163 | }); 164 | -------------------------------------------------------------------------------- /src/common/test/mocha.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body { 4 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; 5 | padding: 60px 50px; 6 | } 7 | 8 | #mocha ul, #mocha li { 9 | margin: 0; 10 | padding: 0; 11 | } 12 | 13 | #mocha ul { 14 | list-style: none; 15 | } 16 | 17 | #mocha h1, #mocha h2 { 18 | margin: 0; 19 | } 20 | 21 | #mocha h1 { 22 | margin-top: 15px; 23 | font-size: 1em; 24 | font-weight: 200; 25 | } 26 | 27 | #mocha h1 a { 28 | text-decoration: none; 29 | color: inherit; 30 | } 31 | 32 | #mocha h1 a:hover { 33 | text-decoration: underline; 34 | } 35 | 36 | #mocha .suite .suite h1 { 37 | margin-top: 0; 38 | font-size: .8em; 39 | } 40 | 41 | .hidden { 42 | display: none; 43 | } 44 | 45 | #mocha h2 { 46 | font-size: 12px; 47 | font-weight: normal; 48 | cursor: pointer; 49 | } 50 | 51 | #mocha .suite { 52 | margin-left: 15px; 53 | } 54 | 55 | #mocha .test { 56 | margin-left: 15px; 57 | overflow: hidden; 58 | } 59 | 60 | #mocha .test.pending:hover h2::after { 61 | content: '(pending)'; 62 | font-family: arial; 63 | } 64 | 65 | #mocha .test.pass.medium .duration { 66 | background: #C09853; 67 | } 68 | 69 | #mocha .test.pass.slow .duration { 70 | background: #B94A48; 71 | } 72 | 73 | #mocha .test.pass::before { 74 | content: '✓'; 75 | font-size: 12px; 76 | display: block; 77 | float: left; 78 | margin-right: 5px; 79 | color: #00d6b2; 80 | } 81 | 82 | #mocha .test.pass .duration { 83 | font-size: 9px; 84 | margin-left: 5px; 85 | padding: 2px 5px; 86 | color: white; 87 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 88 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 89 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2); 90 | -webkit-border-radius: 5px; 91 | -moz-border-radius: 5px; 92 | -ms-border-radius: 5px; 93 | -o-border-radius: 5px; 94 | border-radius: 5px; 95 | } 96 | 97 | #mocha .test.pass.fast .duration { 98 | display: none; 99 | } 100 | 101 | #mocha .test.pending { 102 | color: #0b97c4; 103 | } 104 | 105 | #mocha .test.pending::before { 106 | content: '◦'; 107 | color: #0b97c4; 108 | } 109 | 110 | #mocha .test.fail { 111 | color: #c00; 112 | } 113 | 114 | #mocha .test.fail pre { 115 | color: black; 116 | } 117 | 118 | #mocha .test.fail::before { 119 | content: '✖'; 120 | font-size: 12px; 121 | display: block; 122 | float: left; 123 | margin-right: 5px; 124 | color: #c00; 125 | } 126 | 127 | #mocha .test pre.error { 128 | color: #c00; 129 | max-height: 300px; 130 | overflow: auto; 131 | } 132 | 133 | #mocha .test pre { 134 | display: block; 135 | float: left; 136 | clear: left; 137 | font: 12px/1.5 monaco, monospace; 138 | margin: 5px; 139 | padding: 15px; 140 | border: 1px solid #eee; 141 | border-bottom-color: #ddd; 142 | -webkit-border-radius: 3px; 143 | -webkit-box-shadow: 0 1px 3px #eee; 144 | -moz-border-radius: 3px; 145 | -moz-box-shadow: 0 1px 3px #eee; 146 | } 147 | 148 | #mocha .test h2 { 149 | position: relative; 150 | } 151 | 152 | #mocha .test a.replay { 153 | position: absolute; 154 | top: 3px; 155 | right: 0; 156 | text-decoration: none; 157 | vertical-align: middle; 158 | display: block; 159 | width: 15px; 160 | height: 15px; 161 | line-height: 15px; 162 | text-align: center; 163 | background: #eee; 164 | font-size: 15px; 165 | -moz-border-radius: 15px; 166 | border-radius: 15px; 167 | -webkit-transition: opacity 200ms; 168 | -moz-transition: opacity 200ms; 169 | transition: opacity 200ms; 170 | opacity: 0.3; 171 | color: #888; 172 | } 173 | 174 | #mocha .test:hover a.replay { 175 | opacity: 1; 176 | } 177 | 178 | #mocha-report.pass .test.fail { 179 | display: none; 180 | } 181 | 182 | #mocha-report.fail .test.pass { 183 | display: none; 184 | } 185 | 186 | #mocha-error { 187 | color: #c00; 188 | font-size: 1.5 em; 189 | font-weight: 100; 190 | letter-spacing: 1px; 191 | } 192 | 193 | #mocha-stats { 194 | position: fixed; 195 | top: 15px; 196 | right: 10px; 197 | font-size: 12px; 198 | margin: 0; 199 | color: #888; 200 | } 201 | 202 | #mocha-stats .progress { 203 | float: right; 204 | padding-top: 0; 205 | } 206 | 207 | #mocha-stats em { 208 | color: black; 209 | } 210 | 211 | #mocha-stats a { 212 | text-decoration: none; 213 | color: inherit; 214 | } 215 | 216 | #mocha-stats a:hover { 217 | border-bottom: 1px solid #eee; 218 | } 219 | 220 | #mocha-stats li { 221 | display: inline-block; 222 | margin: 0 5px; 223 | list-style: none; 224 | padding-top: 11px; 225 | } 226 | 227 | code .comment { color: #ddd } 228 | code .init { color: #2F6FAD } 229 | code .string { color: #5890AD } 230 | code .keyword { color: #8A6343 } 231 | code .number { color: #2F6FAD } 232 | -------------------------------------------------------------------------------- /src/common/test/options-store-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | "use strict"; 7 | /* jshint curly:true, noempty:true, newcap:true, eqeqeq:true, eqnull:true, es5:true, undef:true, devel:true, browser:true, node:true, evil:false, latedef:false, nonew:true, trailing:false, immed:false, smarttabs:true, expr:true */ 8 | /* global describe, expect, it, before, beforeEach, after, afterEach */ 9 | /* global _, $, markdownRender, htmlToText, marked, hljs, Utils, OptionsStore */ 10 | 11 | 12 | describe('OptionsStore', function() { 13 | it('should exist', function() { 14 | expect(OptionsStore).to.exist; 15 | }); 16 | 17 | var testKeys = ['test-option-a', 'test-option-b']; 18 | 19 | beforeEach(function(done) { 20 | OptionsStore.remove(testKeys, function() { 21 | done(); 22 | }); 23 | }); 24 | 25 | after(function(done) { 26 | OptionsStore.remove(testKeys, function() { 27 | done(); 28 | }); 29 | }); 30 | 31 | it('should call callback after getting', function(done) { 32 | OptionsStore.get(function() { 33 | done(); 34 | }); 35 | }); 36 | 37 | it('should call callback after setting', function(done) { 38 | OptionsStore.set({}, function() { 39 | done(); 40 | }); 41 | }); 42 | 43 | it('should call callback after removing', function(done) { 44 | OptionsStore.remove([], function() { 45 | done(); 46 | }); 47 | }); 48 | 49 | it('should set and get null values', function(done) { 50 | OptionsStore.get(function(options) { 51 | expect(options).to.not.have.property(testKeys[0]); 52 | 53 | var obj = {}; 54 | obj[testKeys[0]] = null; 55 | 56 | OptionsStore.set(obj, function() { 57 | OptionsStore.get(function(newOptions) { 58 | expect(newOptions).to.have.property(testKeys[0]); 59 | expect(newOptions[testKeys[0]]).to.be.null; 60 | done(); 61 | }); 62 | }); 63 | }); 64 | }); 65 | 66 | it('should set and get long values', function(done) { 67 | var longString = (new Array(10*1024)).join('x'); 68 | 69 | var obj = {}; 70 | obj[testKeys[0]] = longString; 71 | 72 | OptionsStore.set(obj, function() { 73 | OptionsStore.get(function(newOptions) { 74 | expect(newOptions).to.have.property(testKeys[0]); 75 | expect(newOptions[testKeys[0]]).to.equal(longString); 76 | done(); 77 | }); 78 | }); 79 | }); 80 | 81 | it('should set and get objects', function(done) { 82 | OptionsStore.get(function(options) { 83 | expect(options).to.not.have.property(testKeys[0]); 84 | 85 | var obj = {}; 86 | obj[testKeys[0]] = { 87 | 'aaa': 111, 88 | 'bbb': 'zzz', 89 | 'ccc': ['q', 'w', 3, 4], 90 | 'ddd': {'mmm': 'nnn'} 91 | }; 92 | 93 | OptionsStore.set(obj, function() { 94 | OptionsStore.get(function(newOptions) { 95 | expect(newOptions).to.have.property(testKeys[0]); 96 | expect(newOptions[testKeys[0]]).to.eql(obj[testKeys[0]]); 97 | done(); 98 | }); 99 | }); 100 | }); 101 | }); 102 | 103 | it('should set and get arrays', function(done) { 104 | OptionsStore.get(function(options) { 105 | expect(options).to.not.have.property(testKeys[0]); 106 | 107 | var obj = {}; 108 | obj[testKeys[0]] = [1, 2, 'a', 'b', {'aa': 11}, ['q', 6]]; 109 | 110 | OptionsStore.set(obj, function() { 111 | OptionsStore.get(function(newOptions) { 112 | expect(newOptions).to.have.property(testKeys[0]); 113 | expect(newOptions[testKeys[0]]).to.eql(obj[testKeys[0]]); 114 | expect(Array.isArray(newOptions[testKeys[0]])).to.be.true; 115 | expect(newOptions[testKeys[0]]).to.have.property('length'); 116 | 117 | done(); 118 | }); 119 | }); 120 | }); 121 | }); 122 | 123 | it('should remove entries', function(done) { 124 | OptionsStore.get(function(options) { 125 | expect(options).to.not.have.property(testKeys[0]); 126 | 127 | var obj = {}; 128 | obj[testKeys[0]] = 'hi'; 129 | 130 | OptionsStore.set(obj, function() { 131 | OptionsStore.get(function(newOptions) { 132 | expect(newOptions).to.have.property(testKeys[0]); 133 | expect(newOptions[testKeys[0]]).to.eql(obj[testKeys[0]]); 134 | 135 | OptionsStore.remove(testKeys[0], function() { 136 | OptionsStore.get(function(newOptions) { 137 | expect(options).to.not.have.property(testKeys[0]); 138 | done(); 139 | }); 140 | }); 141 | }); 142 | }); 143 | }); 144 | }); 145 | 146 | it('should set and get multiple values', function(done) { 147 | OptionsStore.get(function(options) { 148 | expect(options).to.not.have.property(testKeys[0]); 149 | 150 | var obj = {}; 151 | obj[testKeys[0]] = 'value the first'; 152 | obj[testKeys[1]] = ['value the second']; 153 | 154 | OptionsStore.set(obj, function() { 155 | OptionsStore.get(function(newOptions) { 156 | expect(newOptions).to.have.property(testKeys[0]); 157 | expect(newOptions[testKeys[0]]).to.eql(obj[testKeys[0]]); 158 | expect(newOptions).to.have.property(testKeys[1]); 159 | expect(newOptions[testKeys[1]]).to.eql(obj[testKeys[1]]); 160 | done(); 161 | }); 162 | }); 163 | }); 164 | }); 165 | 166 | describe('default value behaviour', function() { 167 | beforeEach(function() { 168 | delete OptionsStore.defaults[testKeys[0]]; 169 | }); 170 | 171 | after(function() { 172 | delete OptionsStore.defaults[testKeys[0]]; 173 | }); 174 | 175 | it('should not fill in defaults if there is not a default', function(done) { 176 | OptionsStore.get(function(options) { 177 | expect(options).to.not.have.property(testKeys[0]); 178 | 179 | done(); 180 | }); 181 | }); 182 | 183 | it('should fill in defaults', function(done) { 184 | OptionsStore.get(function(options) { 185 | expect(options).to.not.have.property(testKeys[0]); 186 | 187 | // Set the default value (still pretty hacky) 188 | OptionsStore.defaults[testKeys[0]] = 'my default value'; 189 | 190 | // Make sure we get the default value now 191 | OptionsStore.get(function(options) { 192 | expect(options).to.have.property(testKeys[0]); 193 | expect(options[testKeys[0]]).to.eql('my default value'); 194 | 195 | done(); 196 | }); 197 | }); 198 | }); 199 | 200 | it('should not fill in default if value is set', function(done) { 201 | OptionsStore.get(function(options) { 202 | expect(options).to.not.have.property(testKeys[0]); 203 | 204 | // Set the default value (still pretty hacky) 205 | OptionsStore.defaults[testKeys[0]] = 'my default value'; 206 | 207 | var obj = {}; 208 | obj[testKeys[0]] = 'my non-default value'; 209 | 210 | // But also set the value in the options 211 | OptionsStore.set(obj, function() { 212 | // Make sure we do *not* get the default value now 213 | OptionsStore.get(function(options) { 214 | expect(options).to.have.property(testKeys[0]); 215 | expect(options[testKeys[0]]).to.eql('my non-default value'); 216 | 217 | done(); 218 | }); 219 | }); 220 | }); 221 | }); 222 | 223 | it('should fill in default values from files', function(done) { 224 | OptionsStore.get(function(options) { 225 | expect(options).to.not.have.property(testKeys[0]); 226 | 227 | // Set a default value that requires a XHR 228 | OptionsStore.defaults[testKeys[0]] = {'__defaultFromFile__': window.location.href}; 229 | 230 | // Note: Using $.ajax won't work because for local requests Firefox sets 231 | // status to 0 even on success. jQuery interprets this as an error. 232 | var xhr = new XMLHttpRequest(); 233 | xhr.open('GET', window.location.href); 234 | // If we don't set the mimetype, Firefox will complain. 235 | xhr.overrideMimeType('text/plain'); 236 | xhr.onreadystatechange = function() { 237 | if (this.readyState === this.DONE) { 238 | OptionsStore.get(function(options) { 239 | expect(options).to.have.property(testKeys[0]); 240 | expect(options[testKeys[0]]).to.eql(xhr.responseText); 241 | done(); 242 | }); 243 | } 244 | }; 245 | xhr.send(); 246 | }); 247 | }); 248 | 249 | }); 250 | 251 | }); 252 | -------------------------------------------------------------------------------- /src/common/test/test-prep.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | mocha.setup('bdd'); 7 | var expect = chai.expect; -------------------------------------------------------------------------------- /src/common/test/test-run.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | $(function(){ 7 | mocha 8 | // I'm not sure what introduces the global "schemaTypes", but it's not 9 | // Markdown Here and it causes an error on one of my Chrome instances. 10 | .globals([ 'schemaTypes' ]) // acceptable globals 11 | .run(); 12 | }); 13 | -------------------------------------------------------------------------------- /src/common/test/utils-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | "use strict"; 7 | /* jshint curly:true, noempty:true, newcap:true, eqeqeq:true, eqnull:true, es5:true, undef:true, devel:true, browser:true, node:true, evil:false, latedef:false, nonew:true, trailing:false, immed:false, smarttabs:true, expr:true */ 8 | /* global describe, expect, it, before, beforeEach, after, afterEach */ 9 | /* global _, $, markdownRender, htmlToText, marked, hljs, Utils */ 10 | 11 | 12 | // This function wraps `htmlString` in a `
` to make life easier for us. 13 | // It should affect the testing behaviour, though -- good/bad elements in a 14 | // `
` are still good/bad. 15 | function createDocFrag(htmlString) { 16 | var docFrag = document.createDocumentFragment(); 17 | var elem = document.createElement('div'); 18 | elem.innerHTML = htmlString; 19 | docFrag.appendChild(elem); 20 | return docFrag; 21 | } 22 | 23 | 24 | describe('Utils', function() { 25 | it('should exist', function() { 26 | expect(Utils).to.exist; 27 | }); 28 | 29 | describe('sanitizeDocumentFragment', function() { 30 | it('should not alter safe doc-frags', function() { 31 | var origFrag = createDocFrag('
hi'); 32 | var sanFrag = Utils.sanitizeDocumentFragment(origFrag); 33 | expect(origFrag.isEqualNode(sanFrag)).to.be.true; 34 | }); 35 | 36 | it('should remove there'); 38 | var sanFrag = Utils.sanitizeDocumentFragment(origFrag); 39 | expect(origFrag.isEqualNode(sanFrag)).to.be.false; 40 | 41 | var cleanFrag = createDocFrag('hithere'); 42 | expect(cleanFrag.isEqualNode(sanFrag)).to.be.true; 43 | }); 44 | 45 | it('should not remove safe attributes', function() { 46 | var origFrag = createDocFrag('
hi
'); 47 | // Make sure the attributes are sticking in the original 48 | expect(origFrag.querySelector('#rad').style.color).to.equal('red'); 49 | 50 | var sanFrag = Utils.sanitizeDocumentFragment(origFrag); 51 | expect(origFrag.isEqualNode(sanFrag)).to.be.true; 52 | }); 53 | 54 | it('should remove event handler attributes', function() { 55 | var origFrag = createDocFrag('
hi
'); 56 | // Make sure the attributes are sticking in the original 57 | expect(origFrag.querySelector('#rad').attributes.onclick).to.exist; 58 | 59 | var sanFrag = Utils.sanitizeDocumentFragment(origFrag); 60 | expect(origFrag.isEqualNode(sanFrag)).to.be.false; 61 | 62 | var cleanFrag = createDocFrag('
hi
'); 63 | expect(cleanFrag.isEqualNode(sanFrag)).to.be.true; 64 | }); 65 | }); 66 | 67 | describe('saferSetInnerHTML', function() { 68 | it('should set safe HTML without alteration', function() { 69 | var testElem = document.createElement('div'); 70 | Utils.saferSetInnerHTML(testElem, '

hi

'); 71 | 72 | var checkElem = document.createElement('div'); 73 | checkElem.innerHTML = '

hi

'; 74 | 75 | expect(testElem.isEqualNode(checkElem)).to.be.true; 76 | }); 77 | 78 | it('should remove there'); 81 | 82 | var checkElem = document.createElement('div'); 83 | checkElem.innerHTML = 'hithere'; 84 | 85 | expect(testElem.isEqualNode(checkElem)).to.be.false; 86 | 87 | var safeElem = document.createElement('div'); 88 | safeElem.innerHTML = 'hithere'; 89 | 90 | expect(testElem.isEqualNode(safeElem)).to.be.true; 91 | }); 92 | 93 | it('should not remove safe attributes', function() { 94 | var testElem = document.createElement('div'); 95 | Utils.saferSetInnerHTML(testElem, '
hi
'); 96 | 97 | var checkElem = document.createElement('div'); 98 | checkElem.innerHTML = '
hi
'; 99 | 100 | expect(testElem.isEqualNode(checkElem)).to.be.true; 101 | 102 | expect(testElem.querySelector('#rad').style.color).to.equal('red'); 103 | }); 104 | 105 | it('should remove event handler attributes', function() { 106 | var testElem = document.createElement('div'); 107 | Utils.saferSetInnerHTML(testElem, '
hi
'); 108 | 109 | var checkElem = document.createElement('div'); 110 | checkElem.innerHTML = '
hi
'; 111 | 112 | expect(testElem.isEqualNode(checkElem)).to.be.true; 113 | 114 | expect(testElem.querySelector('#rad').style.color).to.equal('red'); 115 | expect(testElem.querySelector('#rad').attributes.onclick).to.not.exist; 116 | }); 117 | 118 | }); 119 | 120 | describe('saferSetOuterHTML', function() { 121 | beforeEach(function() { 122 | // Our test container element, which will not be modified 123 | $('body').append($('')); 124 | }); 125 | 126 | afterEach(function() { 127 | $('#test-container').remove(); 128 | }); 129 | 130 | it('should throw exception if element not in DOM', function() { 131 | var testElem = $('
bye
').get(0); 132 | 133 | var fn = _.partial(Utils.saferSetOuterHTML, '

'); 134 | 135 | expect(fn).to.throw(Error); 136 | }); 137 | 138 | it('should set safe HTML without alteration', function() { 139 | Utils.saferSetOuterHTML($('#test-container').children(':first').get(0), '

hi

'); 140 | 141 | expect($('#test-container').html()).to.equal('

hi

'); 142 | }); 143 | 144 | it('should remove there'); 146 | 147 | expect($('#test-container').html()).to.equal('hithere'); 148 | }); 149 | 150 | it('should not remove safe attributes', function() { 151 | Utils.saferSetOuterHTML($('#test-container').children(':first').get(0), '
hi
'); 152 | 153 | expect($('#test-container').html()).to.equal('
hi
'); 154 | }); 155 | 156 | it('should remove event handler attributes', function() { 157 | Utils.saferSetOuterHTML($('#test-container').children(':first').get(0), '
hi
'); 158 | 159 | expect($('#test-container').html()).to.equal('
hi
'); 160 | }); 161 | 162 | }); 163 | 164 | }); -------------------------------------------------------------------------------- /src/common/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright Adam Pritchard 2013 3 | * MIT License : http://adampritchard.mit-license.org/ 4 | */ 5 | 6 | /* 7 | * Utilitiles and helpers that are needed in multiple places. 8 | */ 9 | 10 | ;(function() { 11 | 12 | "use strict"; 13 | /*global module:false*/ 14 | 15 | 16 | // Assigning a string directly to `element.innerHTML` is potentially dangerous: 17 | // e.g., the string can contain harmful script elements. (Additionally, Mozilla 18 | // won't let us pass validation with `innerHTML` assignments in place.) 19 | // This function provides a safer way to append a HTML string into an element. 20 | function saferSetInnerHTML(parentElem, htmlString) { 21 | // Jump through some hoops to avoid using innerHTML... 22 | 23 | var range = parentElem.ownerDocument.createRange(); 24 | range.selectNodeContents(parentElem); 25 | 26 | var docFrag = range.createContextualFragment(htmlString); 27 | docFrag = sanitizeDocumentFragment(docFrag); 28 | 29 | range.deleteContents(); 30 | range.insertNode(docFrag); 31 | range.detach(); 32 | }; 33 | 34 | 35 | // Approximating equivalent to assigning to `outerHTML` -- completely replaces 36 | // the target element with `htmlString`. 37 | // Note that some caveats apply that also apply to `outerHTML`: 38 | // - The element must be in the DOM. Otherwise an exception will be thrown. 39 | // - The original element has been removed from the DOM, but continues to exist. 40 | // Any references to it (such as the one passed into this function) will be 41 | // references to the original. 42 | function saferSetOuterHTML(elem, htmlString) { 43 | if (!isElementinDocument(elem)) { 44 | throw new Error('Element must be in document'); 45 | return; 46 | } 47 | 48 | var range = elem.ownerDocument.createRange(); 49 | range.selectNode(elem); 50 | 51 | var docFrag = range.createContextualFragment(htmlString); 52 | docFrag = sanitizeDocumentFragment(docFrag); 53 | 54 | range.deleteContents(); 55 | range.insertNode(docFrag); 56 | range.detach(); 57 | }; 58 | 59 | 60 | // Removes potentially harmful elements and attributes from `docFrag`. 61 | // Returns a santized copy. 62 | function sanitizeDocumentFragment(docFrag) { 63 | var i; 64 | 65 | // Don't modify the original 66 | docFrag = docFrag.cloneNode(true); 67 | 68 | var scriptTagElems = docFrag.querySelectorAll('script'); 69 | for (i = 0; i < scriptTagElems.length; i++) { 70 | scriptTagElems[i].parentNode.removeChild(scriptTagElems[i]); 71 | } 72 | 73 | function cleanAttributes(node) { 74 | var i; 75 | 76 | if (typeof(node.removeAttribute) === 'undefined') { 77 | // We can't operate on this node 78 | return; 79 | } 80 | 81 | // Remove event handler attributes 82 | for (i = node.attributes.length-1; i >= 0; i--) { 83 | if (node.attributes[i].name.match(/^on/)) { 84 | node.removeAttribute(node.attributes[i].name); 85 | } 86 | } 87 | } 88 | 89 | walkDOM(docFrag.firstChild, cleanAttributes); 90 | 91 | return docFrag; 92 | } 93 | 94 | 95 | // Walk the DOM, executing `func` on each element. 96 | // From Crockform. 97 | function walkDOM(node, func) { 98 | func(node); 99 | node = node.firstChild; 100 | while(node) { 101 | walkDOM(node, func); 102 | node = node.nextSibling; 103 | } 104 | } 105 | 106 | 107 | function isElementinDocument(element) { 108 | var doc = element.ownerDocument; 109 | while (element = element.parentNode) { 110 | if (element === doc) { 111 | return true; 112 | } 113 | } 114 | return false; 115 | } 116 | 117 | 118 | // Expose these functions 119 | var Utils = {}; 120 | Utils.saferSetInnerHTML = saferSetInnerHTML; 121 | Utils.saferSetOuterHTML = saferSetOuterHTML; 122 | Utils.sanitizeDocumentFragment = sanitizeDocumentFragment; 123 | 124 | var EXPORTED_SYMBOLS = ['Utils']; 125 | 126 | if (typeof module !== 'undefined') { 127 | module.exports = Utils; 128 | } else { 129 | this.Utils = Utils; 130 | this.EXPORTED_SYMBOLS = EXPORTED_SYMBOLS; 131 | } 132 | 133 | }).call(function() { 134 | return this || (typeof window !== 'undefined' ? window : global); 135 | }()); 136 | -------------------------------------------------------------------------------- /src/firefox/chrome/content/background-services-overlay.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------