diff --git a/_includes/head.liquid b/_includes/head.liquid index 1e5503359cab..1035e72e51b2 100644 --- a/_includes/head.liquid +++ b/_includes/head.liquid @@ -12,7 +12,9 @@ > - +{% if page.pretty_table %} + +{% endif %} @@ -72,6 +74,21 @@ > {% endif %} + +{% if page.code_diff %} + + + +{% endif %} + {% if page.images %} {% if page.images.compare %} diff --git a/_includes/scripts/codeDiff.liquid b/_includes/scripts/codeDiff.liquid new file mode 100644 index 000000000000..fb8a85454246 --- /dev/null +++ b/_includes/scripts/codeDiff.liquid @@ -0,0 +1,26 @@ +{% if page.code_diff %} + + + +{% endif %} diff --git a/_includes/scripts/misc.liquid b/_includes/scripts/misc.liquid index 8baf2b17cddd..61223b17acf4 100644 --- a/_includes/scripts/misc.liquid +++ b/_includes/scripts/misc.liquid @@ -22,7 +22,10 @@ {% endif %} - +{% if page.pretty_table %} + + +{% endif %} diff --git a/_layouts/default.liquid b/_layouts/default.liquid index 7f628e652c33..c5a7fabfef25 100644 --- a/_layouts/default.liquid +++ b/_layouts/default.liquid @@ -48,6 +48,7 @@ {% include scripts/bootstrap.liquid %} {% include scripts/masonry.liquid %} {% include scripts/mermaid.liquid %} + {% include scripts/codeDiff.liquid %} {% include scripts/leaflet.liquid %} {% include scripts/chartjs.liquid %} {% include scripts/echarts.liquid %} diff --git a/_posts/2023-03-21-tables.md b/_posts/2023-03-21-tables.md index 700a2128e7ce..da1d7e89d6a5 100644 --- a/_posts/2023-03-21-tables.md +++ b/_posts/2023-03-21-tables.md @@ -7,7 +7,7 @@ tags: formatting tables categories: sample-posts giscus_comments: true related_posts: true -datatable: true +pretty_table: true --- Using markdown to display tables is easy. Just use the following syntax: diff --git a/_posts/2024-01-27-code-diff.md b/_posts/2024-01-27-code-diff.md new file mode 100644 index 000000000000..6ec06d5b7107 --- /dev/null +++ b/_posts/2024-01-27-code-diff.md @@ -0,0 +1,473 @@ +--- +layout: post +title: a post with code diff +date: 2024-01-27 19:22:00 +description: this is how you can display code diffs +tags: formatting code +categories: sample-posts +code_diff: true +--- + +You can display diff code by using the regular markdown syntax: + +````markdown +```diff +diff --git a/sample.js b/sample.js +index 0000001..0ddf2ba +--- a/sample.js ++++ b/sample.js +@@ -1 +1 @@ +-console.log("Hello World!") ++console.log("Hello from Diff2Html!") +``` +```` + +Which generates: + +```diff +diff --git a/sample.js b/sample.js +index 0000001..0ddf2ba +--- a/sample.js ++++ b/sample.js +@@ -1 +1 @@ +-console.log("Hello World!") ++console.log("Hello from Diff2Html!") +``` + +But this is difficult to read, specially if you have a large diff. You can use [diff2html](https://diff2html.xyz/) to display a more readable version of the diff. For this, just use `diff2html` instead of `diff` for the code block language: + +````markdown +```diff2html +diff --git a/sample.js b/sample.js +index 0000001..0ddf2ba +--- a/sample.js ++++ b/sample.js +@@ -1 +1 @@ +-console.log("Hello World!") ++console.log("Hello from Diff2Html!") +``` +```` + +If we use a longer example, for example [this commit from diff2html](https://github.com/rtfpessoa/diff2html/commit/c2c253d3e3f8b8b267f551e659f72b44ca2ac927), it will generate the following output: + +```diff2html +From 2aaae31cc2a37bfff83430c2c914b140bee59b6a Mon Sep 17 00:00:00 2001 +From: Rodrigo Fernandes +Date: Sun, 9 Oct 2016 16:41:54 +0100 +Subject: [PATCH 1/2] Initial template override support + +--- + scripts/hulk.js | 4 ++-- + src/diff2html.js | 3 +-- + src/file-list-printer.js | 11 ++++++++--- + src/hoganjs-utils.js | 29 +++++++++++++++++------------ + src/html-printer.js | 6 ++++++ + src/line-by-line-printer.js | 6 +++++- + src/side-by-side-printer.js | 6 +++++- + test/file-list-printer-tests.js | 2 +- + test/hogan-cache-tests.js | 18 +++++++++++++++--- + test/line-by-line-tests.js | 3 +-- + test/side-by-side-printer-tests.js | 3 +-- + 11 files changed, 62 insertions(+), 29 deletions(-) + +diff --git a/scripts/hulk.js b/scripts/hulk.js +index 5a793c18..a4b1a4d5 100755 +--- a/scripts/hulk.js ++++ b/scripts/hulk.js +@@ -173,11 +173,11 @@ function namespace(name) { + // write a template foreach file that matches template extension + templates = extractFiles(options.argv.remain) + .map(function(file) { +- var openedFile = fs.readFileSync(file, 'utf-8'); ++ var openedFile = fs.readFileSync(file, 'utf-8').trim(); + var name; + if (!openedFile) return; + name = namespace(path.basename(file).replace(/\..*$/, '')); +- openedFile = removeByteOrderMark(openedFile.trim()); ++ openedFile = removeByteOrderMark(openedFile); + openedFile = wrap(file, name, openedFile); + if (!options.outputdir) return openedFile; + fs.writeFileSync(path.join(options.outputdir, name + '.js') +diff --git a/src/diff2html.js b/src/diff2html.js +index 21b0119e..64e138f5 100644 +--- a/src/diff2html.js ++++ b/src/diff2html.js +@@ -7,7 +7,6 @@ + + (function() { + var diffParser = require('./diff-parser.js').DiffParser; +- var fileLister = require('./file-list-printer.js').FileListPrinter; + var htmlPrinter = require('./html-printer.js').HtmlPrinter; + + function Diff2Html() { +@@ -43,7 +42,7 @@ + + var fileList = ''; + if (configOrEmpty.showFiles === true) { +- fileList = fileLister.generateFileList(diffJson, configOrEmpty); ++ fileList = htmlPrinter.generateFileListSummary(diffJson, configOrEmpty); + } + + var diffOutput = ''; +diff --git a/src/file-list-printer.js b/src/file-list-printer.js +index e408d9b2..1e0a2c61 100644 +--- a/src/file-list-printer.js ++++ b/src/file-list-printer.js +@@ -8,11 +8,16 @@ + (function() { + var printerUtils = require('./printer-utils.js').PrinterUtils; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var baseTemplatesPath = 'file-summary'; + var iconsBaseTemplatesPath = 'icon'; + +- function FileListPrinter() { ++ function FileListPrinter(config) { ++ this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + FileListPrinter.prototype.generateFileList = function(diffFiles) { +@@ -38,5 +43,5 @@ + }); + }; + +- module.exports.FileListPrinter = new FileListPrinter(); ++ module.exports.FileListPrinter = FileListPrinter; + })(); +diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js +index 9949e5fa..0dda08d7 100644 +--- a/src/hoganjs-utils.js ++++ b/src/hoganjs-utils.js +@@ -8,18 +8,19 @@ + (function() { + var fs = require('fs'); + var path = require('path'); +- + var hogan = require('hogan.js'); + + var hoganTemplates = require('./templates/diff2html-templates.js'); + +- var templatesPath = path.resolve(__dirname, 'templates'); ++ var extraTemplates; + +- function HoganJsUtils() { ++ function HoganJsUtils(configuration) { ++ this.config = configuration || {}; ++ extraTemplates = this.config.templates || {}; + } + +- HoganJsUtils.prototype.render = function(namespace, view, params, configuration) { +- var template = this.template(namespace, view, configuration); ++ HoganJsUtils.prototype.render = function(namespace, view, params) { ++ var template = this.template(namespace, view); + if (template) { + return template.render(params); + } +@@ -27,17 +28,16 @@ + return null; + }; + +- HoganJsUtils.prototype.template = function(namespace, view, configuration) { +- var config = configuration || {}; ++ HoganJsUtils.prototype.template = function(namespace, view) { + var templateKey = this._templateKey(namespace, view); + +- return this._getTemplate(templateKey, config); ++ return this._getTemplate(templateKey); + }; + +- HoganJsUtils.prototype._getTemplate = function(templateKey, config) { ++ HoganJsUtils.prototype._getTemplate = function(templateKey) { + var template; + +- if (!config.noCache) { ++ if (!this.config.noCache) { + template = this._readFromCache(templateKey); + } + +@@ -53,6 +53,7 @@ + + try { + if (fs.readFileSync) { ++ var templatesPath = path.resolve(__dirname, 'templates'); + var templatePath = path.join(templatesPath, templateKey); + var templateContent = fs.readFileSync(templatePath + '.mustache', 'utf8'); + template = hogan.compile(templateContent); +@@ -66,12 +67,16 @@ + }; + + HoganJsUtils.prototype._readFromCache = function(templateKey) { +- return hoganTemplates[templateKey]; ++ return extraTemplates[templateKey] || hoganTemplates[templateKey]; + }; + + HoganJsUtils.prototype._templateKey = function(namespace, view) { + return namespace + '-' + view; + }; + +- module.exports.HoganJsUtils = new HoganJsUtils(); ++ HoganJsUtils.prototype.compile = function(templateStr) { ++ return hogan.compile(templateStr); ++ }; ++ ++ module.exports.HoganJsUtils = HoganJsUtils; + })(); +diff --git a/src/html-printer.js b/src/html-printer.js +index 585d5b66..13f83047 100644 +--- a/src/html-printer.js ++++ b/src/html-printer.js +@@ -8,6 +8,7 @@ + (function() { + var LineByLinePrinter = require('./line-by-line-printer.js').LineByLinePrinter; + var SideBySidePrinter = require('./side-by-side-printer.js').SideBySidePrinter; ++ var FileListPrinter = require('./file-list-printer.js').FileListPrinter; + + function HtmlPrinter() { + } +@@ -22,5 +23,10 @@ + return sideBySidePrinter.generateSideBySideJsonHtml(diffFiles); + }; + ++ HtmlPrinter.prototype.generateFileListSummary = function(diffJson, config) { ++ var fileListPrinter = new FileListPrinter(config); ++ return fileListPrinter.generateFileList(diffJson); ++ }; ++ + module.exports.HtmlPrinter = new HtmlPrinter(); + })(); +diff --git a/src/line-by-line-printer.js b/src/line-by-line-printer.js +index b07eb53c..d230bedd 100644 +--- a/src/line-by-line-printer.js ++++ b/src/line-by-line-printer.js +@@ -11,7 +11,8 @@ + var utils = require('./utils.js').Utils; + var Rematch = require('./rematch.js').Rematch; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var genericTemplatesPath = 'generic'; + var baseTemplatesPath = 'line-by-line'; + var iconsBaseTemplatesPath = 'icon'; +@@ -19,6 +20,9 @@ + + function LineByLinePrinter(config) { + this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + LineByLinePrinter.prototype.makeFileDiffHtml = function(file, diffs) { +diff --git a/src/side-by-side-printer.js b/src/side-by-side-printer.js +index bbf1dc8d..5e3033b3 100644 +--- a/src/side-by-side-printer.js ++++ b/src/side-by-side-printer.js +@@ -11,7 +11,8 @@ + var utils = require('./utils.js').Utils; + var Rematch = require('./rematch.js').Rematch; + +- var hoganUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ var hoganUtils; ++ + var genericTemplatesPath = 'generic'; + var baseTemplatesPath = 'side-by-side'; + var iconsBaseTemplatesPath = 'icon'; +@@ -26,6 +27,9 @@ + + function SideBySidePrinter(config) { + this.config = config; ++ ++ var HoganJsUtils = require('./hoganjs-utils.js').HoganJsUtils; ++ hoganUtils = new HoganJsUtils(config); + } + + SideBySidePrinter.prototype.makeDiffHtml = function(file, diffs) { +diff --git a/test/file-list-printer-tests.js b/test/file-list-printer-tests.js +index a502a46f..60ea3208 100644 +--- a/test/file-list-printer-tests.js ++++ b/test/file-list-printer-tests.js +@@ -1,6 +1,6 @@ + var assert = require('assert'); + +-var fileListPrinter = require('../src/file-list-printer.js').FileListPrinter; ++var fileListPrinter = new (require('../src/file-list-printer.js').FileListPrinter)(); + + describe('FileListPrinter', function() { + describe('generateFileList', function() { +diff --git a/test/hogan-cache-tests.js b/test/hogan-cache-tests.js +index 190bf6f8..3bb754ac 100644 +--- a/test/hogan-cache-tests.js ++++ b/test/hogan-cache-tests.js +@@ -1,6 +1,6 @@ + var assert = require('assert'); + +-var HoganJsUtils = require('../src/hoganjs-utils.js').HoganJsUtils; ++var HoganJsUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(); + var diffParser = require('../src/diff-parser.js').DiffParser; + + describe('HoganJsUtils', function() { +@@ -21,16 +21,28 @@ describe('HoganJsUtils', function() { + }); + assert.equal(emptyDiffHtml, result); + }); ++ + it('should render view without cache', function() { + var result = HoganJsUtils.render('generic', 'empty-diff', { + contentClass: 'd2h-code-line', + diffParser: diffParser + }, {noCache: true}); +- assert.equal(emptyDiffHtml + '\n', result); ++ assert.equal(emptyDiffHtml, result); + }); ++ + it('should return null if template is missing', function() { +- var result = HoganJsUtils.render('generic', 'missing-template', {}, {noCache: true}); ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)({noCache: true}); ++ var result = hoganUtils.render('generic', 'missing-template', {}); + assert.equal(null, result); + }); ++ ++ it('should allow templates to be overridden', function() { ++ var emptyDiffTemplate = HoganJsUtils.compile('

{{myName}}

'); ++ ++ var config = {templates: {'generic-empty-diff': emptyDiffTemplate}}; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

Rodrigo Fernandes

', result); ++ }); + }); + }); +diff --git a/test/line-by-line-tests.js b/test/line-by-line-tests.js +index 1cd92073..8869b3df 100644 +--- a/test/line-by-line-tests.js ++++ b/test/line-by-line-tests.js +@@ -14,7 +14,7 @@ describe('LineByLinePrinter', function() { + ' File without changes\n' + + ' \n' + + ' \n' + +- '\n'; ++ ''; + + assert.equal(expected, fileHtml); + }); +@@ -422,7 +422,6 @@ describe('LineByLinePrinter', function() { + ' \n' + + ' \n' + + '\n' + +- '\n' + + ' \n' + + ' \n' + + ' \n' + +diff --git a/test/side-by-side-printer-tests.js b/test/side-by-side-printer-tests.js +index 76625f8e..771daaa5 100644 +--- a/test/side-by-side-printer-tests.js ++++ b/test/side-by-side-printer-tests.js +@@ -14,7 +14,7 @@ describe('SideBySidePrinter', function() { + ' File without changes\n' + + ' \n' + + ' \n' + +- '\n'; ++ ''; + + assert.equal(expectedRight, fileHtml.right); + assert.equal(expectedLeft, fileHtml.left); +@@ -324,7 +324,6 @@ describe('SideBySidePrinter', function() { + ' \n' + + ' \n' + + '\n' + +- '\n' + + ' \n' + + ' \n' + + ' \n' + + +From f3cadb96677d0eb82fc2752dc3ffbf35ca9b5bdb Mon Sep 17 00:00:00 2001 +From: Rodrigo Fernandes +Date: Sat, 15 Oct 2016 13:21:22 +0100 +Subject: [PATCH 2/2] Allow uncompiled templates + +--- + README.md | 3 +++ + src/hoganjs-utils.js | 7 +++++++ + test/hogan-cache-tests.js | 24 +++++++++++++++++++++++- + 3 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index 132c8a28..46909f25 100644 +--- a/README.md ++++ b/README.md +@@ -98,6 +98,9 @@ The HTML output accepts a Javascript object with configuration. Possible options + - `synchronisedScroll`: scroll both panes in side-by-side mode: `true` or `false`, default is `false` + - `matchWordsThreshold`: similarity threshold for word matching, default is 0.25 + - `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is `2500` ++ - `templates`: object with previously compiled templates to replace parts of the html ++ - `rawTemplates`: object with raw not compiled templates to replace parts of the html ++ > For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates) + + ## Diff2HtmlUI Helper + +diff --git a/src/hoganjs-utils.js b/src/hoganjs-utils.js +index 0dda08d7..b2e9c275 100644 +--- a/src/hoganjs-utils.js ++++ b/src/hoganjs-utils.js +@@ -17,6 +17,13 @@ + function HoganJsUtils(configuration) { + this.config = configuration || {}; + extraTemplates = this.config.templates || {}; ++ ++ var rawTemplates = this.config.rawTemplates || {}; ++ for (var templateName in rawTemplates) { ++ if (rawTemplates.hasOwnProperty(templateName)) { ++ if (!extraTemplates[templateName]) extraTemplates[templateName] = this.compile(rawTemplates[templateName]); ++ } ++ } + } + + HoganJsUtils.prototype.render = function(namespace, view, params) { +diff --git a/test/hogan-cache-tests.js b/test/hogan-cache-tests.js +index 3bb754ac..a34839c0 100644 +--- a/test/hogan-cache-tests.js ++++ b/test/hogan-cache-tests.js +@@ -36,7 +36,7 @@ describe('HoganJsUtils', function() { + assert.equal(null, result); + }); + +- it('should allow templates to be overridden', function() { ++ it('should allow templates to be overridden with compiled templates', function() { + var emptyDiffTemplate = HoganJsUtils.compile('

{{myName}}

'); + + var config = {templates: {'generic-empty-diff': emptyDiffTemplate}}; +@@ -44,5 +44,27 @@ describe('HoganJsUtils', function() { + var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); + assert.equal('

Rodrigo Fernandes

', result); + }); ++ ++ it('should allow templates to be overridden with uncompiled templates', function() { ++ var emptyDiffTemplate = '

{{myName}}

'; ++ ++ var config = {rawTemplates: {'generic-empty-diff': emptyDiffTemplate}}; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

Rodrigo Fernandes

', result); ++ }); ++ ++ it('should allow templates to be overridden giving priority to compiled templates', function() { ++ var emptyDiffTemplate = HoganJsUtils.compile('

{{myName}}

'); ++ var emptyDiffTemplateUncompiled = '

Not used!

'; ++ ++ var config = { ++ templates: {'generic-empty-diff': emptyDiffTemplate}, ++ rawTemplates: {'generic-empty-diff': emptyDiffTemplateUncompiled} ++ }; ++ var hoganUtils = new (require('../src/hoganjs-utils.js').HoganJsUtils)(config); ++ var result = hoganUtils.render('generic', 'empty-diff', {myName: 'Rodrigo Fernandes'}); ++ assert.equal('

Rodrigo Fernandes

', result); ++ }); + }); + }); +``` diff --git a/assets/js/copy_code.js b/assets/js/copy_code.js index 35dbf7e15b9d..cf0e1da57875 100644 --- a/assets/js/copy_code.js +++ b/assets/js/copy_code.js @@ -4,6 +4,7 @@ codeBlocks.forEach(function (codeBlock) { if ( (codeBlock.querySelector("pre:not(.lineno)") || codeBlock.querySelector("code")) && codeBlock.querySelector("code:not(.language-chartjs)") && + codeBlock.querySelector("code:not(.language-diff2html)") && codeBlock.querySelector("code:not(.language-echarts)") && codeBlock.querySelector("code:not(.language-geojson)") && codeBlock.querySelector("code:not(.language-mermaid)") && diff --git a/assets/js/theme.js b/assets/js/theme.js index 8436959ad3cc..034d7cb514b7 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -18,6 +18,11 @@ let setTheme = (theme) => { setMermaidTheme(theme); } + // if diff2html is not defined, do nothing + if (typeof Diff2HtmlUI !== "undefined") { + setDiff2htmlTheme(theme); + } + // if echarts is not defined, do nothing if (typeof echarts !== "undefined") { setEchartsTheme(theme); @@ -131,6 +136,17 @@ let setMermaidTheme = (theme) => { } }; +let setDiff2htmlTheme = (theme) => { + document.querySelectorAll(".diff2html").forEach((elem) => { + // Get the code block content from previous element, since it is the diff code itself as defined in Markdown, but it is hidden + let textData = elem.previousSibling.childNodes[0].innerHTML; + elem.innerHTML = ""; + const configuration = { colorScheme: theme, drawFileList: true, highlight: true, matching: "lines" }; + const diff2htmlUi = new Diff2HtmlUI(elem, textData, configuration); + diff2htmlUi.draw(); + }); +}; + let setEchartsTheme = (theme) => { document.querySelectorAll(".echarts").forEach((elem) => { // Get the code block content from previous element, since it is the echarts code itself as defined in Markdown, but it is hidden