// TODO: copied from string-utils
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
function formatCssSize(v: any): string {
if (typeof v === 'string') {
if (v.includes('px') || v.includes('em') || v.includes('%')) return v;
}
return `${v}px`;
}
export interface Options {
contentMaxWidth?: number;
contentMaxWidthTarget?: string;
themeId?: number;
whiteBackgroundNoteRendering?: boolean;
}
// If we are viewing an HTML note, it means it comes from the web clipper or
// emil-to-note, in which case we don't apply any specific theme. We just need
// to ensure the background is white so that we don't end up with a dark theme
// and dark font for example. https://github.com/laurent22/joplin/issues/9511
export const whiteBackgroundNoteStyle = () => {
return `
body {
background-color: #ffffff;
}
/* TinyMCE adds a dashed border for tables that have no borders
to make it easier to view where the cells are and edit them.
However HTML notes may contain many nested tables used for
layout and we also consider that these notes are more or less
read-only. Because of this, we remove the dashed lines in this
case as it makes the note more readable. */
.mce-item-table:not([border]),
.mce-item-table:not([border]) caption,
.mce-item-table:not([border]) td,
.mce-item-table:not([border]) th,
.mce-item-table[border="0"],
.mce-item-table[border="0"] caption,
.mce-item-table[border="0"] td,
.mce-item-table[border="0"] th,
table[style*="border-width: 0px"],
table[style*="border-width: 0px"] caption,
table[style*="border-width: 0px"] td,
table[style*="border-width: 0px"] th {
border: none !important;
}
`;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
export default function(theme: any, options: Options = null) {
options = {
contentMaxWidth: 0,
...options,
};
theme = theme ? theme : {};
const fontFamily = '\'Avenir\', \'Arial\', sans-serif';
const maxWidthTarget = options.contentMaxWidthTarget ? options.contentMaxWidthTarget : '#rendered-md';
const maxWidthCss = options.contentMaxWidth ? `
${maxWidthTarget} {
max-width: ${options.contentMaxWidth}px;
margin-left: auto;
margin-right: auto;
}
` : '';
const css =
`
/* https://necolas.github.io/normalize.css/ */
html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}
pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}
b,strong{font-weight:bolder}small{font-size:80%}img{border-style:none}
body {
font-size: ${formatCssSize(theme.noteViewerFontSize)};
color: ${theme.color};
word-wrap: break-word;
line-height: ${theme.lineHeight};
background-color: ${theme.backgroundColor};
font-family: ${fontFamily};
padding-bottom: ${formatCssSize(theme.bodyPaddingBottom)};
padding-top: ${formatCssSize(theme.bodyPaddingTop)};
}
kbd {
border: 1px solid ${theme.codeBorderColor};
box-shadow: inset 0 -1px 0 ${theme.codeBorderColor};
padding: 2px 4px;
border-radius: 3px;
background-color: ${theme.codeBackgroundColor};
}
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-corner {
background: none;
}
::-webkit-scrollbar-track {
border: none;
}
::-webkit-scrollbar-thumb {
background: rgba(100, 100, 100, 0.3);
border-radius: 5px;
}
::-webkit-scrollbar-track:hover {
background: rgba(0, 0, 0, 0.1);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(100, 100, 100, 0.7);
}
${maxWidthCss}
/* Remove top padding and margin from first child so that top of rendered text is aligned to top of text editor text */
#rendered-md > h1:first-child,
#rendered-md > h2:first-child,
#rendered-md > h3:first-child,
#rendered-md > h4:first-child,
#rendered-md > ul:first-child,
#rendered-md > ol:first-child,
#rendered-md > table:first-child,
#rendered-md > blockquote:first-child,
#rendered-md > img:first-child,
#rendered-md > p:first-child {
margin-top: 0;
padding-top: 0;
}
p, h1, h2, h3, h4, h5, h6, ul, table {
margin-top: .6em;
margin-bottom: 1.35em;
/*
Adds support for RTL text in the note body. It automatically detects the direction using the content.
Issue: https://github.com/laurent22/joplin/issues/3991
*/
unicode-bidi: plaintext;
}
h1, h2, h3, h4, h5, h6, ul, table {
margin-bottom: 0.65em;
}
h1, h2, h3, h4, h5, h6 {
line-height: 1.5em;
}
h1 {
font-size: 1.5em;
font-weight: bold;
border-bottom: 1px solid ${theme.dividerColor};
padding-bottom: .3em;
}
h2 {
font-size: 1.3em;
font-weight: bold;
padding-bottom: .1em; */
}
h3 {
font-size: 1.1em;
font-weight: bold;
}
h4, h5, h6 {
font-size: 1em;
font-weight: bold;
}
.exported-note-title {
font-size: 2em;
font-weight: bold;
margin-bottom: 0.8em;
line-height: 1.5em;
padding-bottom: .35em;
border-bottom: 1px solid ${theme.dividerColor};
}
a {
color: ${theme.urlColor};
}
ul, ol {
padding-left: 0;
margin-left: 1.7em;
}
li {
margin-bottom: .4em;
}
li p {
margin-top: 0.2em;
margin-bottom: 0;
}
.resource-icon {
display: inline-block;
position: relative;
top: 0.3em;
text-decoration: none;
width: 1.2em;
height: 1.4em;
margin-right: 0.4em;
background-color: ${theme.urlColor};
}
/* These icons are obtained from the wonderful ForkAwesome project by copying the src svgs
* into the css classes below.
* svgs are obtained from https://github.com/ForkAwesome/Fork-Awesome/tree/master/src/icons/svg
* instead of the svg width, height property you must use a viewbox here, 0 0 1536 1792 is typically the actual size of the icon
* each line begins with the pre-amble -webkit-mask: url("data:image/svg+xml;utf8,
* and of course finishes with ");
* to prevent artifacts it is also necessary to include -webkit-mask-repeat: no-repeat;
* on the following line
* */
.fa-joplin {
/* Awesome Font file */
-webkit-mask: url("data:image/svg+xml;utf8,");
}
.fa-file-image {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-pdf {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-word {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-powerpoint {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-excel {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-audio {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-video {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-archive {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-code {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file-alt, .fa-file-csv {
/* fork-awesome doesn't have csv so we use the text icon */
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
.fa-file {
-webkit-mask: url("data:image/svg+xml;utf8,");
-webkit-mask-repeat: no-repeat;
}
blockquote {
border-left: 4px solid ${theme.codeBorderColor};
padding-left: 1.2em;
margin-left: 0;
opacity: ${theme.blockQuoteOpacity};
}
.jop-tinymce table,
table {
text-align: left;
border-collapse: collapse;
border: 1px solid ${theme.codeBorderColor};
background-color: ${theme.backgroundColor};
}
.jop-tinymce table td, .jop-tinymce table th,
table td, th {
text-align: left;
padding: .5em 1em .5em 1em;
font-size: ${theme.noteViewerFontSize};
color: ${theme.color};
font-family: ${fontFamily};
}
.jop-tinymce table td,
table td {
border: 1px solid ${theme.codeBorderColor};
}
.jop-tinymce table th,
table th {
border: 1px solid ${theme.codeBorderColor};
border-bottom: 2px solid ${theme.codeBorderColor};
background-color: ${theme.tableBackgroundColor};
}
.jop-tinymce table tr:nth-child(even),
table tr:nth-child(even) {
background-color: ${theme.tableBackgroundColor};
}
.jop-tinymce table tr:hover,
table tr:hover {
background-color: ${theme.raisedBackgroundColor};
}
hr {
border: none;
border-bottom: 2px solid ${theme.dividerColor};
}
img {
max-width: 100%;
height: auto;
}
.inline-code,
.mce-content-body code {
border: 1px solid ${theme.codeBorderColor};
background-color: ${theme.codeBackgroundColor};
padding-right: .2em;
padding-left: .2em;
border-radius: .25em;
color: ${theme.codeColor};
font-size: ${theme.codeFontSize};
}
.highlighted-keyword {
background-color: #F3B717;
color: black;
}
.not-loaded-resource img {
width: 1.15em;
height: 1.15em;
background: white;
padding: 2px !important;
border-radius: 2px;
box-shadow: 0 1px 3px #000000aa;
}
a.not-loaded-resource img {
margin-right: .2em;
}
a.not-loaded-resource {
display: flex;
flex-direction: row;
align-items: center;
}
.md-checkbox input[type=checkbox]:checked {
opacity: 0.7;
}
.jop-tinymce ul.joplin-checklist .checked,
.md-checkbox .checkbox-label-checked {
opacity: 0.5;
}
.exported-note {
padding: 1em;
}
.joplin-editable .joplin-source {
display: none;
}
mark {
background: #F7D26E;
color: black;
}
/* =============================================== */
/* For TinyMCE */
/* =============================================== */
.mce-content-body {
/* Note: we give a bit more padding at the bottom, to allow scrolling past the end of the document */
padding: 5px 10px 10em 0;
}
/*
.mce-content-body code {
background-color: transparent;
}
*/
.mce-content-body [data-mce-selected=inline-boundary] {
background-color: transparent;
}
.mce-content-body .joplin-editable {
cursor: pointer !important;
}
.mce-content-body.mce-content-readonly {
opacity: 0.5;
}
/* We need that to make sure click events have the A has a target */
.katex a span {
pointer-events: none;
}
.media-player {
width: 100%;
margin-top: 10px;
}
.media-player.media-pdf {
min-height: 35rem;
width: 100%;
max-width: 1000px;
margin: 0;
border: 0;
display: block;
}
/* Clear the CODE style if the element is within a joplin-editable block */
.mce-content-body .joplin-editable code {
border: none;
background: none;
padding: 0;
color: inherit;
font-size: inherit;
}
/* To make code blocks horizontally scrollable */
/* https://github.com/laurent22/joplin/issues/5740 */
pre.hljs {
overflow-x: auto;
}
.joplin-table-wrapper{
overflow-x: auto;
overflow-y: hidden;
}
/* =============================================== */
/* For TinyMCE */
/* =============================================== */
@media print {
body {
height: auto !important;
}
pre {
white-space: pre-wrap;
}
.code, .inline-code {
border: 1px solid #CBCBCB;
}
#joplin-container-content {
/* The height of the content is set dynamically by JavaScript (in updateBodyHeight) to go
around various issues related to scrolling. However when printing we don't want this
fixed size as that would crop the content. So we set it to auto here. "important" is
needed to override the style set by JavaScript at the element-level. */
height: auto !important;
}
}
`;
return [css];
}