From: Radek Czajka Date: Fri, 16 Jul 2021 15:41:52 +0000 (+0200) Subject: Nicer visual editor first steps. X-Git-Url: https://git.mdrn.pl/redakcja.git/commitdiff_plain/57a3ad0520284210f945b0e2f91f67233e49d07e?ds=sidebyside Nicer visual editor first steps. --- diff --git a/src/redakcja/settings/__init__.py b/src/redakcja/settings/__init__.py index d9d45e45..ba7a738a 100644 --- a/src/redakcja/settings/__init__.py +++ b/src/redakcja/settings/__init__.py @@ -135,7 +135,7 @@ PIPELINE = { 'css/gallery.css', 'css/history.css', 'css/summary.css', - 'css/html.css', + 'css/html.scss', 'css/imgareaselect-default.css', 'css/dialogs.css', diff --git a/src/redakcja/static/css/html.css b/src/redakcja/static/css/html.css deleted file mode 100644 index 214e92a5..00000000 --- a/src/redakcja/static/css/html.css +++ /dev/null @@ -1,689 +0,0 @@ -/* Style widoku HTML. Nie należy tu ustawiać position ani marginesów */ -.htmlview { - counter-reset: main; - font-size: 16px; - font-family: "Georgia", "Times New Roman", serif; - line-height: 1.5em; - padding: 3em 3em 3em 45px; - overflow-y: scroll; - overflow-x: auto; -} - -.htmlview[data-tag-names-visible] { - padding-left: 90px; -} - -.htmlview *[x-node = 'RDF'][x-ns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'] { - display: none; -} - -.htmlview * { - position: relative; -} - -.htmlview div { - max-width: 36em; -} - -.htmlview #toc { - display: none; -} - -.htmlview a { - color: blue; - text-decoration: none; -} - -.htmlview a:hover { - text-decoration: none; -} - -.htmlview .nazwa_utworu { - font-size: 3em; - margin: 1.5em 0; - text-align: center; - line-height: 1.5em; - font-weight: bold; -} - -.htmlview .autor_utworu, -.htmlview .dzielo_nadrzedne, -.htmlview .naglowek_czesc, -.htmlview .srodtytul, -.htmlview .naglowek_akt -{ - font-size: 2em; - margin: 1.5em 0 0; - font-weight: bold; - line-height: 1.5em; -} - -.htmlview .podtytul, -.htmlview .naglowek_scena, -.htmlview .naglowek_rozdzial - font-size: 1.5em; - margin: 1.5em 0 0; - font-weight: normal; - line-height: 1.5em; -} - -.htmlview .naglowek_podrozdzial, -.htmlview .naglowek_osoba -{ - font-size: 1em; - margin: 1.5em 0 0; - line-height: 1.5em; - font-weight: bold; -} - -.htmlview p { - margin: 0; -} - -.htmlview #footnotes div { - margin: 1.5em 0 0 0; -} - -.htmlview #footnotes p { - margin-left: 2.5em; - font-size: 0.875em; -} - -.htmlview blockquote { - font-size: 0.875em; -} - -.htmlview pre { - overflow-x: auto; /* Use horizontal scroller if needed; for Firefox 2, not needed in Firefox 3 */ - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ /* - width: 99%; */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ -} - -/* ============= */ -/* = Numbering = */ -/* ============= */ -.htmlview .anchor { - position: relative; - margin: 0; - left: -2.2em; - color: #777; - font-size: 12px; - width: 2em; - text-align: center; - padding: 0.25em 0.7em; - line-height: 1.5em; -} - -.htmlview .anchor:hover, .htmlview .anchor:active { - color: #FFF; - background-color: #CCC; -} - -/* =================== */ -/* = Custom elements = */ -/* =================== */ -.htmlview .autor_utwor { - font-size: 0.5em; - display: block; - line-height: 1.5em; - margin-bottom: 0.25em; -} - -.htmlview .dzielo_nadrzedne { - /* */ -} - -.htmlview .podtytul { - /* */ -} - -.htmlview .didaskalia { - font-style: italic; - margin: 0.5em 0 0 1.5em; -} - -.htmlview .kwestia { - margin: 0.5em 0 0; -} - -.htmlview .strofa { - margin: 1.5em 0 0.5em auto; -} - -/* wersy */ -.htmlview *[x-verse]:after { - content: "\feff"; -} - -.htmlview .strofa .wers_wciety, .htmlview .strofa .wers_wciety[data-wlf-typ='1'] { - margin-left: 1em; -} - -.htmlview .strofa .wers_wciety[data-wlf-typ='2'], .htmlview .strofa .wers_cd { - margin-left: 2em; -} - -.htmlview .strofa .wers_wciety[data-wlf-typ='3'] { - margin-left: 3em; -} - -.htmlview .strofa .wers_wciety[data-wlf-typ='4'] { - margin-left: 4em; -} - -.htmlview .strofa .wers_wciety[data-wlf-typ='5'] { - margin-left: 5em; -} - -.htmlview .strofa .wers_wciety[data-wlf-typ='6'] { - margin-left: 6em; -} - -.htmlview .strofa .wers_do_prawej { - text-align: right; -} - -/* błędne wersy */ -.htmlview *:not(.strofa) > *[x-verse]::after { - content: "Ten wers znajduje się poza strofą."; - display: inline; - background: red; - font-size: 8pt; - border: 1px solid black; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - padding: 1px 1em; - margin-left: 1em; - vertical-align: super; -} - -.htmlview .kwestia .strofa { - margin: 0; -} - -.htmlview .akap, .htmlview .akap_cd, .htmlview .akap_dialog { - text-align: justify; - margin: 1.5em 0 0; -} - -.htmlview .motto_container { - display: inline-block; - margin: 1.5em 0 0; - clear: right; -} - -.htmlview .motto { - text-align: justify; - font-style: italic; -} - -.htmlview p.motto_podpis { - position: relative; - right: -3em; - text-align: right; -} - -.htmlview div.fragment { - border-bottom: 0.1em solid #999; - padding-bottom: 1.5em; -} - -.htmlview div.nota p, .htmlview div.dedykacja p { - text-align: right; - font-style: italic; -} - -.htmlview div.ramka { - border: 1px darkgray solid; -} - -.htmlview .nota_red { - background-color: #eee; - border: 1px solid #888; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - display: block; - padding: 0 1em 1em 1em; -} - -.htmlview hr.sekcja_swiatlo { - margin: 2em 0; - visibility: hidden; -} - -.htmlview hr.separator_linia { - margin: 1.5em 0; - border: none; - border-bottom: 0.1em solid #000; -} - -.htmlview hr.sekcja_asterysk { - border: none; - padding: 0; - margin: 1.5em 0; - text-align: center; -} - -.htmlview hr.sekcja_asterysk:after { - content: "*"; -} - -.htmlview div.lista_osob ol { - list-style: none; - padding: 0 0 0 1.5em; -} - -.htmlview p.miejsce_czas { - font-style: italic; -} - -.htmlview .mat, .htmlview .slowo_obce, .htmlview .tytul_dziela, .htmlview .didaskalia { - font-style: italic; -} - - -.htmlview .indeks_dolny { - font-style: normal; - vertical-align: sub; - font-size: .9em; -} - -.htmlview .wyroznienie { - letter-spacing: 0.1em; -} - -.htmlview .osoba { - font-style: normal; - font-variant: small-caps; -} - -.htmlview em.wieksze_odstepy { - font-style: normal; - word-spacing: 1em; -} - -.htmlview .ilustr img { - max-width: 100%; -} - -.htmlview .parse-warning { - display: block; - font-size: 10pt; - background: #C0C0C0; - margin: 1em; -} - -.parse-warning .message { - color: purple; - font-weight: bold; -} - -/* Uwaga/Extra */ -.htmlview .uwaga { - background-color: #96e0e4; - border: 1px solid black; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - display: block; - font-size: 10pt; - line-height: 12pt; - padding: 2px 1em; - float: right; - max-width: 20%; - max-height: 24pt; - margin-left: 0.5em; - z-index: 500; -} - -div[x-node] > .uwaga { - float: none; - padding: 0.5em 1em; - margin: 1em; - max-width: 100%; - max-height: 100%; - border: 1px solid black; -} - -.htmlview .uwaga:hover { - max-height: 100%; -} - -.htmlview .annotation-inline-box .uwaga { - max-height: 100%; -} - -/* Motywy */ -/* ======================== */ -/* = Footnotes and themes = */ -/* ======================== */ -.htmlview .begin, .htmlview .end { - background: green; -} - -.htmlview .motyw { - /* position: absolute; */ - float: right; - left: auto; - clear: right; - width: 10em; - - font-style: normal; - font-weight: normal; - font-variant: normal; - letter-spacing: 0; - text-transform: none; - text-decoration: none; - - font-size: 13px; - line-height: 18px; - background-color: #fff; - /* border: 1px solid gray; - - border-right: none; - */ - z-index: 1; - -moz-user-select: -moz-none; - -webkit-user-select: none; - user-select: none; - margin-right: -12em; - text-align: left; - color: #999; -} - -.htmlview .canon { - color: black; -} - -.htmlview .noncanon { - color: #d00; -} - -.htmlview .motyw[x-editable] { - border-left: 4px solid #DDD; - padding: 0.2em 0.2em 0.2em 0.5em; - margin-top: 0.2em; -} - -/* - * Przypisy - */ -/* Znaczniki w tekście */ -.annotation { - font-style: normal; -} - -.htmlview .annotation:before { - content: "[" counter(main) "]"; - counter-increment: main; - vertical-align: super; - text-decoration: none; - font-size: 66%; -} - -.htmlview .annotation:hover { - background-color: #ffcccc; -} -.htmlview .pe .annotation:hover { - background-color: #96e0e4; -} -*.htmlview *.annotation-inline-box { - position: static; -} - -/* - * Przypisy w tekście - */ - -.htmlview .annotation-inline-box:hover > span[x-annotation-box]{ - display: block; -} - -.htmlview .annotation-inline-box > span[x-annotation-box] { - display: none; - width: 300px; - font-size: 10pt; - line-height: 12pt; - font-weight: normal; - font-style: normal; - background: #fffe93; - border: 1px solid black; - border-radius: 10px; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - padding: 3px 5px; - text-decoration: none; - z-index: 600; -} - -/* - * Przypisy na końcu utworu (aktualnie nieuzywane) - */ -.htmlview .annotations-block { - counter-reset: secondary; -} - -.htmlview .annotations-block .annotation-body { - position: relative; - padding-left: 2.5em; - padding-top: 0.2em; -} - -.htmlview .annotations-block .annotation-backref { - position: absolute; - top: 0.4em; - left: -0.4em; - width: 2.5em; - text-align: right; -} - -.htmlview .annotations-block .annotation-backref:before { - content: "[" counter(secondary) "]"; - counter-increment: secondary; -} - -/* - * EDITABLE ELEMENTS - */ -.htmlview *[x-editable] { - position: relative; - padding: 2px; - margin-left: 0; - border: 1px solid transparent; -} - -/* focused editable element */ -.htmlview *[x-editable]:hover { - z-index: 900; -} - -.htmlview *[x-editable][x-open] { - visibility: hidden; -} - -.edit-button, .delete-button, .accept-button, .tytul-button, .wyroznienie-button, .slowo-button, .znak-button { - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; - font-size: 16px; - line-height: 1.5; - position: absolute; - top: -28px; - left: -1px; - width: 72px; - height: 28px; - display: block; - /* margin: 4px 0 2px 0;*/ - padding: 5px 5px 2px 5px; - background-color: #FAFAFA; - /* z-index: 3000;*/ - /* color: #FFF; - z-index: 1500; - */ - border: 1px solid #DDD; - border-bottom: none; -} - -.delete-button { - left: 70px; -} - -.tytul-button { - left:150px; - width:100px; -} - -.wyroznienie-button { - left:250px; - width:100px; -} -.slowo-button { - left:350px; - width:100px; -} -.znak-button { - left:450px; - width:100px; -} - -.edit-button:hover, .edit-button:active, -.delete-button:hover, .delete-button:active, -.accept-button:hover, .accept-button:active, -.tytul-button:hover, .tytul-button:active, -.wyroznienie-button:hover, .wyroznienie-button:active, -.slowo-button:hover, .slowo-button:active, -.znak-button:hover, .znak-button:active { - /* color: #FFF;*/ - background-color: #999; - color: #FFF; -} - -/* - * VISIBILITY RULES - */ -.default-menu { - visibility: inherit; - opacity: 0.2; -} - -.default-menu:hover { - opacity: 1; - z-index: 5000; -} - -.htmlview *[x-annotation-box] > .default-menu { - opacity: 1; -} - -.htmlview *[x-editable][x-open] > .default-menu { - visibility: hidden; -} - -.htmlview *[x-editable][x-open] *[x-annotation-box] > .default-menu { - visibility: hidden; -} - -.htmlview *[x-editable] > .edit-menu { - visibility: hidden; -} - -.htmlview *[x-editable] *[x-annotation-box] > .edit-menu { - visibility: hidden; -} - -.htmlview *[x-editable][x-open] > .edit-menu { - visibility: visible; -} - -.htmlview *[x-editable][x-open] *[x-annotation-box] > .edit-menu { - visibility: visible; -} - -.html-editarea { - border: 0; - background-color: gray; - padding: 1px; - z-index: 2000; - position: absolute; - text-align: left; -} - -.html-editarea textarea { - position: absolute; - top: 0; - margin: 0; - padding: 0; - width: 100%; - height: 100%; - z-index: 0; - font-size: 10pt; - font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; - line-height: 1.25; - /* background-color: ivory;*/ -} - -.htmlview .out-of-flow-text { - display: block; - font-family: monospace; - border: 2px solid red !important; - white-space: pre-line; -} - -.htmlview .out-of-flow-text::before { - content: "Tekst w tej ramce nie jest otagowany!"; - background-color: #ff6c6c; - color: black; - font-size: 10pt; - line-height: 12pt; - border: 1px solid black; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - padding: 5px 1em; - margin: 0 0 0 1em; - text-align: justify; - display: inline; - float: right; - max-width: 25%; -} - -.unknown-tag { - background-color: yellow; - margin: -0.25em; - padding: 0.25em; - border: 1px solid orange; -} - -.alien { - color: red; -} - -/* specialChars */ -#specialCharsContainer { - text-align: center; - width: 640px; - height: 400px; - padding:20px; - background-color: gray; - position: absolute; - top: 20px; - right: 20px; - z-index:10000; - overflow:auto; -} -#specialCharsContainer a { - color: white; - font-weight: bold; -} - -#tableSpecialChars td input { - background-color: transparent; - border:0; - color: white; -} - -#tableSpecialChars td input.recentSymbol { - background-color: white; - border:0; - color: black; -} diff --git a/src/redakcja/static/css/html.scss b/src/redakcja/static/css/html.scss new file mode 100644 index 00000000..b716bc59 --- /dev/null +++ b/src/redakcja/static/css/html.scss @@ -0,0 +1,722 @@ +/* Style widoku HTML. Nie należy tu ustawiać position ani marginesów */ +.htmlview { + counter-reset: main; + font-size: 16px; + font-family: "Georgia", "Times New Roman", serif; + line-height: 1.5em; + padding: 3em 3em 3em 45px; + overflow-y: scroll; + overflow-x: auto; + + + #caret { + display: inline-block; + width: 2px; + height: 1em; + overflow: hidden; + margin-left:-1px; + margin-right: -1px; + + textarea { + border: none; + background: #888; + + &:focus { + background: red; + } + } + } +} + +.htmlview[data-tag-names-visible] { + padding-left: 90px; +} + +.htmlview *[x-node = 'RDF'][x-ns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'] { + display: none; +} + +.htmlview * { + position: relative; +} + +.htmlview div { + max-width: 36em; +} + +.htmlview #toc { + display: none; +} + +.htmlview a { + color: blue; + text-decoration: none; +} + +.htmlview a:hover { + text-decoration: none; +} + +.htmlview .nazwa_utworu { + font-size: 3em; + margin: 1.5em 0; + text-align: center; + line-height: 1.5em; + font-weight: bold; +} + +.htmlview .autor_utworu, +.htmlview .dzielo_nadrzedne, +.htmlview .naglowek_czesc, +.htmlview .srodtytul, +.htmlview .naglowek_akt +{ + font-size: 2em; + margin: 1.5em 0 0; + font-weight: bold; + line-height: 1.5em; +} + +.htmlview .podtytul, +.htmlview .naglowek_scena, +.htmlview .naglowek_rozdzial +{ + font-size: 1.5em; + margin: 1.5em 0 0; + font-weight: normal; + line-height: 1.5em; +} + +.htmlview .naglowek_podrozdzial, +.htmlview .naglowek_osoba +{ + font-size: 1em; + margin: 1.5em 0 0; + line-height: 1.5em; + font-weight: bold; +} + +.htmlview p { + margin: 0; +} + +.htmlview #footnotes div { + margin: 1.5em 0 0 0; +} + +.htmlview #footnotes p { + margin-left: 2.5em; + font-size: 0.875em; +} + +.htmlview blockquote { + font-size: 0.875em; +} + +.htmlview pre { + overflow-x: auto; /* Use horizontal scroller if needed; for Firefox 2, not needed in Firefox 3 */ + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ /* + width: 99%; */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +/* ============= */ +/* = Numbering = */ +/* ============= */ +.htmlview .anchor { + position: relative; + margin: 0; + left: -2.2em; + color: #777; + font-size: 12px; + width: 2em; + text-align: center; + padding: 0.25em 0.7em; + line-height: 1.5em; +} + +.htmlview .anchor:hover, .htmlview .anchor:active { + color: #FFF; + background-color: #CCC; +} + +/* =================== */ +/* = Custom elements = */ +/* =================== */ +.htmlview .autor_utwor { + font-size: 0.5em; + display: block; + line-height: 1.5em; + margin-bottom: 0.25em; +} + +.htmlview .dzielo_nadrzedne { + /* */ +} + +.htmlview .podtytul { + /* */ +} + +.htmlview .didaskalia { + font-style: italic; + margin: 0.5em 0 0 1.5em; +} + +.htmlview .kwestia { + margin: 0.5em 0 0; +} + +.htmlview .strofa { + margin: 1.5em 0 0.5em auto; +} + +/* wersy */ +.htmlview *[x-verse]:after { + content: "\feff"; +} + +.htmlview .strofa .wers_wciety, .htmlview .strofa .wers_wciety[data-wlf-typ='1'] { + margin-left: 1em; +} + +.htmlview .strofa .wers_wciety[data-wlf-typ='2'], .htmlview .strofa .wers_cd { + margin-left: 2em; +} + +.htmlview .strofa .wers_wciety[data-wlf-typ='3'] { + margin-left: 3em; +} + +.htmlview .strofa .wers_wciety[data-wlf-typ='4'] { + margin-left: 4em; +} + +.htmlview .strofa .wers_wciety[data-wlf-typ='5'] { + margin-left: 5em; +} + +.htmlview .strofa .wers_wciety[data-wlf-typ='6'] { + margin-left: 6em; +} + +.htmlview .strofa .wers_do_prawej { + text-align: right; +} + +/* błędne wersy */ +.htmlview *:not(.strofa) > *[x-verse]::after { + content: "Ten wers znajduje się poza strofą."; + display: inline; + background: red; + font-size: 8pt; + border: 1px solid black; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + padding: 1px 1em; + margin-left: 1em; + vertical-align: super; +} + +.htmlview .kwestia .strofa { + margin: 0; +} + +.htmlview .akap, .htmlview .akap_cd, .htmlview .akap_dialog { + text-align: justify; + margin: 1.5em 0 0; +} + +.htmlview .motto_container { + display: inline-block; + margin: 1.5em 0 0; + clear: right; +} + +.htmlview .motto { + text-align: justify; + font-style: italic; +} + +.htmlview p.motto_podpis { + position: relative; + right: -3em; + text-align: right; +} + +.htmlview div.fragment { + border-bottom: 0.1em solid #999; + padding-bottom: 1.5em; +} + +.htmlview div.nota p, .htmlview div.dedykacja p { + text-align: right; + font-style: italic; +} + +.htmlview div.ramka { + border: 1px darkgray solid; +} + +.htmlview .nota_red { + background-color: #eee; + border: 1px solid #888; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + display: block; + padding: 0 1em 1em 1em; +} + +.htmlview hr.sekcja_swiatlo { + margin: 2em 0; + visibility: hidden; +} + +.htmlview hr.separator_linia { + margin: 1.5em 0; + border: none; + border-bottom: 0.1em solid #000; +} + +.htmlview hr.sekcja_asterysk { + border: none; + padding: 0; + margin: 1.5em 0; + text-align: center; +} + +.htmlview hr.sekcja_asterysk:after { + content: "*"; +} + +.htmlview div.lista_osob ol { + list-style: none; + padding: 0 0 0 1.5em; +} + +.htmlview p.miejsce_czas { + font-style: italic; +} + +.htmlview .mat, .htmlview .slowo_obce, .htmlview .tytul_dziela, .htmlview .didaskalia { + font-style: italic; +} + + +.htmlview .indeks_dolny { + font-style: normal; + vertical-align: sub; + font-size: .9em; +} + +.htmlview { + .wyroznienie { + // letter-spacing: 0.1em; + background: #dfd; + border: 1px solid #0f0; + } + .slowo_obce { + background: #ddf; + border: 1px solid #88f; + } + .tytul_dziela { + background: #fdf; + border: 1px solid #f8f; + } +} + + +.htmlview .osoba { + font-style: normal; + font-variant: small-caps; +} + +.htmlview em.wieksze_odstepy { + font-style: normal; + word-spacing: 1em; +} + +.htmlview .ilustr img { + max-width: 100%; +} + +.htmlview .parse-warning { + display: block; + font-size: 10pt; + background: #C0C0C0; + margin: 1em; +} + +.parse-warning .message { + color: purple; + font-weight: bold; +} + +/* Uwaga/Extra */ +.htmlview .uwaga { + background-color: #96e0e4; + border: 1px solid black; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + display: block; + font-size: 10pt; + line-height: 12pt; + padding: 2px 1em; + float: right; + max-width: 20%; + max-height: 24pt; + margin-left: 0.5em; + z-index: 500; +} + +div[x-node] > .uwaga { + float: none; + padding: 0.5em 1em; + margin: 1em; + max-width: 100%; + max-height: 100%; + border: 1px solid black; +} + +.htmlview .uwaga:hover { + max-height: 100%; +} + +.htmlview .annotation-inline-box .uwaga { + max-height: 100%; +} + +/* Motywy */ +/* ======================== */ +/* = Footnotes and themes = */ +/* ======================== */ +.htmlview .begin, .htmlview .end { + background: green; +} + +.htmlview .motyw { + /* position: absolute; */ + float: right; + left: auto; + clear: right; + width: 10em; + + font-style: normal; + font-weight: normal; + font-variant: normal; + letter-spacing: 0; + text-transform: none; + text-decoration: none; + + font-size: 13px; + line-height: 18px; + background-color: #fff; + /* border: 1px solid gray; + + border-right: none; + */ + z-index: 1; + -moz-user-select: -moz-none; + -webkit-user-select: none; + user-select: none; + margin-right: -12em; + text-align: left; + color: #999; +} + +.htmlview .canon { + color: black; +} + +.htmlview .noncanon { + color: #d00; +} + +.htmlview .motyw[x-editable] { + border-left: 4px solid #DDD; + padding: 0.2em 0.2em 0.2em 0.5em; + margin-top: 0.2em; +} + +/* + * Przypisy + */ +/* Znaczniki w tekście */ +.annotation { + font-style: normal; +} + +.htmlview .annotation:before { + content: "[" counter(main) "]"; + counter-increment: main; + vertical-align: super; + text-decoration: none; + font-size: 66%; +} + +.htmlview .annotation:hover { + background-color: #ffcccc; +} +.htmlview .pe .annotation:hover { + background-color: #96e0e4; +} +*.htmlview *.annotation-inline-box { + position: static; +} + +/* + * Przypisy w tekście + */ + +.htmlview .annotation-inline-box:hover > span[x-annotation-box]{ + display: block; +} + +.htmlview .annotation-inline-box > span[x-annotation-box] { + display: none; + width: 300px; + font-size: 10pt; + line-height: 12pt; + font-weight: normal; + font-style: normal; + background: #fffe93; + border: 1px solid black; + border-radius: 10px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + padding: 3px 5px; + text-decoration: none; + z-index: 600; +} + +/* + * Przypisy na końcu utworu (aktualnie nieuzywane) + */ +.htmlview .annotations-block { + counter-reset: secondary; +} + +.htmlview .annotations-block .annotation-body { + position: relative; + padding-left: 2.5em; + padding-top: 0.2em; +} + +.htmlview .annotations-block .annotation-backref { + position: absolute; + top: 0.4em; + left: -0.4em; + width: 2.5em; + text-align: right; +} + +.htmlview .annotations-block .annotation-backref:before { + content: "[" counter(secondary) "]"; + counter-increment: secondary; +} + +/* + * EDITABLE ELEMENTS + */ +.htmlview *[x-editable] { + position: relative; + padding: 2px; + margin-left: 0; + border: 1px solid transparent; +} + +/* focused editable element */ +.htmlview *[x-editable]:hover { + z-index: 900; +} + +.htmlview *[x-editable][x-open] { + visibility: hidden; +} + +.edit-button, .delete-button, .accept-button, .tytul-button, .wyroznienie-button, .slowo-button, .znak-button { + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + font-size: 16px; + line-height: 1.5; + position: absolute; + top: -28px; + left: -1px; + width: 72px; + height: 28px; + display: block; + /* margin: 4px 0 2px 0;*/ + padding: 5px 5px 2px 5px; + background-color: #FAFAFA; + /* z-index: 3000;*/ + /* color: #FFF; + z-index: 1500; + */ + border: 1px solid #DDD; + border-bottom: none; +} + +.delete-button { + left: 70px; +} + +.tytul-button { + left:150px; + width:100px; +} + +.wyroznienie-button { + left:250px; + width:100px; +} +.slowo-button { + left:350px; + width:100px; +} +.znak-button { + left:450px; + width:100px; +} + +.edit-button:hover, .edit-button:active, +.delete-button:hover, .delete-button:active, +.accept-button:hover, .accept-button:active, +.tytul-button:hover, .tytul-button:active, +.wyroznienie-button:hover, .wyroznienie-button:active, +.slowo-button:hover, .slowo-button:active, +.znak-button:hover, .znak-button:active { + /* color: #FFF;*/ + background-color: #999; + color: #FFF; +} + +/* + * VISIBILITY RULES + */ +.default-menu { + visibility: inherit; + opacity: 0.2; +} + +.default-menu:hover { + opacity: 1; + z-index: 5000; +} + +.htmlview *[x-annotation-box] > .default-menu { + opacity: 1; +} + +.htmlview *[x-editable][x-open] > .default-menu { + visibility: hidden; +} + +.htmlview *[x-editable][x-open] *[x-annotation-box] > .default-menu { + visibility: hidden; +} + +.htmlview *[x-editable] > .edit-menu { + visibility: hidden; +} + +.htmlview *[x-editable] *[x-annotation-box] > .edit-menu { + visibility: hidden; +} + +.htmlview *[x-editable][x-open] > .edit-menu { + visibility: visible; +} + +.htmlview *[x-editable][x-open] *[x-annotation-box] > .edit-menu { + visibility: visible; +} + +.html-editarea { + border: 0; + background-color: gray; + padding: 1px; + z-index: 2000; + position: absolute; + text-align: left; +} + +.html-editarea textarea { + position: absolute; + top: 0; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + z-index: 0; + font-size: 10pt; + font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; + line-height: 1.25; + /* background-color: ivory;*/ +} + +.htmlview .out-of-flow-text { + display: block; + font-family: monospace; + border: 2px solid red !important; + white-space: pre-line; +} + +.htmlview .out-of-flow-text::before { + content: "Tekst w tej ramce nie jest otagowany!"; + background-color: #ff6c6c; + color: black; + font-size: 10pt; + line-height: 12pt; + border: 1px solid black; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + padding: 5px 1em; + margin: 0 0 0 1em; + text-align: justify; + display: inline; + float: right; + max-width: 25%; +} + +.unknown-tag { + background-color: yellow; + margin: -0.25em; + padding: 0.25em; + border: 1px solid orange; +} + +.alien { + color: red; +} + +/* specialChars */ +#specialCharsContainer { + text-align: center; + width: 640px; + height: 400px; + padding:20px; + background-color: gray; + position: absolute; + top: 20px; + right: 20px; + z-index:10000; + overflow:auto; +} +#specialCharsContainer a { + color: white; + font-weight: bold; +} + +#tableSpecialChars td input { + background-color: transparent; + border:0; + color: white; +} + +#tableSpecialChars td input.recentSymbol { + background-color: white; + border:0; + color: black; +} diff --git a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js index 517c878e..82920fde 100644 --- a/src/redakcja/static/js/wiki/view_editor_wysiwyg.js +++ b/src/redakcja/static/js/wiki/view_editor_wysiwyg.js @@ -1,4 +1,229 @@ -(function($){ +(function($) { + class Caret { + constructor(view) { + self = this; + self.view = view; + self.singleClick = false; + + let caret = this.element = $(''); + + // When user writes into caret, add it to the document. + $('textarea', caret).on('input', function() { + let v = $(this).val(); + $(this).val(''); + self.insertChar(v); + + }); + + // On click on x-node element, set caret position. + self.view.on('click', '*[x-node]', function(e) { + if (e.redakcja_caret_inserted) return; + e.redakcja_caret_inserted = true; + + if (self.singleClick) { + self.singleClick = false; + return; + } + + self.detach(); + + var selection = window.getSelection(); + if (!selection.isCollapsed) return; + + self.singleClick = true; + setTimeout(function() { + if (self.singleClick) { + self.element.insertBefore( + selection.anchorNode.splitText( + selection.anchorOffset + ) + ) + self.focus(); + } + self.singleClick = false; + }, 250); + + }); + + self.view.on('keydown', function(e) { + // TODO: + // Enter (split block) + // delete selection? + + // cases: + // we are in (no going up) + // we are in (can go up) + // we are next to (can go inside) + + switch (e.key) { + case "ArrowRight": + if (e.shiftKey) { + self.detach(); + return; + } + + self.moveRight(); + break; + case "ArrowLeft": + if (e.shiftKey) { + self.detach(); + return; + } + + self.moveLeft(); + break; + case "ArrowUp": + if (e.shiftKey) { + self.detach(); + return; + } + break; + case "ArrowDown": + if (e.shiftKey) { + self.detach(); + return; + } + break; + case "Backspace": + self.deleteBefore(); + break; + case "Delete": + self.deleteAfter(); + break; +// default: +// console.log('key', e.key, e.code); + } + }) + } + + get attached() { + return this.element.parent().length; + } + + detach() { + let p; + if (this.attached) { + p = this.element.parent()[0] + this.element.detach(); + p.normalize() + } + } + + focus() { + $("textarea", self.element).focus(); + } + + normalize() { + this.element.parent()[0].normalize(); + } + + insertChar(ch) { + $(document.createTextNode(ch)).insertBefore(this.element); + this.normalize(); + } + + deleteBefore() { + let contents = this.element.parent().contents(); + // Find the text before caret. + let textBefore = contents[contents.index(this.element) - 1]; + + // Should be text, but what if not? + textBefore.textContent = textBefore.textContent.substr(0, textBefore.textContent.length - 1); + this.normalize(); + + } + + deleteAfter() { + let contents = this.element.parent().contents(); + // Find the text after caret. + let textAfter = contents[contents.index(this.element) + 1]; + textAfter.textContent = textAfter.textContent.substr(1); + } + + moveLeft() { + this.move({ + move: -1, + edge: (i, l) => {return !i;}, + enter: (l) => {return l - 1;}, + splitTarget: (t) => {return t.splitText(t.length - 1);}, + noSplitTarget: (t) => {return t.splitText(t.length);}, + }) + } + + moveRight() { + this.move({ + move: 1, + edge: (i, l) => {return i == l - 1;}, + enter: (l) => {return 0;}, + splitTarget: (t) => {return t.splitText(1);}, + noSplitTarget: (t) => {return t;}, + }) + } + + move(opts) { + if (!this.attached) return; + this.normalize(); + + let contents = this.element.parent().contents(); + let index = contents.index(this.element); + let target, moved, oldparent; + + let parent = this.element.parent()[0]; + + if (opts.edge(index, contents.length)) { + // We're at the end -- what to do? + // can we go up? + + if (parent.nodeName == 'EM') { + oldparent = parent; + parent = parent.parentNode; + contents = $(parent).contents(); + index = contents.index(oldparent); + } + } + + index += opts.move; + target = contents[index]; + moved = false; + + while (target.nodeType == 1) { + // we've encountered a node. + // can we go inside? + + if (target.nodeName == 'EM') { + // enter + parent = $(target); + contents = parent.contents(); + index = opts.enter(contents.length); + target = contents[index]; + + // what if it has no elements? + } else { + // skip + index += opts.move; // again, what if end? + target = contents[index]; + moved = true; + } + + // if editable? + // what if editable but empty? + + } + + if (target.nodeType == 3) { + if (!moved) { + target = opts.splitTarget(target); + } else { + target = opts.noSplitTarget(target); + } + + this.element.insertBefore(target); + } + this.normalize(); + this.focus(); + } + } + /* Show theme to the user */ function selectTheme(themeId){ @@ -153,7 +378,7 @@ - + /* Insert theme using current selection */ function addTheme(){ @@ -210,10 +435,10 @@ point.setStart(container, offset); return point; } - + var spoint = createPoint(range.startContainer, range.startOffset); var epoint = createPoint(range.endContainer, range.endOffset); - + var mtag, btag, etag, errors; // insert theme-ref @@ -246,10 +471,18 @@ }); } - function addSymbol() { - if($('div.html-editarea textarea')[0]) { + function addSymbol(caret) { + let editArea; + + if (caret) { + editArea = $("textarea", caret.element)[0]; + } else { + editArea = $('div.html-editarea textarea')[0]; + } + + if(editArea) { var specialCharsContainer = $(""); - + var specialChars = [' ', 'Ą','ą','Ć','ć','Ę','ę','Ł','ł','Ń','ń','Ó','ó','Ś','ś','Ż','ż','Ź','ź','Á','á','À','à', 'Â','â','Ä','ä','Å','å','Ā','ā','Ă','ă','Ã','ã', 'Æ','æ','Ç','ç','Č','č','Ċ','ċ','Ď','ď','É','é','È','è', @@ -274,18 +507,18 @@ '„','”','„”','«','»','«»','»«','’','[',']','~','|','−','·', '×','÷','≈','≠','±','≤','≥','∈']; var tableContent = ""; - + for(var i in specialChars) { if(i % 14 == 0 && i > 0) { tableContent += ""; - } - tableContent += ""; + } + tableContent += ""; } - - tableContent += ""; + + tableContent += ""; $("body").append(specialCharsContainer); - - + + // localStorage for recently used characters - reading if (typeof(localStorage) != 'undefined') { if (localStorage.getItem("recentSymbols")) { @@ -293,45 +526,48 @@ var recentArray = recent.split(";"); var recentRow = ""; for(var i in recentArray.reverse()) { - recentRow += ""; + recentRow += ""; } - recentRow = "" + recentRow + ""; + recentRow = "" + recentRow + ""; } - } + } $("#tableSpecialChars").append(recentRow); $("#tableSpecialChars").append(tableContent); - + /* events */ - + $('.specialBtn').click(function(){ - var editArea = $('div.html-editarea textarea')[0]; var insertVal = $(this).val(); - + // if we want to surround text with quotes // not sure if just check if value has length == 2 - - if (insertVal.length == 2) { - var startTag = insertVal[0]; - var endTag = insertVal[1]; - var textAreaOpened = editArea; - //IE support - if (document.selection) { - textAreaOpened.focus(); - sel = document.selection.createRange(); - sel.text = startTag + sel.text + endTag; - } - //MOZILLA/NETSCAPE support - else if (textAreaOpened.selectionStart || textAreaOpened.selectionStart == '0') { - var startPos = textAreaOpened.selectionStart; - var endPos = textAreaOpened.selectionEnd; - textAreaOpened.value = textAreaOpened.value.substring(0, startPos) - + startTag + textAreaOpened.value.substring(startPos, endPos) + endTag + textAreaOpened.value.substring(endPos, textAreaOpened.value.length); - } + + if (caret) { + caret.insertChar(insertVal); + caret.focus(); } else { - // if we just want to insert single symbol - insertAtCaret(editArea, insertVal); + if (insertVal.length == 2) { + var startTag = insertVal[0]; + var endTag = insertVal[1]; + var textAreaOpened = editArea; + //IE support + if (document.selection) { + textAreaOpened.focus(); + sel = document.selection.createRange(); + sel.text = startTag + sel.text + endTag; + } + //MOZILLA/NETSCAPE support + else if (textAreaOpened.selectionStart || textAreaOpened.selectionStart == '0') { + var startPos = textAreaOpened.selectionStart; + var endPos = textAreaOpened.selectionEnd; + textAreaOpened.value = textAreaOpened.value.substring(0, startPos) + + startTag + textAreaOpened.value.substring(startPos, endPos) + endTag + textAreaOpened.value.substring(endPos, textAreaOpened.value.length); + } + } else { + insertAtCaret(editArea, insertVal); + } } - + // localStorage for recently used characters - saving if (typeof(localStorage) != 'undefined') { if (localStorage.getItem("recentSymbols")) { @@ -360,49 +596,49 @@ } } $(specialCharsContainer).remove(); - }); + }); $('#specialCharsClose').click(function(){ $(specialCharsContainer).remove(); - }); - + }); + } else { window.alert('Najedź na fragment tekstu, wybierz "Edytuj" i ustaw kursor na miejscu gdzie chcesz wstawić symbol.'); } } - function insertAtCaret(txtarea,text) { + function insertAtCaret(txtarea,text) { /* http://www.scottklarr.com/topic/425/how-to-insert-text-into-a-textarea-where-the-cursor-is/ */ - var scrollPos = txtarea.scrollTop; - var strPos = 0; + var scrollPos = txtarea.scrollTop; + var strPos = 0; var backStart = 0; var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? "ff" : (document.selection ? "ie" : false ) ); - if (br == "ie") { + if (br == "ie") { txtarea.focus(); - var range = document.selection.createRange(); - range.moveStart ('character', -txtarea.value.length); - strPos = backStart = range.text.length; + var range = document.selection.createRange(); + range.moveStart ('character', -txtarea.value.length); + strPos = backStart = range.text.length; } else if (br == "ff") { - strPos = txtarea.selectionStart; + strPos = txtarea.selectionStart; backStart = txtarea.selectionEnd; } - var front = (txtarea.value).substring(0,strPos); - var back = (txtarea.value).substring(backStart,txtarea.value.length); - txtarea.value=front+text+back; - strPos = strPos + text.length; - if (br == "ie") { - txtarea.focus(); - var range = document.selection.createRange(); - range.moveStart ('character', -txtarea.value.length); - range.moveStart ('character', strPos); - range.moveEnd ('character', 0); - range.select(); - } else if (br == "ff") { - txtarea.selectionStart = strPos; - txtarea.selectionEnd = strPos; - txtarea.focus(); - } - txtarea.scrollTop = scrollPos; - } + var front = (txtarea.value).substring(0,strPos); + var back = (txtarea.value).substring(backStart,txtarea.value.length); + txtarea.value=front+text+back; + strPos = strPos + text.length; + if (br == "ie") { + txtarea.focus(); + var range = document.selection.createRange(); + range.moveStart ('character', -txtarea.value.length); + range.moveStart ('character', strPos); + range.moveEnd ('character', 0); + range.select(); + } else if (br == "ff") { + txtarea.selectionStart = strPos; + txtarea.selectionEnd = strPos; + txtarea.focus(); + } + txtarea.scrollTop = scrollPos; + } /* open edition window for selected fragment */ function openForEdit($origin){ @@ -416,8 +652,8 @@ $box = $origin; } var x = $box[0].offsetLeft; - var y = $box[0].offsetTop; - + var y = $box[0].offsetTop; + var w = $box.outerWidth(); var h = $box.innerHeight(); @@ -425,7 +661,7 @@ w = Math.max(w, 400); h = Math.max(h, 60); if($('.htmlview div').offset().left + $('.htmlview div').width() > ($('.vsplitbar').offset().left - 480)){ - x = -(Math.max($origin.offset().left, $origin.width())); + x = -(Math.max($origin.offset().left, $origin.width())); } else { x = 100; } @@ -448,12 +684,12 @@ top: y, width: w }).appendTo($box[0].offsetParent || $box.parent()).show(); - + if ($origin.is('*[x-edit-no-format]')) { $('.akap-edit-button').remove(); } - + if ($origin.is('.motyw')) { $.themes.autocomplete($('textarea', $overlay)); } @@ -499,7 +735,7 @@ } else { source = $box[0]; } - + html2text({ element: source, stripOuter: true, @@ -524,7 +760,7 @@ xml = '<' + nodeName + '>' + insertedText + ''; } - + xml2html({ xml: xml, success: function(element){ @@ -545,11 +781,11 @@ alert('Błąd! ' + text); } }) - + var msg = $("

Pamiętaj, żeby zapisać swoje zmiany.

"); $("#base").prepend(msg); $('#base .saveNotify').fadeOut(3000, function(){ - $(this).remove(); + $(this).remove(); }); } @@ -572,9 +808,9 @@ addSymbol(); return false; } - - var myField = textAreaOpened; - + + var myField = textAreaOpened; + //IE support if (document.selection) { textAreaOpened.focus(); @@ -612,6 +848,7 @@ function VisualPerspective(options){ + perspective = this; var old_callback = options.callback; @@ -620,6 +857,7 @@ var button = $(''); if (!CurrentDocument.readonly) { + $('#html-view').bind('mousemove', function(event){ var editable = $(event.target).closest('*[x-editable]'); $('.active', element).not(editable).removeClass('active').children('.edit-button').remove(); @@ -652,7 +890,19 @@ $('#insert-theme-button').click(function(){ addTheme(); return false; - }); + }); + + + $(".insert-inline-tag").click(function() { + perspective.insertInlineTag($(this).attr('data-tag')); + return false; + }); + + $(".insert-char").click(function() { + console.log('perspective', perspective); + addSymbol(caret=perspective.caret); + return false; + }); $(document).on('click', '.edit-button', function(event){ event.preventDefault(); @@ -690,12 +940,19 @@ callback(); } + perspective = this; xml2html({ xml: this.doc.text, base: this.doc.getBase(), success: function(element){ + var htmlView = $('#html-view'); htmlView.html(element); + + perspective.caret = new Caret(htmlView); + + + htmlView.find('*[x-node]').dblclick(function(e) { if($(e.target).is('textarea')) return; @@ -746,6 +1003,73 @@ }); }; + VisualPerspective.prototype.insertInlineTag = function(tag) { + this.caret.detach(); + + let selection = window.getSelection(); + var n = selection.rangeCount; + if (n != 1) { + window.alert("Nie zaznaczono obszaru"); + return false + } + let range = selection.getRangeAt(0); + + // Make sure that: + // Both ends are in the same x-node container. + // TODO: That the container is a inline-text container. + let node = range.startContainer; + if (node.nodeType == node.TEXT_NODE) { + node = node.parentNode; + } + let endNode = range.endContainer; + if (endNode.nodeType == endNode.TEXT_NODE) { + endNode = endNode.parentNode; + } + if (node != endNode) { + window.alert("Zły obszar."); + return false; + } + + // We will construct a HTML element with the range selected. + let div = $(""); + + contents = $(node).contents(); + let startChildIndex = node == range.startContainer ? 0 : contents.index(range.startContainer); + let endChildIndex = contents.index(range.endContainer); + + current = range.startContainer; + if (current.nodeType == current.TEXT_NODE) { + current = current.splitText(range.startOffset); + } + while (current != range.endContainer) { + n = current.nextSibling; + $(current).appendTo(div); + current = n; + } + if (current.nodeType == current.TEXT_NODE) { + end = current.splitText(range.endOffset); + } + $(current).appendTo(div); + + html2text({ + element: div[0], + success: function(d) { + xml2html({ + xml: d = '<' + tag + '>' + d + '', + success: function(html) { + // What if no end? + node.insertBefore($(html)[0], end); + } + }); + }, + error: function(a, b) { + console.log(a, b); + } + }); + }; + + + $.wiki.VisualPerspective = VisualPerspective; })(jQuery); diff --git a/src/redakcja/static/js/wiki/xslt.js b/src/redakcja/static/js/wiki/xslt.js index 8e80a9c2..c1575fd1 100644 --- a/src/redakcja/static/js/wiki/xslt.js +++ b/src/redakcja/static/js/wiki/xslt.js @@ -17,7 +17,7 @@ function withStylesheets(code_block, onError) if (!xml2htmlStylesheet) { $.blockUI({message: 'Ładowanie arkuszy stylów...'}); $.ajax({ - url: STATIC_URL + 'xsl/wl2html_client.xsl?210706', + url: STATIC_URL + 'xsl/wl2html_client.xsl?210709', dataType: 'xml', timeout: 10000, success: function(data) { diff --git a/src/wiki/templates/wiki/tabs/wysiwyg_editor.html b/src/wiki/templates/wiki/tabs/wysiwyg_editor.html index 8b65bb55..c94e5b15 100644 --- a/src/wiki/templates/wiki/tabs/wysiwyg_editor.html +++ b/src/wiki/templates/wiki/tabs/wysiwyg_editor.html @@ -9,9 +9,24 @@ - + +
+ + + + +
{% endif %}