├── Trilium-Heatmap.png ├── index.html ├── navigation.html ├── README.md ├── Trilium-Heatmap ├── html.html └── html │ └── js.js ├── !!!meta.json └── style.css /Trilium-Heatmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvai/Trilium-Heatmap/HEAD/Trilium-Heatmap.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /navigation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trilium-Heatmap 2 | Display a note modification heatmap in your Trilium note, just like the Github contributions heatmap! 3 | ![](./Trilium-Heatmap.png) 4 | Powered by [d3.js](https://d3js.org/). 5 | 6 | (It may not work properly before Trilium v0.60, If it doesn't work, please upgrade your Trilium version.) 7 | 8 | ## Features 9 | - Display a heatmap of note edits in Trilium. 10 | - View the number of edits per day for each note. 11 | - Click to navigate to the corresponding date. 12 | 13 | ## Installation 14 | 1. Download the zip file from the latest Releases. 15 | 2. In the Trilium note, right-click to import, select the zip file, uncheck "Safe import," and then click the "Import" button. 16 | 3. Enjoy it! 17 | 18 | ## Upgrade 19 | You can choose to directly copy the new [html](./Trilium-Heatmap/html.html) and [js](./Trilium-Heatmap/html/js.js) files to replace the corresponding files in Trilium. 20 | 21 | Alternatively, you can choose to delete the original version and import the new zip file. -------------------------------------------------------------------------------- /Trilium-Heatmap/html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 24 | 25 |
26 | 27 |
28 |
29 | 30 | ← Previous 31 | 32 | 33 | Next → 34 | 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /!!!meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "formatVersion": 2, 3 | "appVersion": "0.61.4-beta", 4 | "files": [ 5 | { 6 | "noteId": "tMja7JAriyA5", 7 | "notePath": [ 8 | "tMja7JAriyA5" 9 | ], 10 | "isClone": false, 11 | "title": "Trilium-Heatmap", 12 | "notePosition": 30, 13 | "prefix": null, 14 | "isExpanded": false, 15 | "type": "render", 16 | "mime": "", 17 | "dirFileName": "Trilium-Heatmap", 18 | "noImport": false, 19 | "attributes": [ 20 | { 21 | "type": "relation", 22 | "name": "renderNote", 23 | "value": "JmstipmxRbhO", 24 | "isInheritable": false, 25 | "position": 10 26 | }, 27 | { 28 | "type": "label", 29 | "name": "iconClass", 30 | "value": "bx bx-objects-vertical-bottom", 31 | "isInheritable": false, 32 | "position": 11 33 | } 34 | ], 35 | "attachments": [], 36 | "children": [ 37 | { 38 | "noteId": "JmstipmxRbhO", 39 | "notePath": [ 40 | "tMja7JAriyA5", 41 | "JmstipmxRbhO" 42 | ], 43 | "isClone": false, 44 | "title": "html", 45 | "notePosition": 10, 46 | "prefix": null, 47 | "isExpanded": false, 48 | "type": "code", 49 | "mime": "text/html", 50 | "dataFileName": "html.html", 51 | "dirFileName": "html", 52 | "noImport": false, 53 | "attributes": [ 54 | { 55 | "type": "label", 56 | "name": "archived", 57 | "value": "", 58 | "isInheritable": true, 59 | "position": 10 60 | } 61 | ], 62 | "attachments": [], 63 | "children": [ 64 | { 65 | "noteId": "9EQTP14cO2yj", 66 | "notePath": [ 67 | "tMja7JAriyA5", 68 | "JmstipmxRbhO", 69 | "9EQTP14cO2yj" 70 | ], 71 | "isClone": false, 72 | "title": "js", 73 | "notePosition": 10, 74 | "prefix": null, 75 | "isExpanded": false, 76 | "type": "code", 77 | "mime": "application/javascript;env=frontend", 78 | "dataFileName": "js.js", 79 | "dirFileName": "js", 80 | "noImport": false, 81 | "attributes": [], 82 | "attachments": [], 83 | "children": [ 84 | { 85 | "noteId": "ltKwhy16qPOu", 86 | "notePath": [ 87 | "tMja7JAriyA5", 88 | "JmstipmxRbhO", 89 | "9EQTP14cO2yj", 90 | "ltKwhy16qPOu" 91 | ], 92 | "isClone": false, 93 | "title": "d3", 94 | "notePosition": 30, 95 | "prefix": null, 96 | "isExpanded": false, 97 | "type": "file", 98 | "mime": "application/javascript", 99 | "dataFileName": "d3.js", 100 | "noImport": false, 101 | "attributes": [ 102 | { 103 | "type": "label", 104 | "name": "originalFileName", 105 | "value": "d3", 106 | "isInheritable": false, 107 | "position": 10 108 | } 109 | ], 110 | "attachments": [] 111 | } 112 | ] 113 | } 114 | ] 115 | } 116 | ] 117 | }, 118 | { 119 | "noImport": true, 120 | "dataFileName": "navigation.html" 121 | }, 122 | { 123 | "noImport": true, 124 | "dataFileName": "index.html" 125 | }, 126 | { 127 | "noImport": true, 128 | "dataFileName": "style.css" 129 | } 130 | ] 131 | } -------------------------------------------------------------------------------- /Trilium-Heatmap/html/js.js: -------------------------------------------------------------------------------- 1 | const weeks = ['Mon', 'Wed', 'Fri', 'Sun']; //fill in the month word names that are suitable for your native language. 2 | const colorRange = ["#FC9", "#fd5409"]; //fill in the range of colors you like. 3 | const dataRange = [1, 40]; //fill in the number of note modifications that are suitable for you. 4 | const offsetX = 20; //Adjust the offset of the tooltip according to your needs. 5 | const offsetY = 40; //Adjust the offset of the tooltip according to your needs. 6 | 7 | function generateDataset(displayedMonthCount, options = {}) { 8 | const config = Object.assign({}, { 9 | endDate: null, 10 | fill: {}, 11 | }, options); 12 | const months = []; 13 | let days = []; 14 | 15 | let referDate = config.endDate ? new Date(config.endDate) : new Date(); 16 | referDate.setDate(1); 17 | 18 | for (let i = 0; i < displayedMonthCount; i++) { 19 | let currentMonth = new Date(referDate.getFullYear(), referDate.getMonth() - i, 1); 20 | let nextMonth = new Date(referDate.getFullYear(), referDate.getMonth() - i + 1, 1); 21 | 22 | let month = (currentMonth.getMonth() + 1).toString().padStart(2, '0'); 23 | months.unshift(currentMonth.getFullYear() + '-' + month); 24 | 25 | const monthDays = []; 26 | while (currentMonth < nextMonth) { 27 | let day = currentMonth.getDate().toString().padStart(2, '0'); 28 | let dateStr = currentMonth.getFullYear() + '-' + month + '-' + day; 29 | 30 | let data = { 31 | date: dateStr, 32 | }; 33 | 34 | if (config.fill.hasOwnProperty(dateStr)) { 35 | data.total = config.fill[dateStr]; 36 | } 37 | monthDays.push(data); 38 | currentMonth.setDate(currentMonth.getDate() + 1); 39 | } 40 | days.unshift(...monthDays) 41 | } 42 | 43 | days = days.slice(days.length % 365); 44 | 45 | return { days, months }; 46 | } 47 | 48 | const datas = await api.runOnBackend(() => { 49 | const editedNotes = api.sql.getMap(`SELECT date , COUNT(*) FROM ( 50 | SELECT noteId, SUBSTR(dateModified, 0, 11) AS date FROM notes 51 | UNION 52 | SELECT DISTINCT noteId, SUBSTR(dateCreated, 0, 11) AS date FROM revisions 53 | ) 54 | GROUP BY date`); 55 | return editedNotes; 56 | }); 57 | 58 | const width = 1000; 59 | const height = 180; 60 | const margin = 30; 61 | const weekBoxWidth = 20; 62 | const monthBoxHeight = 20; 63 | 64 | function updateCells(cellBox, dataset) { 65 | const cellMargin = 3; 66 | const cellSize = (height - margin - monthBoxHeight - cellMargin * 6 - 10) / 7; 67 | let cellCol = 1; 68 | const colorScale = d3.scaleSequential() 69 | .domain(dataRange) 70 | .interpolator(d3.interpolateRgb(colorRange[0], colorRange[1])); 71 | 72 | const weekOffset = (new Date(dataset.days[0].date).getDay() + 6) % 7; 73 | 74 | const cells = cellBox.selectAll('rect').data(dataset.days); 75 | 76 | cells.attr('fill', v => { 77 | if (v.total == undefined) { 78 | return '#EFEFEF'; 79 | } 80 | if (v.total >= 1) { 81 | return colorScale(v.total); 82 | } 83 | }) 84 | .attr('x', (v, i) => { 85 | if ((i + weekOffset) % 7 == 0 && i != 0) { 86 | cellCol++; 87 | } 88 | const x = (cellCol - 1) * cellSize; 89 | const offset = Math.floor(i / (365)) * -((cellMargin + cellSize) * 52); 90 | return offset + (cellCol > 1 ? x + cellMargin * (cellCol - 1) : x); 91 | }) 92 | .attr('y', (v, i) => { 93 | const y = (i + weekOffset) % 7; 94 | const offset = Math.floor(i / (365)) * height; 95 | return offset + (y > 0 ? y * cellSize + cellMargin * y : y * cellSize); 96 | }); 97 | 98 | cells.enter() 99 | .append('rect') 100 | .attr('width', cellSize) 101 | .attr('height', cellSize) 102 | .attr('rx', 3) 103 | .attr('fill', v => { 104 | if (v.total == undefined) { 105 | return '#EFEFEF'; 106 | } 107 | if (v.total >= 1) { 108 | return colorScale(v.total); 109 | } 110 | }) 111 | .attr('x', (v, i) => { 112 | if ((i + weekOffset) % 7 == 0 && i != 0) { 113 | cellCol++; 114 | } 115 | const x = (cellCol - 1) * cellSize; 116 | const offset = Math.floor(i / (365)) * -((cellMargin + cellSize) * 52); 117 | return offset + (cellCol > 1 ? x + cellMargin * (cellCol - 1) : x); 118 | }) 119 | .attr('y', (v, i) => { 120 | const y = (i + weekOffset) % 7; 121 | const offset = Math.floor(i / (365)) * height; 122 | return offset + (y > 0 ? y * cellSize + cellMargin * y : y * cellSize); 123 | }) 124 | .on("mouseover", function(d, v) { 125 | const element = d3.select(this); 126 | element.style("stroke", "black"); 127 | const parentElement = document.getElementById("trilium-heatmap"); 128 | const elementSVG = parentElement.getBoundingClientRect(); 129 | 130 | const x = d.pageX - elementSVG.left; 131 | const y = d.pageY - elementSVG.top; 132 | const tooltip = document.getElementById("heatmap-tooltip"); 133 | if (v.total == undefined) { v.total = '0'; } 134 | tooltip.innerHTML = `${v.total.toString()} notes Modified in ${v.date}`; 135 | tooltip.style.left = `${x + offsetX}px`; 136 | tooltip.style.top = `${y + offsetY}px`; 137 | tooltip.style.display = "block"; 138 | }) 139 | .on("mouseout", function(d) { 140 | const element = d3.select(this); 141 | element.style("stroke", null); 142 | const tooltip = document.getElementById("heatmap-tooltip"); 143 | tooltip.style.display = "none"; 144 | }) 145 | .on("click", async function(d, v) { 146 | const noteId = await api.runAsyncOnBackendWithManualTransactionHandling(async (date) => { 147 | const note = await api.getDayNote(date); 148 | return note.noteId; 149 | }, [v.date]); 150 | await api.waitUntilSynced(); 151 | api.activateNote(noteId); 152 | }); 153 | 154 | cells.exit().remove(); 155 | } 156 | 157 | function drawHeatmap(endDate=null){ 158 | const dataset = generateDataset(12, { 159 | endDate: endDate, 160 | fill: datas, 161 | }); 162 | 163 | d3.select('#trilium-heatmap') 164 | .selectAll("*") 165 | .remove(); 166 | 167 | const svg = d3.select('#trilium-heatmap') 168 | .attr('width', width) 169 | .attr('height', height); 170 | 171 | const monthBox = svg.append('g').attr( 172 | 'transform', 173 | `translate(${margin + weekBoxWidth}, ${margin})` 174 | ); 175 | 176 | const monthScale = d3.scaleLinear() 177 | .domain([0, dataset.months.length]) 178 | .range([0, width - margin - weekBoxWidth + 10]); 179 | 180 | monthBox.selectAll('text').data(dataset.months).enter() 181 | .append('text') 182 | .text(v => v) 183 | .attr('font-size', '16px') 184 | .attr('fill', '#999') 185 | .attr('cursor', 'default') 186 | .attr('x', (v, i) => monthScale(i % 12)) 187 | .attr('y', (v, i) => Math.floor(i / 12) * height); 188 | 189 | const weekBox = svg.append('g').attr( 190 | 'transform', 191 | `translate(${margin - 10}, ${margin + monthBoxHeight})` 192 | ); 193 | const weekScale = d3.scaleLinear() 194 | .domain([0, weeks.length]) 195 | .range([0, height - margin - monthBoxHeight + 15]); 196 | 197 | weekBox.selectAll('text').data(weeks).enter() 198 | .append('text') 199 | .text(v => v) 200 | .attr('font-size', '0.85em') 201 | .attr('fill', '#CCC') 202 | .attr('y', (v, i) => weekScale(i)); 203 | 204 | const cellBox = svg.append('g').attr( 205 | 'transform', 206 | `translate(${margin + weekBoxWidth}, ${margin + 10})` 207 | ); 208 | 209 | updateCells(cellBox, dataset); 210 | const previousButton = document.getElementById("button-previous"); 211 | const nextButton = document.getElementById("button-next"); 212 | previousButton.addEventListener("click", handlePreviousButtonClick); 213 | nextButton.addEventListener("click", handleNextButtonClick); 214 | function handlePreviousButtonClick() { 215 | const previousEndDate = new Date(dataset.months[0]); 216 | previousEndDate.setMonth(previousEndDate.getMonth() - 1); 217 | drawHeatmap(previousEndDate); 218 | 219 | previousButton.removeEventListener("click", handlePreviousButtonClick); 220 | nextButton.removeEventListener("click", handleNextButtonClick); 221 | } 222 | 223 | function handleNextButtonClick() { 224 | const nextEndDate = new Date(new Date(dataset.months[dataset.months.length-1])); 225 | nextEndDate.setMonth(nextEndDate.getMonth() + 12); 226 | drawHeatmap(nextEndDate); 227 | 228 | previousButton.removeEventListener("click", handlePreviousButtonClick); 229 | nextButton.removeEventListener("click", handleNextButtonClick); 230 | } 231 | } 232 | 233 | drawHeatmap(); -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | /* !!!!!! TRILIUM CUSTOM CHANGES !!!!!! */ 2 | 3 | .printed-content .ck-widget__selection-handle, .printed-content .ck-widget__type-around { /* gets rid of triangles: https://github.com/zadam/trilium/issues/1129 */ 4 | display: none; 5 | } 6 | 7 | /* 8 | * CKEditor 5 (v38.1.1) content styles. 9 | * Generated on Thu, 27 Jul 2023 08:16:09 GMT. 10 | * For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html 11 | */ 12 | 13 | :root { 14 | --ck-color-image-caption-background: hsl(0, 0%, 97%); 15 | --ck-color-image-caption-text: hsl(0, 0%, 20%); 16 | --ck-color-mention-background: hsla(341, 100%, 30%, 0.1); 17 | --ck-color-mention-text: hsl(341, 100%, 30%); 18 | --ck-color-table-caption-background: hsl(0, 0%, 97%); 19 | --ck-color-table-caption-text: hsl(0, 0%, 20%); 20 | --ck-highlight-marker-blue: hsl(201, 97%, 72%); 21 | --ck-highlight-marker-green: hsl(120, 93%, 68%); 22 | --ck-highlight-marker-pink: hsl(345, 96%, 73%); 23 | --ck-highlight-marker-yellow: hsl(60, 97%, 73%); 24 | --ck-highlight-pen-green: hsl(112, 100%, 27%); 25 | --ck-highlight-pen-red: hsl(0, 85%, 49%); 26 | --ck-image-style-spacing: 1.5em; 27 | --ck-inline-image-style-spacing: calc(var(--ck-image-style-spacing) / 2); 28 | --ck-todo-list-checkmark-size: 16px; 29 | } 30 | 31 | /* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */ 32 | .ck-content .table .ck-table-resized { 33 | table-layout: fixed; 34 | } 35 | /* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */ 36 | .ck-content .table table { 37 | overflow: hidden; 38 | } 39 | /* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */ 40 | .ck-content .table td, 41 | .ck-content .table th { 42 | overflow-wrap: break-word; 43 | position: relative; 44 | } 45 | /* @ckeditor/ckeditor5-table/theme/tablecaption.css */ 46 | .ck-content .table > figcaption { 47 | display: table-caption; 48 | caption-side: top; 49 | word-break: break-word; 50 | text-align: center; 51 | color: var(--ck-color-table-caption-text); 52 | background-color: var(--ck-color-table-caption-background); 53 | padding: .6em; 54 | font-size: .75em; 55 | outline-offset: -1px; 56 | } 57 | /* @ckeditor/ckeditor5-table/theme/table.css */ 58 | .ck-content .table { 59 | margin: 0.9em auto; 60 | display: table; 61 | } 62 | /* @ckeditor/ckeditor5-table/theme/table.css */ 63 | .ck-content .table table { 64 | border-collapse: collapse; 65 | border-spacing: 0; 66 | width: 100%; 67 | height: 100%; 68 | border: 1px double hsl(0, 0%, 70%); 69 | } 70 | /* @ckeditor/ckeditor5-table/theme/table.css */ 71 | .ck-content .table table td, 72 | .ck-content .table table th { 73 | min-width: 2em; 74 | padding: .4em; 75 | border: 1px solid hsl(0, 0%, 75%); 76 | } 77 | /* @ckeditor/ckeditor5-table/theme/table.css */ 78 | .ck-content .table table th { 79 | font-weight: bold; 80 | background: hsla(0, 0%, 0%, 5%); 81 | } 82 | /* @ckeditor/ckeditor5-table/theme/table.css */ 83 | .ck-content[dir="rtl"] .table th { 84 | text-align: right; 85 | } 86 | /* @ckeditor/ckeditor5-table/theme/table.css */ 87 | .ck-content[dir="ltr"] .table th { 88 | text-align: left; 89 | } 90 | /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ 91 | .ck-content .page-break { 92 | position: relative; 93 | clear: both; 94 | padding: 5px 0; 95 | display: flex; 96 | align-items: center; 97 | justify-content: center; 98 | } 99 | /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ 100 | .ck-content .page-break::after { 101 | content: ''; 102 | position: absolute; 103 | border-bottom: 2px dashed hsl(0, 0%, 77%); 104 | width: 100%; 105 | } 106 | /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ 107 | .ck-content .page-break__label { 108 | position: relative; 109 | z-index: 1; 110 | padding: .3em .6em; 111 | display: block; 112 | text-transform: uppercase; 113 | border: 1px solid hsl(0, 0%, 77%); 114 | border-radius: 2px; 115 | font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif; 116 | font-size: 0.75em; 117 | font-weight: bold; 118 | color: hsl(0, 0%, 20%); 119 | background: hsl(0, 0%, 100%); 120 | box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15); 121 | -webkit-user-select: none; 122 | -moz-user-select: none; 123 | -ms-user-select: none; 124 | user-select: none; 125 | } 126 | /* @ckeditor/ckeditor5-media-embed/theme/mediaembed.css */ 127 | .ck-content .media { 128 | clear: both; 129 | margin: 0.9em 0; 130 | display: block; 131 | min-width: 15em; 132 | } 133 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 134 | .ck-content .todo-list { 135 | list-style: none; 136 | } 137 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 138 | .ck-content .todo-list li { 139 | margin-bottom: 5px; 140 | } 141 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 142 | .ck-content .todo-list li .todo-list { 143 | margin-top: 5px; 144 | } 145 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 146 | .ck-content .todo-list .todo-list__label > input { 147 | -webkit-appearance: none; 148 | display: inline-block; 149 | position: relative; 150 | width: var(--ck-todo-list-checkmark-size); 151 | height: var(--ck-todo-list-checkmark-size); 152 | vertical-align: middle; 153 | border: 0; 154 | left: -25px; 155 | margin-right: -15px; 156 | right: 0; 157 | margin-left: 0; 158 | } 159 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 160 | .ck-content .todo-list .todo-list__label > input::before { 161 | display: block; 162 | position: absolute; 163 | box-sizing: border-box; 164 | content: ''; 165 | width: 100%; 166 | height: 100%; 167 | border: 1px solid hsl(0, 0%, 20%); 168 | border-radius: 2px; 169 | transition: 250ms ease-in-out box-shadow, 250ms ease-in-out background, 250ms ease-in-out border; 170 | } 171 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 172 | .ck-content .todo-list .todo-list__label > input::after { 173 | display: block; 174 | position: absolute; 175 | box-sizing: content-box; 176 | pointer-events: none; 177 | content: ''; 178 | left: calc( var(--ck-todo-list-checkmark-size) / 3 ); 179 | top: calc( var(--ck-todo-list-checkmark-size) / 5.3 ); 180 | width: calc( var(--ck-todo-list-checkmark-size) / 5.3 ); 181 | height: calc( var(--ck-todo-list-checkmark-size) / 2.6 ); 182 | border-style: solid; 183 | border-color: transparent; 184 | border-width: 0 calc( var(--ck-todo-list-checkmark-size) / 8 ) calc( var(--ck-todo-list-checkmark-size) / 8 ) 0; 185 | transform: rotate(45deg); 186 | } 187 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 188 | .ck-content .todo-list .todo-list__label > input[checked]::before { 189 | background: hsl(126, 64%, 41%); 190 | border-color: hsl(126, 64%, 41%); 191 | } 192 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 193 | .ck-content .todo-list .todo-list__label > input[checked]::after { 194 | border-color: hsl(0, 0%, 100%); 195 | } 196 | /* @ckeditor/ckeditor5-list/theme/todolist.css */ 197 | .ck-content .todo-list .todo-list__label .todo-list__label__description { 198 | vertical-align: middle; 199 | } 200 | /* @ckeditor/ckeditor5-image/theme/image.css */ 201 | .ck-content .image { 202 | display: table; 203 | clear: both; 204 | text-align: center; 205 | margin: 0.9em auto; 206 | min-width: 50px; 207 | } 208 | /* @ckeditor/ckeditor5-image/theme/image.css */ 209 | .ck-content .image img { 210 | display: block; 211 | margin: 0 auto; 212 | max-width: 100%; 213 | min-width: 100%; 214 | } 215 | /* @ckeditor/ckeditor5-image/theme/image.css */ 216 | .ck-content .image-inline { 217 | /* 218 | * Normally, the .image-inline would have "display: inline-block" and "img { width: 100% }" (to follow the wrapper while resizing).; 219 | * Unfortunately, together with "srcset", it gets automatically stretched up to the width of the editing root. 220 | * This strange behavior does not happen with inline-flex. 221 | */ 222 | display: inline-flex; 223 | max-width: 100%; 224 | align-items: flex-start; 225 | } 226 | /* @ckeditor/ckeditor5-image/theme/image.css */ 227 | .ck-content .image-inline picture { 228 | display: flex; 229 | } 230 | /* @ckeditor/ckeditor5-image/theme/image.css */ 231 | .ck-content .image-inline picture, 232 | .ck-content .image-inline img { 233 | flex-grow: 1; 234 | flex-shrink: 1; 235 | max-width: 100%; 236 | } 237 | /* @ckeditor/ckeditor5-image/theme/imageresize.css */ 238 | .ck-content .image.image_resized { 239 | max-width: 100%; 240 | display: block; 241 | box-sizing: border-box; 242 | } 243 | /* @ckeditor/ckeditor5-image/theme/imageresize.css */ 244 | .ck-content .image.image_resized img { 245 | width: 100%; 246 | } 247 | /* @ckeditor/ckeditor5-image/theme/imageresize.css */ 248 | .ck-content .image.image_resized > figcaption { 249 | display: block; 250 | } 251 | /* @ckeditor/ckeditor5-image/theme/imagecaption.css */ 252 | .ck-content .image > figcaption { 253 | display: table-caption; 254 | caption-side: bottom; 255 | word-break: break-word; 256 | color: var(--ck-color-image-caption-text); 257 | background-color: var(--ck-color-image-caption-background); 258 | padding: .6em; 259 | font-size: .75em; 260 | outline-offset: -1px; 261 | } 262 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 263 | .ck-content .marker-yellow { 264 | background-color: var(--ck-highlight-marker-yellow); 265 | } 266 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 267 | .ck-content .marker-green { 268 | background-color: var(--ck-highlight-marker-green); 269 | } 270 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 271 | .ck-content .marker-pink { 272 | background-color: var(--ck-highlight-marker-pink); 273 | } 274 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 275 | .ck-content .marker-blue { 276 | background-color: var(--ck-highlight-marker-blue); 277 | } 278 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 279 | .ck-content .pen-red { 280 | color: var(--ck-highlight-pen-red); 281 | background-color: transparent; 282 | } 283 | /* @ckeditor/ckeditor5-highlight/theme/highlight.css */ 284 | .ck-content .pen-green { 285 | color: var(--ck-highlight-pen-green); 286 | background-color: transparent; 287 | } 288 | /* @ckeditor/ckeditor5-list/theme/list.css */ 289 | .ck-content ol { 290 | list-style-type: decimal; 291 | } 292 | /* @ckeditor/ckeditor5-list/theme/list.css */ 293 | .ck-content ol ol { 294 | list-style-type: lower-latin; 295 | } 296 | /* @ckeditor/ckeditor5-list/theme/list.css */ 297 | .ck-content ol ol ol { 298 | list-style-type: lower-roman; 299 | } 300 | /* @ckeditor/ckeditor5-list/theme/list.css */ 301 | .ck-content ol ol ol ol { 302 | list-style-type: upper-latin; 303 | } 304 | /* @ckeditor/ckeditor5-list/theme/list.css */ 305 | .ck-content ol ol ol ol ol { 306 | list-style-type: upper-roman; 307 | } 308 | /* @ckeditor/ckeditor5-list/theme/list.css */ 309 | .ck-content ul { 310 | list-style-type: disc; 311 | } 312 | /* @ckeditor/ckeditor5-list/theme/list.css */ 313 | .ck-content ul ul { 314 | list-style-type: circle; 315 | } 316 | /* @ckeditor/ckeditor5-list/theme/list.css */ 317 | .ck-content ul ul ul { 318 | list-style-type: square; 319 | } 320 | /* @ckeditor/ckeditor5-list/theme/list.css */ 321 | .ck-content ul ul ul ul { 322 | list-style-type: square; 323 | } 324 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 325 | .ck-content .image-style-block-align-left, 326 | .ck-content .image-style-block-align-right { 327 | max-width: calc(100% - var(--ck-image-style-spacing)); 328 | } 329 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 330 | .ck-content .image-style-align-left, 331 | .ck-content .image-style-align-right { 332 | clear: none; 333 | } 334 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 335 | .ck-content .image-style-side { 336 | float: right; 337 | margin-left: var(--ck-image-style-spacing); 338 | max-width: 50%; 339 | } 340 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 341 | .ck-content .image-style-align-left { 342 | float: left; 343 | margin-right: var(--ck-image-style-spacing); 344 | } 345 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 346 | .ck-content .image-style-align-center { 347 | margin-left: auto; 348 | margin-right: auto; 349 | } 350 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 351 | .ck-content .image-style-align-right { 352 | float: right; 353 | margin-left: var(--ck-image-style-spacing); 354 | } 355 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 356 | .ck-content .image-style-block-align-right { 357 | margin-right: 0; 358 | margin-left: auto; 359 | } 360 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 361 | .ck-content .image-style-block-align-left { 362 | margin-left: 0; 363 | margin-right: auto; 364 | } 365 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 366 | .ck-content p + .image-style-align-left, 367 | .ck-content p + .image-style-align-right, 368 | .ck-content p + .image-style-side { 369 | margin-top: 0; 370 | } 371 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 372 | .ck-content .image-inline.image-style-align-left, 373 | .ck-content .image-inline.image-style-align-right { 374 | margin-top: var(--ck-inline-image-style-spacing); 375 | margin-bottom: var(--ck-inline-image-style-spacing); 376 | } 377 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 378 | .ck-content .image-inline.image-style-align-left { 379 | margin-right: var(--ck-inline-image-style-spacing); 380 | } 381 | /* @ckeditor/ckeditor5-image/theme/imagestyle.css */ 382 | .ck-content .image-inline.image-style-align-right { 383 | margin-left: var(--ck-inline-image-style-spacing); 384 | } 385 | /* @ckeditor/ckeditor5-basic-styles/theme/code.css */ 386 | .ck-content code { 387 | background-color: hsla(0, 0%, 78%, 0.3); 388 | padding: .15em; 389 | border-radius: 2px; 390 | } 391 | /* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */ 392 | .ck-content blockquote { 393 | overflow: hidden; 394 | padding-right: 1.5em; 395 | padding-left: 1.5em; 396 | margin-left: 0; 397 | margin-right: 0; 398 | font-style: italic; 399 | border-left: solid 5px hsl(0, 0%, 80%); 400 | } 401 | /* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */ 402 | .ck-content[dir="rtl"] blockquote { 403 | border-left: 0; 404 | border-right: solid 5px hsl(0, 0%, 80%); 405 | } 406 | /* @ckeditor/ckeditor5-font/theme/fontsize.css */ 407 | .ck-content .text-tiny { 408 | font-size: .7em; 409 | } 410 | /* @ckeditor/ckeditor5-font/theme/fontsize.css */ 411 | .ck-content .text-small { 412 | font-size: .85em; 413 | } 414 | /* @ckeditor/ckeditor5-font/theme/fontsize.css */ 415 | .ck-content .text-big { 416 | font-size: 1.4em; 417 | } 418 | /* @ckeditor/ckeditor5-font/theme/fontsize.css */ 419 | .ck-content .text-huge { 420 | font-size: 1.8em; 421 | } 422 | /* @ckeditor/ckeditor5-mention/theme/mention.css */ 423 | .ck-content .mention { 424 | background: var(--ck-color-mention-background); 425 | color: var(--ck-color-mention-text); 426 | } 427 | /* @ckeditor/ckeditor5-horizontal-line/theme/horizontalline.css */ 428 | .ck-content hr { 429 | margin: 15px 0; 430 | height: 4px; 431 | background: hsl(0, 0%, 87%); 432 | border: 0; 433 | } 434 | /* @ckeditor/ckeditor5-code-block/theme/codeblock.css */ 435 | .ck-content pre { 436 | padding: 1em; 437 | color: hsl(0, 0%, 20.8%); 438 | background: hsla(0, 0%, 78%, 0.3); 439 | border: 1px solid hsl(0, 0%, 77%); 440 | border-radius: 2px; 441 | text-align: left; 442 | direction: ltr; 443 | tab-size: 4; 444 | white-space: pre-wrap; 445 | font-style: normal; 446 | min-width: 200px; 447 | } 448 | /* @ckeditor/ckeditor5-code-block/theme/codeblock.css */ 449 | .ck-content pre code { 450 | background: unset; 451 | padding: 0; 452 | border-radius: 0; 453 | } 454 | @media print { 455 | /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ 456 | .ck-content .page-break { 457 | padding: 0; 458 | } 459 | /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ 460 | .ck-content .page-break::after { 461 | display: none; 462 | } 463 | } 464 | --------------------------------------------------------------------------------