diff --git a/README.md b/README.md index f31f731..e4bb50d 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Fernanda's look was inspired by the nice and quiet feeling of using [WordStar](h Fernanda got its name because I just really like the name a lot. But, as it turns out, Fernanda means an ["adventurous, bold journey"](https://en.wikipedia.org/wiki/Fernanda) (the kind one might be *called* to, say), and I think that's neat. Colorful conch shell icon. -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :honeybee: **Build** @@ -79,11 +79,14 @@ Among the other fonts used are: Solarized theme palettes by [@altercation](https://github.com/altercation/solarized) -Markdown preview support provided with: +[Markdown](https://www.markdownguide.org/)/[Fountain](https://fountain.io/) preview support provided with: - [Marked.js](https://github.com/markedjs/marked) -- and [Markdown.css](https://bitbucket.org/kevinburke/markdowncss) +- [Markdown.css](https://bitbucket.org/kevinburke/markdowncss) +- and [Fountain.js](https://github.com/mattdaly/Fountain.js) -[⏎](#top) +> **Note:** Markdown/Fountain support is, at the moment, extremely barebones! + +[:leftwards_arrow_with_hook:](#top) ## :star: **Features** @@ -95,7 +98,7 @@ Markdown preview support provided with: - Save backups (in [`{userdata}\backup\.rollback`](#folders)) - Global line, word, and character totals - Export to PDF or directory -- Markdown preview +- Markdown/Fountain preview --- @@ -153,7 +156,7 @@ If you want to manually rename, move, or delete items within a `.story` file via

-[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :floppy_disk: **Installation** @@ -179,7 +182,7 @@ You can grab the installer on the [Releases](https://github.com/fairybow/fernand They can be opened via the `Help` menu. -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :compass: **Roadmap** @@ -194,11 +197,11 @@ If I think of something big, I'll try to add it right here. Otherwise, these thi - Persist undo/redo stacks between file changes - Separators and possibly customizable file icons, for better mental organization at-a-glance - Simple storage of links and research materials -- Fountain preview/export support +- Markdown/Fountain export More to come. -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :smiley_cat: **Thanks** @@ -206,7 +209,7 @@ A major thanks to [@philipplenk](https://codemetas.de/) for their teaching and i A major thanks, too, to [@rikyoz](https://github.com/rikyoz/) for their tireless work on the very amazing [Bit7z library](https://github.com/rikyoz/bit7z). -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :hibiscus: **Screens** @@ -275,8 +278,8 @@ A major thanks, too, to [@rikyoz](https://github.com/rikyoz/) for their tireless -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) ## :heartpulse: **Bye** -[⏎](#top) +[:leftwards_arrow_with_hook:](#top) diff --git a/fernanda/docs/dependencies.md b/fernanda/docs/dependencies.md index db2ac2c..7747aa5 100644 --- a/fernanda/docs/dependencies.md +++ b/fernanda/docs/dependencies.md @@ -29,6 +29,7 @@ - text.h (+ version.h) - preview.h - layout.h + - userdata.h (+ path.h) - resource.h - path.h - splitter.h @@ -280,6 +281,7 @@ ### preview.h ``` #include "layout.h" +#include "userdata.h" #include #include diff --git a/fernanda/docs/fountain.js/LICENSE.md b/fernanda/docs/fountain.js/LICENSE.md new file mode 100644 index 0000000..9bc30bb --- /dev/null +++ b/fernanda/docs/fountain.js/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Matt Daly + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/fernanda/docs/fountain.js/readme.md b/fernanda/docs/fountain.js/readme.md new file mode 100644 index 0000000..d4ef22e --- /dev/null +++ b/fernanda/docs/fountain.js/readme.md @@ -0,0 +1,110 @@ +fountain-js +=========== + +fountain-js is a JavaScript based parser for the screenplay format [Fountain](http://fountain.io/). + +You can [try fountain-js out](http://mattdaly.github.com/Fountain.js/). The file system currently uses the HTML 5 File API, which means not all browsers support it, you'll be told if yours doesn't - I'm working on compatiblity. CSS styling isn't complete, so some elements aren't placed correctly and the text spacing might not be quite right, and, as you'll see, individual pages aren't currently supported either. + +# Syntax Support + +As of version 0.1.8 the full Fountain syntax is supported. + +Currently fountain-js supports a limited range of key-value pairs for title pages - + +* Title, Credit, Author/s, Source, Notes, Draft date, Date, Contact, Copyright + +Work is being done to make title page parsing friendlier, allowing custom key-value pairs, but as of version 0.1.0 only the above are supported. + +Instructions +============ + +fountain-js accepts a string value to it's parse function, therefore opening or retrieving files is down to you - open the file, retrieve it's string contents and pass it to fountain-js. + +The parser doesn't simply change scripts lines in to html, it first splits the script down line by line and generates an array of tokens representing each script element. This tokenized array provides the opportunity to iterate over a script in it's raw state and do some analysis (e.g. we could search for every character element with the name STEEL, we could do this against the HTML using jQuery but it'd be a slower process). By default, fountain-js simply returns the generated html, but you can also gain access to those tokens if you ask for them (more on that below). + +To use Fountain.js, either import it within an HTML page or require it as a module inside Node.js (it's available to both by default). + +``` + + +``` + +fountain-js supports both sync and async functionality, the function names remain the same. For async, simply attach a callback to the parse function and handle the result inside that callback. + +``` + + +``` + +The output provided by fountain-js is of a specific format. The output to both sync and async functions is an object literal of the format { title: '...', html: { title_page: '...', script: '...' } }. If a title was set in the original file the title property will be set to it (as plain text with formatting removed), the html.title_page property contains the html generated for any title page syntax definitions, and the html.script property contains the html generated for the rest of the script. + +``` + + +``` + +If you want access to the tokens that fountain-js generates, simply attach a true parameter to your parse calls. Requesting tokens adds a tokens property to the output generated by fountain-js. That tokens property is an array of object literals, each of the form { type: '...', text: '...' }, some elements have additional properties (e.g. the type 'scene_heading' also has a property called 'scene-number' if a scene number was attached to that specific scene heading). It should also be noted that fountain-js iterates the script from bottom to top, therefore requesting tokens requires reversing the array before fountain-js returns you the data, this might add a slight delay (milliseconds in most cases) on large scripts. + +``` + + +``` + +The tokens for the Brick & Steel sample found on the fountain.io website would look as follows (just a small sample): + +``` +[ + ..., + { type="scene_heading", text="EXT. BRICK'S PATIO - DAY", scene_number="1"}, + { type="action", text="A gorgeous day. The su...emplating -- something."}, + { type="action", text="The SCREEN DOOR slides ...es with two cold beers."}, + { type="dialogue_begin"}, + { type="character", text="STEEL"}, + { type="dialogue", text="Beer's ready!"}, + { type="dialogue_end"}, + { type="dialogue_begin"}, + { type="character", text="BRICK"}, + { type="dialogue", text="Are they cold?"}, + { type="dialogue_end"}, + { type="page_break"}, + { type="dialogue_begin"}, + { type="character", text="STEEL"}, + { type="dialogue", text="Does a bear crap in the woods?"}, + { type="dialogue_end"}, + { type="action", text="Steel sits. They laugh at the dumb joke."}, + { type="dialogue_begin"}, + { type="character", text="STEEL"}, + { type="parenthetical", text="(beer raised)"}, + { type="dialogue", text="To retirement."}, + { type="dialogue_end"}, + { type="dialogue_begin"}, + { type="character", text="BRICK"}, + { type="dialogue", text="To retirement."}, + { type="dialogue_end"} + ... +``` + +As you can see fountain-js attaches some extra tokens, such as 'dialogue_begin' and 'dialogue_end'. These are used to block together sections, in the case of dialogue it allows fountain-js to attach a dual dialogue property to blocks of dialogue. diff --git a/fernanda/docs/todo.md b/fernanda/docs/todo.md index b84259d..533c4d5 100644 --- a/fernanda/docs/todo.md +++ b/fernanda/docs/todo.md @@ -145,6 +145,7 @@ - [x] ~~May not need `makePosix()`; Bit7z only accepts `\\` paths for searching~~ ### Resource +- [ ] DataPair should be split up. A lot of instances' lhs-es aren't even paths. - [x] ~~There surely must be a smarter way to incorporate `.otf` into the fonts RC list (applies to MainWindow, too)~~ - [x] ~~Convert to `std::filesystem::path`~~ diff --git a/fernanda/docs/zips/Fountain.js.zip b/fernanda/docs/zips/Fountain.js.zip new file mode 100644 index 0000000..7a18607 Binary files /dev/null and b/fernanda/docs/zips/Fountain.js.zip differ diff --git a/fernanda/fernanda.vcxproj b/fernanda/fernanda.vcxproj index d078b0a..5534ced 100644 --- a/fernanda/fernanda.vcxproj +++ b/fernanda/fernanda.vcxproj @@ -111,7 +111,8 @@ - + + diff --git a/fernanda/fernanda.vcxproj.filters b/fernanda/fernanda.vcxproj.filters index fd599be..be9100a 100644 --- a/fernanda/fernanda.vcxproj.filters +++ b/fernanda/fernanda.vcxproj.filters @@ -131,12 +131,15 @@ Utilities - - Resource Files\Preview - Utilities + + Resource Files\Preview + + + Resource Files\Preview + diff --git a/fernanda/res/preview.qrc b/fernanda/res/preview.qrc index 8ae12e1..54c265a 100644 --- a/fernanda/res/preview.qrc +++ b/fernanda/res/preview.qrc @@ -1,7 +1,10 @@ - preview/index.html + preview/include/fountain.min.js + preview/include/fountain-js.css preview/include/markdown.css preview/include/marked.min.js + preview/fountain.html + preview/markdown.html diff --git a/fernanda/res/preview/fountain.html b/fernanda/res/preview/fountain.html new file mode 100644 index 0000000..08da33a --- /dev/null +++ b/fernanda/res/preview/fountain.html @@ -0,0 +1,27 @@ + + + + + + + + + +
+ + + diff --git a/fernanda/res/preview/include/fountain-js.css b/fernanda/res/preview/include/fountain-js.css new file mode 100644 index 0000000..e16b019 --- /dev/null +++ b/fernanda/res/preview/include/fountain-js.css @@ -0,0 +1,305 @@ +body +{ + background-color: #f7f7f7; + color: #333333; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 14px; + margin: 0; +} + +a { color: #ED303C; text-decoration: none; } +a:hover { text-decoration: underline; } + +.container +{ + margin: 0 auto; + position: relative; + width: 850px; +} + +header +{ + background-color: #454545; + color: #F0F0D8; + font-size: 13px; + height: 40px; + line-height: 40px; + width: 100%; +} + +header::-moz-selection, header::selection { background: #454545; color: #fff; } + +/* dock */ +#dock +{ + margin: 0; +} + +#dock header +{ + margin-bottom: 25px; +} + +#dock header h1 +{ + background: url('../images/fountain-24.png') 0 9px no-repeat; + color: #fff; + font-size: 16px; + margin: 0; + padding-left: 34px; +} + +#dock blockquote { background: #fff; margin: 0; padding: 10px; } +#dock p.more-information { font-size: 12px; margin: 5px 0 25px 0; padding: 0; text-align: right; } +#dock #file-api { background: #fff; border: 3px dashed #454545; display: none; margin-top: 75px; text-align: center; } +#dock #file-api.over { border-color: #ED303C; cursor: pointer; } +#dock #file-api p { font-weight: bold; margin: 125px auto; } +#dock p.error { background: #fff url('../images/warning.png') 10px 10px no-repeat; font-weight: bold; margin-top: 75px; padding: 15px 15px 15px 50px; } + +/* workspace */ +#workspace +{ + color: #333333; + display: none; + float: left; + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + position: relative; + width: 100%; +} + +#workspace header.dimmed +{ + background-color: transparent; +} + +#workspace header.dimmed p +{ + color: #333333; + font-weight: bold; +} + + +#workspace header ul, +#workspace header li, +#workspace header p +{ + display: inline; + float: left; + margin: 0; + padding: 0; +} + +#workspace header p +{ + color: #fff; + font-size: 15px; + height: 20px; + line-height: 20px; + margin-top: 10px; + text-align: center; + width: 44%; +} + +#workspace header ul +{ + padding: 0; + width: 27%; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +#workspace #toolbar { float: right; margin-right: 3px; } +#workspace #inspector li, #workspace #toolbar li { height: 16px; line-height: 16px; margin: 12px 12px 12px 0; position: relative; width: 16px; } +#workspace #toolbar li { float: right; margin: 12px 0 12px 12px; text-align: right; } +#workspace #inspector li a, #workspace #toolbar li a { cursor: pointer; color: #3C3D36; display: block; height: 16px; text-indent: 16px; overflow: hidden; width: 16px; } +#workspace #inspector li a:hover, #workspace #toolbar li a:hover { text-decoration: none; } + +#workspace #inspector li a:hover:after, #workspace #toolbar li a:hover:after +{ + background: #ED303C; + border-radius: 4px; + color: #fff; + content: attr(data-tooltip); + left: -5px; + padding: 3px 7px 4px 30px; + position: absolute; + text-align: left; + text-indent: 0; + top: -3px; +} + +/* toolbar */ +#workspace #toolbar li a:hover:after { background-position: 5px 3px; background-repeat: no-repeat; } + +#workspace #toolbar li.resize { background: url('../images/toolbar/resize.small.png') top left no-repeat; } +#workspace #toolbar li.resize:hover { background-image: url('../images/toolbar/resize.small-hover.png'); } +#workspace #toolbar li.resize.large { background: url('../images/toolbar/resize.large.png') top left no-repeat; } +#workspace #toolbar li.resize.large:hover { background-image: url('../images/toolbar/resize.large-hover.png'); } +#workspace #toolbar li.resize a:hover:after { background-image: url('../images/toolbar/resize.small-hover.png'); width: 78px; } +#workspace #toolbar li.resize.large a:hover:after { background-image: url('../images/toolbar/resize.large-hover.png'); } + +#workspace #toolbar li.dim { background: url('../images/toolbar/dim.reduce.png') top left no-repeat; } +#workspace #toolbar li.dim:hover { background-image: url('../images/toolbar/dim.reduce-hover.png'); } +#workspace #toolbar li.dim.increase { background: url('../images/toolbar/dim.increase.png') top left no-repeat; } +#workspace #toolbar li.dim.increase:hover { background-image: url('../images/toolbar/dim.increase-hover.png'); } +#workspace #toolbar li.dim a:hover:after { background-image: url('../images/toolbar/dim.reduce-hover.png'); width: 83px; } +#workspace #toolbar li.dim.increase a:hover:after { background-image: url('../images/toolbar/dim.increase-hover.png'); } + +#workspace #toolbar li.dock { background: url('../images/toolbar/dock.png') top left no-repeat; } +#workspace #toolbar li.dock:hover { background-image: url('../images/toolbar/dock-hover.png'); } +#workspace #toolbar li.dock a:hover:after { background-image: url('../images/toolbar/dock-hover.png'); width: 90px; } +#workspace #toolbar li.dock.over { background: url('../images/toolbar/dock-drop.png') no-repeat; cursor: pointer; } + +/* inspector */ +#workspace #inspector li a:hover:after { background-position: 5px 3px; background-repeat: no-repeat; } +/* +#workspace #inspector li.fountain { background: url('../images/toolbar/fountain.png') top left no-repeat; } +#workspace #inspector li.fountain:hover { background-image: url('../images/toolbar/fountain-hover.png'); } +#workspace #inspector li.fountain a:hover:after { background-image: url('../images/toolbar/fountain-hover.png'); width: 98px; } +*/ + +/* notifications */ +#workspace .notification::-moz-selection, #workspace .notification::selection { background: #454545; } +#workspace .notification +{ + background: #454545 url('../images/notification.png') 6px 6px no-repeat; + border-radius: 4px; + color: #fff; + display: none; + font-size: 13px; + padding: 6px 8px 6px 28px; + position: absolute; + right: 5px; + top: -8px; +} + +/* #51445F - moon warrior */ +#workspace #script { margin: 25px auto 0 auto; width: 850px; } + +#workspace .page::-moz-selection, #workspace .page::selection { background: #ED303C; color: #fff; } +#workspace #script .page +{ + background: #fff; + border: 1px solid #d2d2d2; + border-radius: 2px; + color: #222; + cursor: text; + font: Courier,"Courier New",monospace; + letter-spacing: 0 !important; + font-family: 'Courier Final Draft', Courier, Courier New, monospace; + line-height: 107.5%; + margin-bottom: 25px; + position: relative; + text-align: left; + width: 100%; + z-index: 200; + -webkit-box-shadow: 0 0 5px rgba(0,0,0,0.1); + -moz-box-shadow: 0 0 5px rgba(0,0,0,0.1); + box-shadow: 0 0 5px rgba(0,0,0,0.1); + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +#workspace #script.dpi72 .page { font-size: 12px; padding: 72px 72px 72px 108px; } +#workspace #script.dpi100 .page { font-size: 16px; padding: 100px 100px 100px 150px; } +#workspace #script.dpi150 .page { font-size: 33px; padding: 150px 150px 150px 225px; } + +#workspace #script.dpi72 .page h1, +#workspace #script.dpi72 .page h2, +#workspace #script.dpi72 .page h3, +#workspace #script.dpi72 .page h4, +#workspace #script.dpi72 .page p { font-size: 12px; font-weight: normal; } + +#workspace #script.dpi100 .page h1, +#workspace #script.dpi100 .page h2, +#workspace #script.dpi100 .page h3, +#workspace #script.dpi100 .page h4, +#workspace #script.dpi100 .page p { font-size: 17px; font-weight: normal; } + +#workspace #script.dpi150 .page h1, +#workspace #script.dpi150 .page h2, +#workspace #script.dpi150 .page h3, +#workspace #script.dpi150 .page h4, +#workspace #script.dpi150 .page p { font-size: 33px; font-weight: normal; } + +/* US Paper */ +#workspace #script.us-letter.dpi72 { width: 612px; } /* us letter - 72 dpi - 612px x 792px - margins: 1" 1" 1" 1.5" */ +#workspace #script.us-letter.dpi100 { width: 850px; } /* us letter - 100 dpi - 850px x 1100px - margins: 1" 1" 1" 1.5" */ +#workspace #script.us-letter.dpi150 { width: 1275px; } /* us letter - 150 dpi - 1275px x 1650px - margins: 1" 1" 1" 1.5" */ + +#workspace #script.us-letter.dpi72 .page { min-height: 792px; } /* min height temporary until proper paging is implemented */ +#workspace #script.us-letter.dpi100 .page { min-height: 1100px; } /* min height temporary until proper paging is implemented */ +#workspace #script.us-letter.dpi150 .page { min-height: 1650px; } /* min height temporary until proper paging is implemented */ + +#workspace #script.us-letter.dpi72 .page.title-page { height: 792px; } /* temp for title page until paging is implemented */ +#workspace #script.us-letter.dpi100 .page.title-page { height: 1100px; } /* temp for title page until paging is implemented */ +#workspace #script.us-letter.dpi150 .page.title-page { height: 1650px; } /* temp for title page until paging is implemented */ + +/* A4 Paper */ +#workspace #script.a4.dpi72 { width: 595px; } /* us letter - 72 dpi - 595px x 842px - margins: 1" 1" 1" 1.5" */ +#workspace #script.a4.dpi100 { width: 827px; } /* us letter - 72 dpi - 827px x 1169px - margins: 1" 1" 1" 1.5" */ +#workspace #script.a4.dpi150 { width: 1250px; } /* us letter - 72 dpi - 1250px x 1754px - margins: 1" 1" 1" 1.5" */ + +#workspace #script.a4.dpi72 .page { height: 842px; } +#workspace #script.a4.dpi100 .page { height: 1169px; } +#workspace #script.a4.dpi150 .page { height: 1754px; } + +/* title page */ +#workspace #script .title-page h1 { margin-top: 50%; margin-bottom: 34px; text-align: center; width: 90.5%; } +#workspace #script .title-page p.credit { text-align: center; width: 90.5%; } +#workspace #script .title-page p.author, +#workspace #script .title-page p.authors { margin-bottom: 32px; margin-top: 0; text-align: center; width: 90.5%; } +#workspace #script .title-page p.source { margin-bottom: 32px; text-align: center; width: 90.5%; } +#workspace #script .title-page p.notes { bottom: 350px; position: absolute; right: 0; text-align: right; } +#workspace #script.dpi72 .title-page p.notes { bottom: 252px; right: 72px; } +#workspace #script.dpi100 .title-page p.notes { bottom: 350px; right: 100px; } +#workspace #script.dpi150 .title-page p.notes { bottom: 525px; right: 150px; } +#workspace #script .title-page p.date, +#workspace #script .title-page p.draft-date { bottom: 250px; position: absolute; right: 0; text-align: right; } +#workspace #script.dpi72 .title-page p.date, +#workspace #script.dpi72 .title-page p.draft-date { bottom: 180px; right: 72px; } +#workspace #script.dpi100 .title-page p.date, +#workspace #script.dpi100 .title-page p.draft-date { bottom: 250px; right: 100px; } +#workspace #script.dpi150 .title-page p.date, +#workspace #script.dpi150 .title-page p.draft-date { bottom: 375px; right: 150px; } +#workspace #script .title-page p.contact { bottom: 100px; position: absolute; right: 0; text-align: right; } +#workspace #script.dpi72 .title-page p.contact { bottom: 72px; right: 72px; } +#workspace #script.dpi100 .title-page p.contact { bottom: 100px; right: 100px; } +#workspace #script.dpi150 .title-page p.contact { bottom: 150px; right: 150px; } +#workspace #script .title-page p.copyright { bottom: 100px; position: absolute; text-align: left; } +#workspace #script.dpi72 .title-page p.copyright { bottom: 72px; } +#workspace #script.dpi100 .title-page p.copyright { bottom: 100px; } +#workspace #script.dpi150 .title-page p.copyright { bottom: 150px; } + +/* script */ +#workspace #script .page h2 { text-align: right; } +#workspace #script .page h2.left-aligned { text-align: left } +#workspace #script .page h3 { position: relative; } +#workspace #script .page h3:before { color: #bbb; content: attr(id); font-weight: bold; left: -45px; position: absolute; } +#workspace #script .page h3:after { color: #bbb; content: attr(id); font-weight: bold; right: -45px; position: absolute; } + +#workspace #script .page div.dialogue { margin-left: auto; margin-right: auto; width: 68%; } +#workspace #script .page div.dialogue h4 { margin-bottom: 0; margin-left: 23%; } +#workspace #script .page div.dialogue p.parenthetical { margin-bottom: 0; margin-top: 0; margin-left: 11%;} +#workspace #script .page div.dialogue p { margin-bottom: 0; margin-top: 0; } + +#workspace #script .page div.dual-dialogue { margin: 2em 0 0.9em 2%; auto; width: 95%; } +#workspace #script .page div.dual-dialogue div.dialogue { display: inline-block; margin: 0; width: 45%; } +#workspace #script .page div.dual-dialogue div.dialogue h4 { margin-top: 0;} +#workspace #script .page div.dual-dialogue div.dialogue.right { float: right; } + +#workspace #script .page p { } +#workspace #script .page p.centered { text-align: center; width: 92.5%; } + +#workspace #script .page p.section { color: #bbb; margin-left: -30px; } +#workspace #script .page p.synopsis { color: #bbb; margin-left: -20px; } + +#workspace #script .page span.italic { font-style: italic; } +#workspace #script .page span.bold { font-weight: bold; } +#workspace #script .page span.underline { text-decoration: underline; diff --git a/fernanda/res/preview/include/fountain.min.js b/fernanda/res/preview/include/fountain.min.js new file mode 100644 index 0000000..3402949 --- /dev/null +++ b/fernanda/res/preview/include/fountain.min.js @@ -0,0 +1,12 @@ +(function(){var d={title_page:/^((?:title|credit|author[s]?|source|notes|draft date|date|contact|copyright)\:)/gim,scene_heading:/^((?:\*{0,3}_?)?(?:(?:int|ext|est|i\/e)[. ]).+)|^(?:\.(?!\.+))(.+)/i,scene_number:/( *#(.+)# *)/,transition:/^((?:FADE (?:TO BLACK|OUT)|CUT TO BLACK)\.|.+ TO\:)|^(?:> *)(.+)/,dialogue:/^([A-Z*_]+[0-9A-Z (._\-')]*)(\^?)?(?:\n(?!\n+))([\s\S]+)/,parenthetical:/^(\(.+\))$/,action:/^(.+)/g,centered:/^(?:> *)(.+)(?: *<)(\n.+)*/g,section:/^(#+)(?: *)(.*)/,synopsis:/^(?:\=(?!\=+) *)(.*)/, +note:/^(?:\[{2}(?!\[+))(.+)(?:\]{2}(?!\[+))$/,note_inline:/(?:\[{2}(?!\[+))([\s\S]+?)(?:\]{2}(?!\[+))/g,boneyard:/(^\/\*|^\*\/)$/g,page_break:/^\={3,}$/,line_break:/^ {2}$/,emphasis:/(_|\*{1,3}|_\*{1,3}|\*{1,3}_)(.+)(_|\*{1,3}|_\*{1,3}|\*{1,3}_)/g,bold_italic_underline:/(_{1}\*{3}(?=.+\*{3}_{1})|\*{3}_{1}(?=.+_{1}\*{3}))(.+?)(\*{3}_{1}|_{1}\*{3})/g,bold_underline:/(_{1}\*{2}(?=.+\*{2}_{1})|\*{2}_{1}(?=.+_{1}\*{2}))(.+?)(\*{2}_{1}|_{1}\*{2})/g,italic_underline:/(?:_{1}\*{1}(?=.+\*{1}_{1})|\*{1}_{1}(?=.+_{1}\*{1}))(.+?)(\*{1}_{1}|_{1}\*{1})/g, +bold_italic:/(\*{3}(?=.+\*{3}))(.+?)(\*{3})/g,bold:/(\*{2}(?=.+\*{2}))(.+?)(\*{2})/g,italic:/(\*{1}(?=.+\*{1}))(.+?)(\*{1})/g,underline:/(_{1}(?=.+_{1}))(.+?)(_{1})/g,splitter:/\n{2,}/g,cleaner:/^\n+|\n+$/,standardizer:/\r\n|\r/g,whitespacer:/^\t+|^ {3,}/gm},n={note:"<\!-- $1 --\>",line_break:"
",bold_italic_underline:'$2',bold_underline:'$2',italic_underline:'$2',bold_italic:'$2', +bold:'$2',italic:'$2',underline:'$2',lexer:function(c){if(c){for(var j="underline,italic,bold,bold_italic,italic_underline,bold_underline,bold_italic_underline".split(","),k=j.length,g,b,c=c.replace(d.note_inline,n.note).replace(/\\\*/g,"[star]").replace(/\\_/g,"[underline]").replace(/\n/g,n.line_break);k--;)g=j[k],b=d[g],b.test(c)&&(c=c.replace(b,n[g]));return c.replace(/\[star\]/g,"*").replace(/\[underline\]/g, +"_").trim()}}},h=function(c,d){return h.parse(c,d)};h.parse=function(c,j,k){var g;void 0===k&&"function"===typeof j&&(k=j,j=void 0);for(var b=c.replace(d.boneyard,"\n$1\n").replace(d.standardizer,"\n").replace(d.cleaner,"").replace(d.whitespacer,"").split(d.splitter),f=b.length,e,a,l,i,h,m,c=[];f--;)if(e=b[f],d.title_page.test(e)){a=e.replace(d.title_page,"\n$1").split(d.splitter).reverse();i=0;for(h=a.length;i|"+b.text+"");g=b.text.replace("
"," ").replace(/<(?:.|\n)*?>/g,"");break;case "credit":f.push('

'+b.text+"

");break;case "author":f.push('

'+ +b.text+"

");break;case "authors":f.push('

'+b.text+"

");break;case "source":f.push('

'+b.text+"

");break;case "notes":f.push('

'+b.text+"

");break;case "draft_date":f.push('

'+b.text+"

");break;case "date":f.push('

'+b.text+"

");break;case "contact":f.push('

'+b.text+"

");break;case "copyright":f.push('");break;case "scene_heading":a.push("':">")+b.text+"");break;case "transition":a.push("

"+b.text+"

");break;case "dual_dialogue_begin":a.push('
');break;case "dialogue_begin":a.push('
');break;case "character":a.push("

"+b.text+"

");break;case "parenthetical":a.push('

'+b.text+"

");break;case "dialogue":a.push("

"+b.text+"

");break;case "dialogue_end":a.push("
"); +break;case "dual_dialogue_end":a.push("
");break;case "section":a.push('

'+b.text+"

");break;case "synopsis":a.push('

'+b.text+"

");break;case "note":a.push("<\!-- "+b.text+"--\>");break;case "boneyard_begin":a.push("<\!-- ");break;case "boneyard_end":a.push(" --\>");break;case "action":a.push("

"+b.text+"

");break;case "centered":a.push('

'+b.text+"

");break;case "page_break":a.push("
");break; +case "line_break":a.push("
")}g={title:g,html:{title_page:f.join(""),script:a.join("")},tokens:j?c.reverse():void 0};g="function"===typeof k?k(g):g;return g};"undefined"!==typeof module?module.exports=h:this.fountain=h}).call(this); \ No newline at end of file diff --git a/fernanda/res/preview/index.html b/fernanda/res/preview/markdown.html similarity index 90% rename from fernanda/res/preview/index.html rename to fernanda/res/preview/markdown.html index 5b5ec9b..02cf852 100644 --- a/fernanda/res/preview/index.html +++ b/fernanda/res/preview/markdown.html @@ -2,7 +2,7 @@ - + @@ -23,4 +23,4 @@ ); - \ No newline at end of file + diff --git a/fernanda/src/mainwindow.cpp b/fernanda/src/mainwindow.cpp index c582624..f48f60a 100644 --- a/fernanda/src/mainwindow.cpp +++ b/fernanda/src/mainwindow.cpp @@ -129,6 +129,7 @@ void MainWindow::connections() connect(this, &MainWindow::sendItems, pane, &Pane::receiveItems); connect(this, &MainWindow::sendEditsList, pane, &Pane::receiveEditsList); connect(this, &MainWindow::askPaneAdd, pane, &Pane::add); + connect(this, &MainWindow::askSetPreviewType, preview, &Preview::setType); connect(this, &MainWindow::askSetCountdown, timer, &Tool::setCountdown); connect(editor, &Editor::askFontSliderZoom, this, &MainWindow::handleFontSlider); connect(editor, &Editor::askHasProject, this, &MainWindow::replyHasProject); @@ -284,6 +285,10 @@ void MainWindow::makeSetMenu() Resource::DataPair{ "Top", "Top" }, Resource::DataPair{ "Bottom", "Bottom" } }; + QVector preview_types_list = { + Resource::DataPair{ "Fountain", "Fountain" }, + Resource::DataPair{ "Markdown", "Markdown" } + }; QVector timer_values_list = { Resource::DataPair{ "300", "5 minutes" }, Resource::DataPair{ "600", "10 minutes" }, @@ -315,6 +320,7 @@ void MainWindow::makeSetMenu() auto character_count_set = new QAction(tr("&Character count"), this); auto line_count_set = new QAction(tr("&Line count"), this); auto word_count_set = new QAction(tr("&Word count"), this); + previewTypes = makeViewToggles(preview_types_list, [&]() { askSetPreviewType(getSetting(previewTypes)); }); timerValues = makeViewToggles(timer_values_list, [&]() { askSetCountdown(getSetting(timerValues)); }); windowThemes = makeViewToggles(window_themes_list, &MainWindow::setStyle); editorFonts = makeViewToggles(fonts_list, [&]() @@ -345,6 +351,7 @@ void MainWindow::makeSetMenu() loadMenuToggle(character_count_set, UserData::IniGroup::Window, UserData::IniValue::CharCount, false); loadMenuToggle(line_count_set, UserData::IniGroup::Window, UserData::IniValue::LineCount, true); loadMenuToggle(word_count_set, UserData::IniGroup::Window, UserData::IniValue::WordCount, true); + loadViewConfig(previewTypes->actions(), UserData::IniGroup::Window, UserData::IniValue::PreviewType, "Markdown"); loadViewConfig(timerValues->actions(), UserData::IniGroup::Window, UserData::IniValue::ToolTimer, "900"); loadViewConfig(windowThemes->actions(), UserData::IniGroup::Window, UserData::IniValue::WindowTheme, ":/themes/window/Light.fernanda_window"); fontSlider->setValue(UserData::loadConfig(UserData::IniGroup::Editor, UserData::IniValue::EditorFontSize, 16, UserData::Type::Int).toInt()); @@ -361,6 +368,8 @@ void MainWindow::makeSetMenu() indicator_items->addSeparator(); for (const auto& action : { character_count_set, line_count_set, word_count_set }) indicator_items->addAction(action); + auto preview_types = set->addMenu(tr("&Preview")); + preview_types->addActions(previewTypes->actions()); auto timer_values = set->addMenu(tr("&Timer")); timer_values->addActions(timerValues->actions()); auto window_themes = set->addMenu(tr("&Window theme")); diff --git a/fernanda/src/mainwindow.h b/fernanda/src/mainwindow.h index a65e6b3..36b4461 100644 --- a/fernanda/src/mainwindow.h +++ b/fernanda/src/mainwindow.h @@ -66,6 +66,7 @@ class MainWindow : public QMainWindow QActionGroup* tabStops = new QActionGroup(this); QActionGroup* wrapModes = new QActionGroup(this); QActionGroup* colorBarAlignments = new QActionGroup(this); + QActionGroup* previewTypes = new QActionGroup(this); QActionGroup* timerValues = new QActionGroup(this); QSlider* fontSlider = new QSlider(Qt::Horizontal); Indicator* indicator = new Indicator(this); @@ -165,6 +166,7 @@ private slots: void askPaneAdd(Path::Type type); void askSetBarAlignment(QString alignment); void askSetCountdown(int seconds); + void askSetPreviewType(QString typeName); void askToggleScrolls(bool checked); void askToggleStartUpBar(bool checked); void askUpdateCounts(const QString text, const int blockCount); diff --git a/fernanda/src/preview.cpp b/fernanda/src/preview.cpp index af079c4..b071584 100644 --- a/fernanda/src/preview.cpp +++ b/fernanda/src/preview.cpp @@ -19,9 +19,13 @@ Preview::Preview(QWidget* parent) setContentsMargins(0, 0, 0, 0); } -void Preview::setText(const QString& text) +void Preview::setType(QString typeName) { - content.setText(text); + (typeName == "Fountain") + ? type = Type::Fountain + : type = Type::Markdown; + UserData::saveConfig(UserData::IniGroup::Window, UserData::IniValue::PreviewType, typeName); + refresh(); } bool Preview::eventFilter(QObject* watched, QEvent* event) @@ -33,6 +37,12 @@ bool Preview::eventFilter(QObject* watched, QEvent* event) check(isVisible()); return true; } + else if (event->type() == QEvent::Resize) + { + if (size().width() == 0) + refresh(); + return true; + } return false; } @@ -62,7 +72,16 @@ void Preview::open() QWebChannel* channel = new QWebChannel(view_value); channel->registerObject(QStringLiteral("content"), &content); page->setWebChannel(channel); - view_value->setUrl(QUrl("qrc:/preview/index.html")); + (type == Type::Fountain) + ? view_value->setUrl(QUrl("qrc:/preview/fountain.html")) + : view_value->setUrl(QUrl("qrc:/preview/markdown.html")); +} + +void Preview::refresh() +{ + if (!isVisible()) return; + hide(); + show(); } // preview.cpp, Fernanda diff --git a/fernanda/src/preview.h b/fernanda/src/preview.h index f455e41..60c4d27 100644 --- a/fernanda/src/preview.h +++ b/fernanda/src/preview.h @@ -13,6 +13,7 @@ #pragma once #include "layout.h" +#include "userdata.h" #include #include @@ -72,15 +73,25 @@ class Preview : public QWidget public: Preview(QWidget* parent = nullptr); - void setText(const QString& text); + void setText(const QString& text) { content.setText(text); } + +public slots: + void setType(QString typeName); private: + enum class Type { + Fountain, + Markdown + }; + std::unique_ptr view; WebDocument content; + Type type = Type::Markdown; bool eventFilter(QObject* watched, QEvent* event); void check(bool isVisible); void open(); + void refresh(); }; // preview.h, Fernanda diff --git a/fernanda/src/userdata.cpp b/fernanda/src/userdata.cpp index 8b8b3b7..3f23f93 100644 --- a/fernanda/src/userdata.cpp +++ b/fernanda/src/userdata.cpp @@ -146,6 +146,9 @@ const QString UserData::valueName(IniValue valueType) case IniValue::MostRecent: result = "data____most_recent_project"; break; + case IniValue::PreviewType: + result = "set_____preview_type"; + break; case IniValue::SplitterPosition: result = "window__splitter_position"; break; diff --git a/fernanda/src/userdata.h b/fernanda/src/userdata.h index 1d2ed1d..db35104 100644 --- a/fernanda/src/userdata.h +++ b/fernanda/src/userdata.h @@ -45,6 +45,7 @@ namespace UserData LineCount, LinePosition, MostRecent, + PreviewType, SplitterPosition, StayAwake, TabStop, diff --git a/fernanda/src/version.h b/fernanda/src/version.h index 10719ec..feadddc 100644 --- a/fernanda/src/version.h +++ b/fernanda/src/version.h @@ -12,8 +12,8 @@ #pragma once -#define VER_FILEVERSION 0,17,1,37 -#define VER_FILEVERSION_STR "v0.17.1-beta37" +#define VER_FILEVERSION 0,18,0,38 +#define VER_FILEVERSION_STR "v0.18.0-beta38" #define VER_PRODUCTVERSION VER_FILEVERSION #define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR #define VER_COMPANYNAME_STR "@fairybow"