From 640066840e23367d9d13e92d786b877448ae9329 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Fri, 7 May 2021 10:43:41 +0200 Subject: Use a generic markup class to display externally rendered files and diffs (#15735) * creates and implements generic markup less class * How to give custom CSS to externally rendered html * Clarifies sources of CSS styling of markup * further clarification of sources of markup styling * rename _markdown to _markup * remove defunct import * fix orphaned reference * Update docs/content/doc/advanced/external-renderers.en-us.md * more renames markdown -> markup * do not suggest less customization * add back tokens * fix class whitespace, remove useless if-clause * remove unused csv-data rules * use named exports and rename functions * sort imports Co-authored-by: HarvsG <11440490+HarvsG@users.noreply.github.com> Co-authored-by: techknowlogick Co-authored-by: silverwind --- .../doc/advanced/external-renderers.en-us.md | 33 ++ templates/org/home.tmpl | 2 +- templates/repo/diff/box.tmpl | 2 +- templates/repo/diff/comment_form.tmpl | 4 +- templates/repo/diff/comments.tmpl | 2 +- templates/repo/editor/edit.tmpl | 2 +- templates/repo/empty.tmpl | 4 +- templates/repo/issue/comment_tab.tmpl | 2 +- templates/repo/issue/milestone_issues.tmpl | 2 +- templates/repo/issue/milestones.tmpl | 2 +- templates/repo/issue/view_content.tmpl | 4 +- templates/repo/issue/view_content/comments.tmpl | 8 +- templates/repo/release/list.tmpl | 2 +- templates/repo/release/new.tmpl | 2 +- templates/repo/settings/lfs_file.tmpl | 2 +- templates/repo/view_file.tmpl | 2 +- templates/repo/wiki/view.tmpl | 2 +- templates/user/profile.tmpl | 2 +- web_src/js/index.js | 38 +- web_src/js/markdown/anchors.js | 32 -- web_src/js/markdown/content.js | 5 - web_src/js/markdown/mermaid.js | 56 --- web_src/js/markup/anchors.js | 32 ++ web_src/js/markup/content.js | 5 + web_src/js/markup/mermaid.js | 56 +++ web_src/less/_base.less | 4 +- web_src/less/_markdown.less | 542 --------------------- web_src/less/_repository.less | 12 +- web_src/less/_review.less | 4 +- web_src/less/features/animations.less | 2 +- web_src/less/index.less | 4 +- web_src/less/markdown/mermaid.less | 13 - web_src/less/markup/content.less | 542 +++++++++++++++++++++ web_src/less/markup/mermaid.less | 13 + web_src/less/themes/theme-arc-green.less | 8 +- 35 files changed, 740 insertions(+), 707 deletions(-) delete mode 100644 web_src/js/markdown/anchors.js delete mode 100644 web_src/js/markdown/content.js delete mode 100644 web_src/js/markdown/mermaid.js create mode 100644 web_src/js/markup/anchors.js create mode 100644 web_src/js/markup/content.js create mode 100644 web_src/js/markup/mermaid.js delete mode 100644 web_src/less/_markdown.less delete mode 100644 web_src/less/markdown/mermaid.less create mode 100644 web_src/less/markup/content.less create mode 100644 web_src/less/markup/mermaid.less diff --git a/docs/content/doc/advanced/external-renderers.en-us.md b/docs/content/doc/advanced/external-renderers.en-us.md index 6b283ca2e1..71fabc529d 100644 --- a/docs/content/doc/advanced/external-renderers.en-us.md +++ b/docs/content/doc/advanced/external-renderers.en-us.md @@ -98,3 +98,36 @@ Once your configuration changes have been made, restart Gitea to have changes ta **Note**: Prior to Gitea 1.12 there was a single `markup.sanitiser` section with keys that were redefined for multiple rules, however, there were significant problems with this method of configuration necessitating configuration through multiple sections. + +## Customizing CSS +The external renderer is specified in the .ini in the format `[markup.XXXXX]` and the HTML supplied by your external renderer will be wrapped in a `
` with classes `markup` and `XXXXX`. The `markup` class provides out of the box styling (as does `markdown` if `XXXXX` is `markdown`). Otherwise you can use these classes to specifically target the contents of your rendered HTML. + +And so you could write some CSS: +```css +.markup.XXXXX html { + font-size: 100%; + overflow-y: scroll; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +.markup.XXXXX body { + color: #444; + font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif; + font-size: 12px; + line-height: 1.7; + padding: 1em; + margin: auto; + max-width: 42em; + background: #fefefe; +} + +.markup.XXXXX p { + color: orangered; +} +``` + +Add your stylesheet to your custom directory e.g `custom/public/css/my-style-XXXXX.css` and import it using a custom header file `custom/templates/custom/header.tmpl`: +```html + +``` diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 9b77ae6b3f..5e0a53aa56 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -11,7 +11,7 @@ {{if .IsOrganizationOwner}}{{svg "octicon-gear" 16 "mb-3"}}{{end}}
- {{if $.RenderedDescription}}

{{$.RenderedDescription|Str2html}}

{{end}} + {{if $.RenderedDescription}}

{{$.RenderedDescription|Str2html}}

{{end}}
{{if .Org.Location}}
{{svg "octicon-location"}} {{.Org.Location}}
{{end}} {{if .Org.Website}}
{{svg "octicon-link"}} {{.Org.Website}}
{{end}} diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index 9a2f7bdd7f..582b66d5db 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -164,7 +164,7 @@
-
+
{{$.i18n.Tr "loading"}}
diff --git a/templates/repo/diff/comment_form.tmpl b/templates/repo/diff/comment_form.tmpl index c82d32c214..628cd52dc2 100644 --- a/templates/repo/diff/comment_form.tmpl +++ b/templates/repo/diff/comment_form.tmpl @@ -22,12 +22,12 @@
-
+
{{.i18n.Tr "loading"}}
-
+
{{if .RenderedContent}} {{.RenderedContent|Str2html}} {{else}} diff --git a/templates/repo/editor/edit.tmpl b/templates/repo/editor/edit.tmpl index 3efde70f50..b7e1589aa1 100644 --- a/templates/repo/editor/edit.tmpl +++ b/templates/repo/editor/edit.tmpl @@ -44,7 +44,7 @@ {{.FileContent}}
-
+
{{.i18n.Tr "loading"}}
diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl index 7dae7c0121..21c6005456 100644 --- a/templates/repo/empty.tmpl +++ b/templates/repo/empty.tmpl @@ -27,7 +27,7 @@

{{.i18n.Tr "repo.create_new_repo_command"}}

-
+
touch README.md
 git init
 {{if ne .Repository.DefaultBranch "master"}}git checkout -b {{.Repository.DefaultBranch}}{{end}}
@@ -41,7 +41,7 @@ git push -u origin {{.Repository.DefaultBranch}}

{{.i18n.Tr "repo.push_exist_repo"}}

-
+
git remote add origin {{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}
 git push -u origin {{.Repository.DefaultBranch}}
diff --git a/templates/repo/issue/comment_tab.tmpl b/templates/repo/issue/comment_tab.tmpl index ab874bdd13..77e82930dc 100644 --- a/templates/repo/issue/comment_tab.tmpl +++ b/templates/repo/issue/comment_tab.tmpl @@ -8,7 +8,7 @@ {{- if .BodyQuery}}{{.BodyQuery}}{{else if .IssueTemplate}}{{.IssueTemplate}}{{else if .PullRequestTemplate}}{{.PullRequestTemplate}}{{else}}{{.content}}{{end -}}
-
+
{{.i18n.Tr "loading"}}
diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl index 8c2f36f04b..897d297d37 100644 --- a/templates/repo/issue/milestone_issues.tmpl +++ b/templates/repo/issue/milestone_issues.tmpl @@ -5,7 +5,7 @@

{{.Milestone.Name}}

-
+
{{.Milestone.RenderedContent|Str2html}}
diff --git a/templates/repo/issue/milestones.tmpl b/templates/repo/issue/milestones.tmpl index c7d3522abc..448d758e3e 100644 --- a/templates/repo/issue/milestones.tmpl +++ b/templates/repo/issue/milestones.tmpl @@ -98,7 +98,7 @@
{{end}} {{if .Content}} -
+
{{.RenderedContent|Str2html}}
{{end}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index 0482604b70..e353d71ee9 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -57,7 +57,7 @@
-
+
{{if .Issue.RenderedContent}} {{.Issue.RenderedContent|Str2html}} {{else}} @@ -191,7 +191,7 @@
-
+
{{$.i18n.Tr "loading"}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 81f0d0434a..4863f7f2f1 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -64,7 +64,7 @@
-
+
{{if .RenderedContent}} {{.RenderedContent|Str2html}} {{else}} @@ -442,7 +442,7 @@
-
+
{{if .RenderedContent}} {{.RenderedContent|Str2html}} {{else}} @@ -552,7 +552,7 @@
-
+
{{if .RenderedContent}} {{.RenderedContent|Str2html}} {{else}} @@ -739,7 +739,7 @@
-
+
{{if .RenderedContent}} {{.RenderedContent|Str2html}} {{else}} diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index 63f9e26cf1..d98e441644 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -136,7 +136,7 @@ | {{$.i18n.Tr "repo.release.ahead.commits" .NumCommitsBehind | Str2html}} {{$.i18n.Tr "repo.release.ahead.target" .Target}} {{end}}

-
+
{{Str2html .Note}}
diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl index 8489d89597..c4b36597c6 100644 --- a/templates/repo/release/new.tmpl +++ b/templates/repo/release/new.tmpl @@ -53,7 +53,7 @@
-
+
{{$.i18n.Tr "loading"}}
diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl index 09eeb3f27f..478c034e11 100644 --- a/templates/repo/settings/lfs_file.tmpl +++ b/templates/repo/settings/lfs_file.tmpl @@ -12,7 +12,7 @@
-
+
{{if .IsMarkup}} {{if .FileContent}}{{.FileContent | Safe}}{{end}} {{else if .IsRenderedHTML}} diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index d9c1e93eaf..5798ec875c 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -64,7 +64,7 @@ {{end}}
-
+
{{if .IsMarkup}} {{if .FileContent}}{{.FileContent | Safe}}{{end}} {{else if .IsRenderedHTML}} diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl index 0bc5858863..fbb97db4ad 100644 --- a/templates/repo/wiki/view.tmpl +++ b/templates/repo/wiki/view.tmpl @@ -61,7 +61,7 @@
{{end}}
-
+
{{.content | Str2html}}
{{if .sidebarPresent}} diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 18f3c9f6dd..29da933493 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -36,7 +36,7 @@ {{end}} {{if $.RenderedDescription}}
  • -
    {{$.RenderedDescription|Str2html}}
    +
    {{$.RenderedDescription|Str2html}}
  • {{end}} {{range .OpenIDs}} diff --git a/web_src/js/index.js b/web_src/js/index.js index 2fce21b8d3..53843a6d22 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -4,26 +4,26 @@ import Vue from 'vue'; import {htmlEscape} from 'escape-goat'; import 'jquery.are-you-sure'; -import initMigration from './features/migration.js'; +import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; +import attachTribute from './features/tribute.js'; +import createColorPicker from './features/colorpicker.js'; +import createDropzone from './features/dropzone.js'; +import initClipboard from './features/clipboard.js'; import initContextPopups from './features/contextpopup.js'; import initGitGraph from './features/gitgraph.js'; -import initClipboard from './features/clipboard.js'; import initHeatmap from './features/heatmap.js'; +import initImageDiff from './features/imagediff.js'; +import initMigration from './features/migration.js'; import initProject from './features/projects.js'; import initServiceWorker from './features/serviceworker.js'; -import initMarkdownAnchors from './markdown/anchors.js'; -import renderMarkdownContent from './markdown/content.js'; -import attachTribute from './features/tribute.js'; -import createColorPicker from './features/colorpicker.js'; -import createDropzone from './features/dropzone.js'; import initTableSort from './features/tablesort.js'; -import initImageDiff from './features/imagediff.js'; -import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; +import {createCodeEditor, createMonaco} from './features/codeeditor.js'; +import {initMarkupAnchors} from './markup/anchors.js'; import {initNotificationsTable, initNotificationCount} from './features/notification.js'; import {initStopwatch} from './features/stopwatch.js'; -import {createCodeEditor, createMonaco} from './features/codeeditor.js'; -import {svg, svgs} from './svg.js'; +import {renderMarkupContent} from './markup/content.js'; import {stripTags, mqBinarySearch} from './utils.js'; +import {svg, svgs} from './svg.js'; const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; @@ -51,7 +51,7 @@ function initCommentPreviewTab($form) { }, (data) => { const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`); $previewPanel.html(data); - renderMarkdownContent(); + renderMarkupContent(); }); }); @@ -81,7 +81,7 @@ function initEditPreviewTab($form) { }, (data) => { const $previewPanel = $form.find(`.tab[data-tab="${$tabMenu.data('preview')}"]`); $previewPanel.html(data); - renderMarkdownContent(); + renderMarkupContent(); }); }); } @@ -1107,7 +1107,7 @@ async function initRepository() { dz.emit('submit'); dz.emit('reload'); } - renderMarkdownContent(); + renderMarkupContent(); }); }); } else { @@ -1473,8 +1473,8 @@ function initWikiForm() { text: plainText, wiki: true }, (data) => { - preview.innerHTML = `
    ${data}
    `; - renderMarkdownContent(); + preview.innerHTML = `
    ${data}
    `; + renderMarkupContent(); }); }; @@ -1553,7 +1553,7 @@ function initWikiForm() { const $form = $('.repository.wiki.new .ui.form'); const $root = $form.find('.field.content'); const loading = $root.data('loading'); - $root.append(`
    ${loading}
    `); + $root.append(`
    ${loading}
    `); initCommentPreviewTab($form); }, className: 'fa fa-file', @@ -2772,7 +2772,7 @@ $(document).ready(async () => { searchTeams(); searchRepositories(); - initMarkdownAnchors(); + initMarkupAnchors(); initCommentForm(); initInstall(); initArchiveLinks(); @@ -2830,7 +2830,7 @@ $(document).ready(async () => { initServiceWorker(), initNotificationCount(), initStopwatch(), - renderMarkdownContent(), + renderMarkupContent(), initGithook(), initImageDiff(), ]); diff --git a/web_src/js/markdown/anchors.js b/web_src/js/markdown/anchors.js deleted file mode 100644 index 62bf8c83c3..0000000000 --- a/web_src/js/markdown/anchors.js +++ /dev/null @@ -1,32 +0,0 @@ -import {svg} from '../svg.js'; - -const headingSelector = '.markdown h1, .markdown h2, .markdown h3, .markdown h4, .markdown h5, .markdown h6'; - -function scrollToAnchor() { - if (document.querySelector(':target')) return; - if (!window.location.hash || window.location.hash.length <= 1) return; - const id = decodeURIComponent(window.location.hash.substring(1)); - const el = document.getElementById(`user-content-${id}`); - if (el) { - el.scrollIntoView(); - } else if (id.startsWith('user-content-')) { // compat for links with old 'user-content-' prefixed hashes - const el = document.getElementById(id); - if (el) el.scrollIntoView(); - } -} - -export default function initMarkdownAnchors() { - if (!document.querySelector('.markdown')) return; - - for (const heading of document.querySelectorAll(headingSelector)) { - const originalId = heading.id.replace(/^user-content-/, ''); - const a = document.createElement('a'); - a.classList.add('anchor'); - a.setAttribute('href', `#${encodeURIComponent(originalId)}`); - a.innerHTML = svg('octicon-link'); - heading.prepend(a); - } - - scrollToAnchor(); - window.addEventListener('hashchange', scrollToAnchor); -} diff --git a/web_src/js/markdown/content.js b/web_src/js/markdown/content.js deleted file mode 100644 index 918cd6fe81..0000000000 --- a/web_src/js/markdown/content.js +++ /dev/null @@ -1,5 +0,0 @@ -import {renderMermaid} from './mermaid.js'; - -export default async function renderMarkdownContent() { - await renderMermaid(document.querySelectorAll('code.language-mermaid')); -} diff --git a/web_src/js/markdown/mermaid.js b/web_src/js/markdown/mermaid.js deleted file mode 100644 index a518bc7345..0000000000 --- a/web_src/js/markdown/mermaid.js +++ /dev/null @@ -1,56 +0,0 @@ -const MAX_SOURCE_CHARACTERS = 5000; - -function displayError(el, err) { - el.closest('pre').classList.remove('is-loading'); - const errorNode = document.createElement('div'); - errorNode.setAttribute('class', 'ui message error markdown-block-error mono'); - errorNode.textContent = err.str || err.message || String(err); - el.closest('pre').before(errorNode); -} - -export async function renderMermaid(els) { - if (!els || !els.length) return; - - const mermaid = await import(/* webpackChunkName: "mermaid" */'mermaid'); - - mermaid.initialize({ - mermaid: { - startOnLoad: false, - }, - flowchart: { - useMaxWidth: true, - htmlLabels: false, - }, - theme: 'neutral', - securityLevel: 'strict', - }); - - for (const el of els) { - if (el.textContent.length > MAX_SOURCE_CHARACTERS) { - displayError(el, new Error(`Mermaid source of ${el.textContent.length} characters exceeds the maximum allowed length of ${MAX_SOURCE_CHARACTERS}.`)); - continue; - } - - let valid; - try { - valid = mermaid.parse(el.textContent); - } catch (err) { - displayError(el, err); - } - - if (!valid) { - el.closest('pre').classList.remove('is-loading'); - continue; - } - - try { - mermaid.init(undefined, el, (id) => { - const svg = document.getElementById(id); - svg.classList.add('mermaid-chart'); - svg.closest('pre').replaceWith(svg); - }); - } catch (err) { - displayError(el, err); - } - } -} diff --git a/web_src/js/markup/anchors.js b/web_src/js/markup/anchors.js new file mode 100644 index 0000000000..cc2ed5db78 --- /dev/null +++ b/web_src/js/markup/anchors.js @@ -0,0 +1,32 @@ +import {svg} from '../svg.js'; + +const headingSelector = '.markup h1, .markup h2, .markup h3, .markup h4, .markup h5, .markup h6'; + +function scrollToAnchor() { + if (document.querySelector(':target')) return; + if (!window.location.hash || window.location.hash.length <= 1) return; + const id = decodeURIComponent(window.location.hash.substring(1)); + const el = document.getElementById(`user-content-${id}`); + if (el) { + el.scrollIntoView(); + } else if (id.startsWith('user-content-')) { // compat for links with old 'user-content-' prefixed hashes + const el = document.getElementById(id); + if (el) el.scrollIntoView(); + } +} + +export function initMarkupAnchors() { + if (!document.querySelector('.markup')) return; + + for (const heading of document.querySelectorAll(headingSelector)) { + const originalId = heading.id.replace(/^user-content-/, ''); + const a = document.createElement('a'); + a.classList.add('anchor'); + a.setAttribute('href', `#${encodeURIComponent(originalId)}`); + a.innerHTML = svg('octicon-link'); + heading.prepend(a); + } + + scrollToAnchor(); + window.addEventListener('hashchange', scrollToAnchor); +} diff --git a/web_src/js/markup/content.js b/web_src/js/markup/content.js new file mode 100644 index 0000000000..f06c9908f2 --- /dev/null +++ b/web_src/js/markup/content.js @@ -0,0 +1,5 @@ +import {renderMermaid} from './mermaid.js'; + +export async function renderMarkupContent() { + await renderMermaid(document.querySelectorAll('code.language-mermaid')); +} diff --git a/web_src/js/markup/mermaid.js b/web_src/js/markup/mermaid.js new file mode 100644 index 0000000000..d0aefd1aff --- /dev/null +++ b/web_src/js/markup/mermaid.js @@ -0,0 +1,56 @@ +const MAX_SOURCE_CHARACTERS = 5000; + +function displayError(el, err) { + el.closest('pre').classList.remove('is-loading'); + const errorNode = document.createElement('div'); + errorNode.setAttribute('class', 'ui message error markup-block-error mono'); + errorNode.textContent = err.str || err.message || String(err); + el.closest('pre').before(errorNode); +} + +export async function renderMermaid(els) { + if (!els || !els.length) return; + + const mermaid = await import(/* webpackChunkName: "mermaid" */'mermaid'); + + mermaid.initialize({ + mermaid: { + startOnLoad: false, + }, + flowchart: { + useMaxWidth: true, + htmlLabels: false, + }, + theme: 'neutral', + securityLevel: 'strict', + }); + + for (const el of els) { + if (el.textContent.length > MAX_SOURCE_CHARACTERS) { + displayError(el, new Error(`Mermaid source of ${el.textContent.length} characters exceeds the maximum allowed length of ${MAX_SOURCE_CHARACTERS}.`)); + continue; + } + + let valid; + try { + valid = mermaid.parse(el.textContent); + } catch (err) { + displayError(el, err); + } + + if (!valid) { + el.closest('pre').classList.remove('is-loading'); + continue; + } + + try { + mermaid.init(undefined, el, (id) => { + const svg = document.getElementById(id); + svg.classList.add('mermaid-chart'); + svg.closest('pre').replaceWith(svg); + }); + } catch (err) { + displayError(el, err); + } + } +} diff --git a/web_src/less/_base.less b/web_src/less/_base.less index 7e563d2f23..d85f13cb33 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -102,8 +102,8 @@ --color-active: #00000014; --color-menu: #ffffff; --color-card: #ffffff; - --color-markdown-table-row: #00000008; - --color-markdown-code-block: #00000010; + --color-markup-table-row: #00000008; + --color-markup-code-block: #00000010; --color-button: #ffffff; --color-code-bg: #ffffff; --color-shadow: #00000030; diff --git a/web_src/less/_markdown.less b/web_src/less/_markdown.less deleted file mode 100644 index 66276894c0..0000000000 --- a/web_src/less/_markdown.less +++ /dev/null @@ -1,542 +0,0 @@ -.markdown:not(code) { - overflow: hidden; - font-size: 16px; - line-height: 1.5 !important; - word-wrap: break-word; - - &.ui.segment { - padding: 3em; - } - - &.file-view { - padding: 2em !important; - } - - > *:first-child { - margin-top: 0 !important; - } - - > *:last-child { - margin-bottom: 0 !important; - } - - a:not([href]) { - color: inherit; - text-decoration: none; - } - - .absent { - color: var(--color-red); - } - - .anchor { - padding-right: 4px; - margin-left: -20px; - line-height: 1; - color: inherit; - } - - .anchor .svg { - vertical-align: middle; - } - - .anchor:focus { - outline: none; - } - - h1 .anchor .svg, - h2 .anchor .svg, - h3 .anchor .svg, - h4 .anchor .svg, - h5 .anchor .svg, - h6 .anchor .svg { - visibility: hidden; - } - - h1:hover .anchor .svg, - h2:hover .anchor .svg, - h3:hover .anchor .svg, - h4:hover .anchor .svg, - h5:hover .anchor .svg, - h6:hover .anchor .svg { - visibility: visible; - } - - h2 .anchor .svg, - h3 .anchor .svg, - h4 .anchor .svg { - position: relative; - top: -2px; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; - } - - h1 tt, - h1 code, - h2 tt, - h2 code, - h3 tt, - h3 code, - h4 tt, - h4 code, - h5 tt, - h5 code, - h6 tt, - h6 code { - font-size: inherit; - } - - h1 { - padding-bottom: .3em; - font-size: 2em; - border-bottom: 1px solid var(--color-secondary); - } - - h2 { - padding-bottom: .3em; - font-size: 1.5em; - border-bottom: 1px solid var(--color-secondary); - } - - h3 { - font-size: 1.25em; - } - - h4 { - font-size: 1em; - } - - h5 { - font-size: .875em; - } - - h6 { - font-size: .85em; - color: var(--color-text-light-2); - } - - p, - blockquote, - details, - ul, - ol, - dl, - table, - pre { - margin-top: 0; - margin-bottom: 16px; - } - - hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: var(--color-secondary); - border: 0; - } - - ul, - ol { - padding-left: 2em; - } - - ul.no-list, - ol.no-list { - padding: 0; - list-style-type: none; - } - - .task-list-item { - list-style-type: none; - - input[type="checkbox"] { - margin: 0 6px .25em -1.6em; - } - } - - .task-list-item + .task-list-item { - margin-top: 3px; - } - - input[type="checkbox"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - position: relative; - border: 1px solid var(--color-secondary); - border-radius: 2px; - background: var(--color-input-background); - height: 14px; - width: 14px; - opacity: 1 !important; // override fomantic on edit preview - pointer-events: auto !important; // override fomantic on edit preview - vertical-align: middle !important; // override fomantic on edit preview - } - - input[type="checkbox"]:not([disabled]):hover, - input[type="checkbox"]:not([disabled]):active { - border-color: var(--color-primary); - } - - input[type="checkbox"]::after { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - pointer-events: none; - background: var(--color-text); - mask-size: cover; - -webkit-mask-size: cover; - } - - input[type="checkbox"]:checked::after { - content: ""; - mask-image: var(--checkbox-mask-checked); - -webkit-mask-image: var(--checkbox-mask-checked); - } - - input[type="checkbox"]:indeterminate::after { - content: ""; - mask-image: var(--checkbox-mask-indeterminate); - -webkit-mask-image: var(--checkbox-mask-indeterminate); - } - - ul ul, - ul ol, - ol ol, - ol ul { - margin-top: 0; - margin-bottom: 0; - } - - ol ol, - ul ol { - list-style-type: lower-roman; - } - - li > p { - margin-top: 16px; - } - - li + li { - margin-top: .25em; - } - - dl { - padding: 0; - } - - dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 600; - } - - dl dd { - padding: 0 16px; - margin-bottom: 16px; - } - - blockquote { - margin-left: 0; - padding: 0 15px; - color: var(--color-text-light-2); - border-left: 4px solid var(--color-secondary); - } - - blockquote > :first-child { - margin-top: 0; - } - - blockquote > :last-child { - margin-bottom: 0; - } - - table { - display: block; - width: 100%; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - max-width: 100%; - overflow: auto; - } - - table th { - font-weight: 600; - } - - table th, - table td { - padding: 6px 13px !important; - border: 1px solid var(--color-secondary) !important; - } - - table tr { - border-top: 1px solid var(--color-secondary); - } - - table tr:nth-child(2n) { - background-color: var(--color-markdown-table-row); - } - - img { - max-width: 100%; - box-sizing: initial; - } - - img[align="right"] { - padding-left: 20px; - } - - img[align="left"] { - padding-right: 20px; - } - - .emoji { - max-width: none; - vertical-align: text-top; - } - - span.frame { - display: block; - overflow: hidden; - } - - span.frame > span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid var(--color-secondary); - } - - span.frame span img { - display: block; - float: left; - } - - span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: var(--color-text); - } - - span.align-center { - display: block; - overflow: hidden; - clear: both; - } - - span.align-center > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: center; - } - - span.align-center span img { - margin: 0 auto; - text-align: center; - } - - span.align-right { - display: block; - overflow: hidden; - clear: both; - } - - span.align-right > span { - display: block; - margin: 13px 0 0; - overflow: hidden; - text-align: right; - } - - span.align-right span img { - margin: 0; - text-align: right; - } - - span.float-left { - display: block; - float: left; - margin-right: 13px; - overflow: hidden; - } - - span.float-left span { - margin: 13px 0 0; - } - - span.float-right { - display: block; - float: right; - margin-left: 13px; - overflow: hidden; - } - - span.float-right > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: right; - } - - code, - tt { - padding: .2em .4em; - margin: 0; - font-size: 85%; - background-color: var(--color-markdown-code-block); - border-radius: 4px; - } - - code br, - tt br { - display: none; - } - - del code { - text-decoration: inherit; - } - - pre > code { - padding: 0; - margin: 0; - font-size: 100%; - white-space: pre-wrap; - word-break: break-all; - overflow-wrap: break-word; - background: transparent; - border: 0; - } - - .highlight { - margin-bottom: 16px; - } - - .highlight pre, - pre { - padding: 16px; - font-size: 85%; - line-height: 1.45; - background-color: var(--color-markdown-code-block); - border-radius: 4px; - } - - .highlight pre { - margin-bottom: 0; - word-break: normal; - } - - pre { - word-wrap: normal; - } - - pre code, - pre tt { - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; - } - - pre code::before, - pre code::after, - pre tt::before, - pre tt::after { - content: normal; - } - - kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: var(--color-text-light); - vertical-align: middle; - background-color: var(--color-markdown-code-block); - border: 1px solid var(--color-secondary); - border-radius: 3px; - box-shadow: inset 0 -1px 0 var(--color-secondary); - } - - .ui.list .list, - ol.ui.list ol, - ul.ui.list ul { - padding-left: 2em; - } -} - -.repository.wiki.revisions { - .ui.container > .ui.stackable.grid { - -ms-flex-direction: row-reverse; - flex-direction: row-reverse; - - > .header { - margin-top: 0; - - .sub.header { - padding-left: 52px; - word-break: break-word; - } - } - } -} - -.file-revisions-btn { - display: block; - float: left; - margin-bottom: 2px !important; - padding: 11px !important; - margin-right: 10px !important; - - i { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } -} - -.markdown-block-error { - margin-bottom: 0 !important; - border-bottom-left-radius: 0 !important; - border-bottom-right-radius: 0 !important; - box-shadow: none !important; - font-size: 85% !important; - white-space: pre !important; - padding: .5rem 1rem !important; - text-align: left !important; -} - -.markdown-block-error + pre { - border-top: none !important; - margin-top: 0 !important; - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; -} diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 5ff51b1d6d..549bd4d7e5 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -580,7 +580,7 @@ border-right-color: var(--color-box-body); } - .markdown { + .markup { font-size: 14px; } } @@ -1020,7 +1020,7 @@ } } - .markdown { + .markup { font-size: 14px; } @@ -1040,7 +1040,7 @@ overflow: hidden; } - .tab.markdown { + .tab.markup { min-height: 5rem; } } @@ -1244,7 +1244,7 @@ margin-bottom: 1.5rem; } - .markdown { + .markup { font-size: 14px; } } @@ -1996,7 +1996,7 @@ margin-top: -5px; } - > .markdown { + > .markup { padding: 15px 30px; h1, @@ -2991,7 +2991,7 @@ td.blob-excerpt { .webhook-info { padding: 7px 12px; margin: 10px 0; - background-color: var(--color-markdown-code-block); + background-color: var(--color-markup-code-block); border: 1px solid var(--color-secondary); border-radius: 3px; font-size: 13px; diff --git a/web_src/less/_review.less b/web_src/less/_review.less index f6f5df20a2..2b8700a745 100644 --- a/web_src/less/_review.less +++ b/web_src/less/_review.less @@ -81,7 +81,7 @@ .ui.active.tab { padding: .5em; - &.markdown { + &.markup { padding: 1em; min-height: 168px; } @@ -95,7 +95,7 @@ border-top: 1px solid var(--color-secondary); padding: 10px 0; - .markdown-info { + .markup-info { display: inline-block; margin: 5px 0; font-size: 12px; diff --git a/web_src/less/features/animations.less b/web_src/less/features/animations.less index 0b50440bf3..f3491155cd 100644 --- a/web_src/less/features/animations.less +++ b/web_src/less/features/animations.less @@ -28,7 +28,7 @@ border-radius: 100%; } -.markdown pre.is-loading, +.markup pre.is-loading, .editor-loading.is-loading { height: 12rem; } diff --git a/web_src/less/index.less b/web_src/less/index.less index c125ccac31..f52953f2a4 100644 --- a/web_src/less/index.less +++ b/web_src/less/index.less @@ -9,7 +9,8 @@ @import "./features/imagediff.less"; @import "./features/codeeditor.less"; @import "./features/projects.less"; -@import "./markdown/mermaid.less"; +@import "./markup/content.less"; +@import "./markup/mermaid.less"; @import "./chroma/base.less"; @import "./chroma/light.less"; @@ -18,7 +19,6 @@ @import "_tribute"; @import "_font_i18n"; @import "_base"; -@import "_markdown"; @import "_home"; @import "_install"; @import "_form"; diff --git a/web_src/less/markdown/mermaid.less b/web_src/less/markdown/mermaid.less deleted file mode 100644 index f68b577dec..0000000000 --- a/web_src/less/markdown/mermaid.less +++ /dev/null @@ -1,13 +0,0 @@ -.mermaid-chart { - display: flex; - justify-content: center; - align-items: center; - padding: 1rem; - margin: 1rem auto; - height: auto; -} - -/* mermaid's errorRenderer seems to unavoidably spew stuff into , hide it */ -body > div[id*="mermaid-"] { - display: none !important; -} diff --git a/web_src/less/markup/content.less b/web_src/less/markup/content.less new file mode 100644 index 0000000000..df87c21d8c --- /dev/null +++ b/web_src/less/markup/content.less @@ -0,0 +1,542 @@ +.markup { + overflow: hidden; + font-size: 16px; + line-height: 1.5 !important; + word-wrap: break-word; + + &.ui.segment { + padding: 3em; + } + + &.file-view { + padding: 2em !important; + } + + > *:first-child { + margin-top: 0 !important; + } + + > *:last-child { + margin-bottom: 0 !important; + } + + a:not([href]) { + color: inherit; + text-decoration: none; + } + + .absent { + color: var(--color-red); + } + + .anchor { + padding-right: 4px; + margin-left: -20px; + line-height: 1; + color: inherit; + } + + .anchor .svg { + vertical-align: middle; + } + + .anchor:focus { + outline: none; + } + + h1 .anchor .svg, + h2 .anchor .svg, + h3 .anchor .svg, + h4 .anchor .svg, + h5 .anchor .svg, + h6 .anchor .svg { + visibility: hidden; + } + + h1:hover .anchor .svg, + h2:hover .anchor .svg, + h3:hover .anchor .svg, + h4:hover .anchor .svg, + h5:hover .anchor .svg, + h6:hover .anchor .svg { + visibility: visible; + } + + h2 .anchor .svg, + h3 .anchor .svg, + h4 .anchor .svg { + position: relative; + top: -2px; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; + } + + h1 tt, + h1 code, + h2 tt, + h2 code, + h3 tt, + h3 code, + h4 tt, + h4 code, + h5 tt, + h5 code, + h6 tt, + h6 code { + font-size: inherit; + } + + h1 { + padding-bottom: .3em; + font-size: 2em; + border-bottom: 1px solid var(--color-secondary); + } + + h2 { + padding-bottom: .3em; + font-size: 1.5em; + border-bottom: 1px solid var(--color-secondary); + } + + h3 { + font-size: 1.25em; + } + + h4 { + font-size: 1em; + } + + h5 { + font-size: .875em; + } + + h6 { + font-size: .85em; + color: var(--color-text-light-2); + } + + p, + blockquote, + details, + ul, + ol, + dl, + table, + pre { + margin-top: 0; + margin-bottom: 16px; + } + + hr { + height: 4px; + padding: 0; + margin: 16px 0; + background-color: var(--color-secondary); + border: 0; + } + + ul, + ol { + padding-left: 2em; + } + + ul.no-list, + ol.no-list { + padding: 0; + list-style-type: none; + } + + .task-list-item { + list-style-type: none; + + input[type="checkbox"] { + margin: 0 6px .25em -1.6em; + } + } + + .task-list-item + .task-list-item { + margin-top: 3px; + } + + input[type="checkbox"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + border: 1px solid var(--color-secondary); + border-radius: 2px; + background: var(--color-input-background); + height: 14px; + width: 14px; + opacity: 1 !important; // override fomantic on edit preview + pointer-events: auto !important; // override fomantic on edit preview + vertical-align: middle !important; // override fomantic on edit preview + } + + input[type="checkbox"]:not([disabled]):hover, + input[type="checkbox"]:not([disabled]):active { + border-color: var(--color-primary); + } + + input[type="checkbox"]::after { + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + pointer-events: none; + background: var(--color-text); + mask-size: cover; + -webkit-mask-size: cover; + } + + input[type="checkbox"]:checked::after { + content: ""; + mask-image: var(--checkbox-mask-checked); + -webkit-mask-image: var(--checkbox-mask-checked); + } + + input[type="checkbox"]:indeterminate::after { + content: ""; + mask-image: var(--checkbox-mask-indeterminate); + -webkit-mask-image: var(--checkbox-mask-indeterminate); + } + + ul ul, + ul ol, + ol ol, + ol ul { + margin-top: 0; + margin-bottom: 0; + } + + ol ol, + ul ol { + list-style-type: lower-roman; + } + + li > p { + margin-top: 16px; + } + + li + li { + margin-top: .25em; + } + + dl { + padding: 0; + } + + dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; + } + + dl dd { + padding: 0 16px; + margin-bottom: 16px; + } + + blockquote { + margin-left: 0; + padding: 0 15px; + color: var(--color-text-light-2); + border-left: 4px solid var(--color-secondary); + } + + blockquote > :first-child { + margin-top: 0; + } + + blockquote > :last-child { + margin-bottom: 0; + } + + table { + display: block; + width: 100%; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + overflow: auto; + } + + table th { + font-weight: 600; + } + + table th, + table td { + padding: 6px 13px !important; + border: 1px solid var(--color-secondary) !important; + } + + table tr { + border-top: 1px solid var(--color-secondary); + } + + table tr:nth-child(2n) { + background-color: var(--color-markup-table-row); + } + + img { + max-width: 100%; + box-sizing: initial; + } + + img[align="right"] { + padding-left: 20px; + } + + img[align="left"] { + padding-right: 20px; + } + + .emoji { + max-width: none; + vertical-align: text-top; + } + + span.frame { + display: block; + overflow: hidden; + } + + span.frame > span { + display: block; + float: left; + width: auto; + padding: 7px; + margin: 13px 0 0; + overflow: hidden; + border: 1px solid var(--color-secondary); + } + + span.frame span img { + display: block; + float: left; + } + + span.frame span span { + display: block; + padding: 5px 0 0; + clear: both; + color: var(--color-text); + } + + span.align-center { + display: block; + overflow: hidden; + clear: both; + } + + span.align-center > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: center; + } + + span.align-center span img { + margin: 0 auto; + text-align: center; + } + + span.align-right { + display: block; + overflow: hidden; + clear: both; + } + + span.align-right > span { + display: block; + margin: 13px 0 0; + overflow: hidden; + text-align: right; + } + + span.align-right span img { + margin: 0; + text-align: right; + } + + span.float-left { + display: block; + float: left; + margin-right: 13px; + overflow: hidden; + } + + span.float-left span { + margin: 13px 0 0; + } + + span.float-right { + display: block; + float: right; + margin-left: 13px; + overflow: hidden; + } + + span.float-right > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: right; + } + + code, + tt { + padding: .2em .4em; + margin: 0; + font-size: 85%; + background-color: var(--color-markup-code-block); + border-radius: 4px; + } + + code br, + tt br { + display: none; + } + + del code { + text-decoration: inherit; + } + + pre > code { + padding: 0; + margin: 0; + font-size: 100%; + white-space: pre-wrap; + word-break: break-all; + overflow-wrap: break-word; + background: transparent; + border: 0; + } + + .highlight { + margin-bottom: 16px; + } + + .highlight pre, + pre { + padding: 16px; + font-size: 85%; + line-height: 1.45; + background-color: var(--color-markup-code-block); + border-radius: 4px; + } + + .highlight pre { + margin-bottom: 0; + word-break: normal; + } + + pre { + word-wrap: normal; + } + + pre code, + pre tt { + display: inline; + max-width: initial; + padding: 0; + margin: 0; + overflow: initial; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; + } + + pre code::before, + pre code::after, + pre tt::before, + pre tt::after { + content: normal; + } + + kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: var(--color-text-light); + vertical-align: middle; + background-color: var(--color-markup-code-block); + border: 1px solid var(--color-secondary); + border-radius: 3px; + box-shadow: inset 0 -1px 0 var(--color-secondary); + } + + .ui.list .list, + ol.ui.list ol, + ul.ui.list ul { + padding-left: 2em; + } +} + +.repository.wiki.revisions { + .ui.container > .ui.stackable.grid { + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; + + > .header { + margin-top: 0; + + .sub.header { + padding-left: 52px; + word-break: break-word; + } + } + } +} + +.file-revisions-btn { + display: block; + float: left; + margin-bottom: 2px !important; + padding: 11px !important; + margin-right: 10px !important; + + i { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } +} + +.markup-block-error { + margin-bottom: 0 !important; + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; + box-shadow: none !important; + font-size: 85% !important; + white-space: pre !important; + padding: .5rem 1rem !important; + text-align: left !important; +} + +.markup-block-error + pre { + border-top: none !important; + margin-top: 0 !important; + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} diff --git a/web_src/less/markup/mermaid.less b/web_src/less/markup/mermaid.less new file mode 100644 index 0000000000..f68b577dec --- /dev/null +++ b/web_src/less/markup/mermaid.less @@ -0,0 +1,13 @@ +.mermaid-chart { + display: flex; + justify-content: center; + align-items: center; + padding: 1rem; + margin: 1rem auto; + height: auto; +} + +/* mermaid's errorRenderer seems to unavoidably spew stuff into , hide it */ +body > div[id*="mermaid-"] { + display: none !important; +} diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index 346a6e85ea..9e39c4bec4 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -97,8 +97,8 @@ --color-active: #ffffff16; --color-menu: #2e323e; --color-card: #2e323e; - --color-markdown-table-row: #ffffff06; - --color-markdown-code-block: #2a2e3a; + --color-markup-table-row: #ffffff06; + --color-markup-code-block: #2a2e3a; --color-button: #353846; --color-code-bg: #2a2e3a; --color-shadow: #00000060; @@ -301,7 +301,7 @@ a.ui.basic.green.label:hover { & + .editor-preview-side { background: #353945; - .markdown:not(code).ui.segment { + .markup.ui.segment { border-width: 0; } } @@ -754,7 +754,7 @@ img[src$="/img/matrix.svg"] { border-color: #4a4c58 #4a4c58 #d7d7da #d7d7da; } -.markdown-block-error { +.markup-block-error { border: 1px solid rgba(121, 71, 66, .5) !important; border-bottom: none !important; } -- cgit v1.2.3