Skip to content

Commit

Permalink
Merge pull request #9476 from keymanapp/feat/developer/keyboard-info-…
Browse files Browse the repository at this point in the history
…markdown

feat(developer): convert markdown description to html 🎺
  • Loading branch information
mcdurdin authored Sep 1, 2023
2 parents 6e8cc16 + fcf2b51 commit 651af2f
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 34 deletions.
2 changes: 1 addition & 1 deletion developer/src/kmc-keyboard-info/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@keymanapp/kmc-package": "*"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/chai": "^4.3.5",
"@types/mocha": "^5.2.7",
"@types/node": "^20.4.1",
"c8": "^7.12.0",
Expand Down
7 changes: 1 addition & 6 deletions developer/src/kmc-keyboard-info/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class KeyboardInfoCompiler {
// description

if(sources.kmpJsonData.info.description?.description) {
keyboard_info.description = markDownToHTML(sources.kmpJsonData.info.description?.description);
keyboard_info.description = sources.kmpJsonData.info.description?.description.trim();
}

// extract the language identifiers from the language metadata arrays for
Expand Down Expand Up @@ -438,10 +438,5 @@ export class KeyboardInfoCompiler {
);
}
}

}

function markDownToHTML(markdown: string): string {
// TODO
return markdown;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"languageName": "Khmer"
}
},
"description": "Khmer Unicode keyboard layout based on the NiDA keyboard layout. Automatically corrects many common keying errors.",
"description": "<p>Khmer Unicode keyboard layout based on the NiDA keyboard layout. Automatically corrects many common keying errors.</p>",
"related": {
"khmer10": {
"deprecates": true
Expand Down
3 changes: 2 additions & 1 deletion developer/src/kmc-package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
},
"dependencies": {
"@keymanapp/common-types": "*",
"jszip": "^3.7.0"
"jszip": "^3.7.0",
"marked": "^7.0.0"
},
"devDependencies": {
"@keymanapp/developer-test-helpers": "*",
Expand Down
36 changes: 22 additions & 14 deletions developer/src/kmc-package/src/compiler/kmp-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { transcodeToCP1252 } from './cp1252.js';
import { MIN_LM_FILEVERSION_KMP_JSON, PackageVersionValidator } from './package-version-validator.js';
import { PackageKeyboardTargetValidator } from './package-keyboard-target-validator.js';
import { PackageMetadataUpdater } from './package-metadata-updater.js';
import { markdownToHTML } from './markdown.js';

const KMP_JSON_FILENAME = 'kmp.json';
const KMP_INF_FILENAME = 'kmp.inf';
Expand Down Expand Up @@ -246,26 +247,33 @@ export class KmpCompiler {

// Helper functions

private kpsInfoToKmpInfo(info: KpsFile.KpsFileInfo): KmpJsonFile.KmpJsonFileInfo {
let ni: KmpJsonFile.KmpJsonFileInfo = {};
private kpsInfoToKmpInfo(kpsInfo: KpsFile.KpsFileInfo): KmpJsonFile.KmpJsonFileInfo {
let kmpInfo: KmpJsonFile.KmpJsonFileInfo = {};

const keys: [(keyof KpsFile.KpsFileInfo), (keyof KmpJsonFile.KmpJsonFileInfo)][] = [
['author','author'],
['copyright','copyright'],
['name','name'],
['version','version'],
['webSite','website'],
['description','description'],
const keys: [(keyof KpsFile.KpsFileInfo), (keyof KmpJsonFile.KmpJsonFileInfo), boolean][] = [
['author','author',false],
['copyright','copyright',false],
['name','name',false],
['version','version',false],
['webSite','website',false],
['description','description',true],
];

for (let [src,dst] of keys) {
if (info[src]) {
ni[dst] = {description: (info[src]._ ?? (typeof info[src] == 'string' ? info[src].toString() : '').trim())};
if(info[src].$ && info[src].$.URL) ni[dst].url = info[src].$.URL.trim();
for (let [src,dst,isMarkdown] of keys) {
if (kpsInfo[src]) {
kmpInfo[dst] = {
description: (kpsInfo[src]._ ?? (typeof kpsInfo[src] == 'string' ? kpsInfo[src].toString() : '')).trim()
};
if(isMarkdown) {
kmpInfo[dst].description = markdownToHTML(kmpInfo[dst].description, false).trim();
}
if(kpsInfo[src].$?.URL) {
kmpInfo[dst].url = kpsInfo[src].$.URL.trim();
}
}
}

return ni;
return kmpInfo;
};

private arrayWrap(a: unknown) {
Expand Down
50 changes: 50 additions & 0 deletions developer/src/kmc-package/src/compiler/markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Markdown transform for our `description` field. Tweaked to disable all inline
* HTML, because we want descriptions to be short and sweet, and don't need any
* of the more complex formatting that inline HTML affords.
*/

//
// Note: using marked 7.0.0.
// https://github.com/markedjs/marked/issues/2926
//
// Version 7.0.1 introduced a TypeScript 5.0+ feature `export type *` which causes:
//
// ../../../node_modules/marked/lib/marked.d.ts:722:5 - error TS1383: Only named exports may use 'export type'.
// 722 export type * from "MarkedOptions";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// https://github.com/markedjs/marked/compare/v7.0.0...v7.0.1#diff-32d87a2bc59f429470ccf7afc8ae8818914d4d45c3f7c5b1767c6a0a240b55c9R449-R451
//
// When we move to TS 5.0, we can upgrade marked.
//
import { Marked } from 'marked';

/*
Markdown rendering: we don't want to use the global object, because this
pollutes the settings for all modules. So we construct our own instance,
so that we can strip all inline HTML; we don't need any
*/

const renderer = {
html(_html:string, _block:boolean) {
// we don't allow inline HTML
return '';
}
}
const markedStripHtml = new Marked({renderer});
const marked = new Marked();

/**
*
* @param markdown
* @param allowHTML
* @returns
*/
export function markdownToHTML(markdown: string, allowHTML: boolean): string {
// <string>: .parse can return a Promise if async=true. We don't pass ths
// option, and this sync usage isn't separated out in the types for
// Marked.prototype.parse, so <string> avoids tsc complaints here.
const html = <string> (allowHTML ? marked : markedStripHtml).parse(markdown.trim());
return html;
}
2 changes: 1 addition & 1 deletion developer/src/kmc-package/test/fixtures/kmp_2.0/kmp.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"url": "https://keyman.com/keyboards/khmer_angkor"
},
"description": {
"description": "# Khmer Angkor\r\n\r\nKhmer Unicode keyboard layout based on the NiDA keyboard layout. Automatically corrects many common keying errors, including:\r\n\r\n* Using wrong vowel combination\r\n* Typing clusters out of order\r\n* Typing wrong mark for consonant shifters\r\n* And more!"
"description": "<h1>Khmer Angkor</h1>\n<p>Khmer Unicode keyboard layout based on the NiDA keyboard layout. Automatically corrects many common keying errors, including:</p>\n<ul>\n<li>Using wrong vowel combination</li>\n<li>Typing clusters out of order</li>\n<li>Typing wrong mark for consonant shifters</li>\n<li>And more!</li>\n</ul>"
}
},
"files": [
Expand Down
20 changes: 20 additions & 0 deletions developer/src/kmc-package/test/test-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { assert } from 'chai';
import 'mocha';
import { markdownToHTML } from '../src/compiler/markdown.js';

describe('markdownToHTML', function () {
it('should convert markdown into HTML', function() {
const html = markdownToHTML('# heading\n\n**bold** and _beautiful_', true);
assert.equal(html, `<h1>heading</h1>\n<p><strong>bold</strong> and <em>beautiful</em></p>\n`);
});

it('should strip inline html if asked to do so', function() {
const html = markdownToHTML(`# heading\n\n<script>alert('gotcha')</script>\n\n**bold** and _beautiful_`, false);
assert.equal(html, `<h1>heading</h1>\n<p><strong>bold</strong> and <em>beautiful</em></p>\n`);
});

it('should keep inline html if asked to do so', function() {
const html = markdownToHTML(`# heading\n\n<script>alert('gotcha')</script>\n\n**bold** and _beautiful_`, true);
assert.equal(html, `<h1>heading</h1>\n<script>alert('gotcha')</script>\n\n<p><strong>bold</strong> and <em>beautiful</em></p>\n`);
});
});
36 changes: 26 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 651af2f

Please sign in to comment.