import { Component, ViewChild, Input, Renderer } from '@angular/core'; import * as hljs from 'highlight.js'; import 'highlight.js/lib/languages/python.js'; import 'highlight.js/lib/languages/sql.js'; import 'highlight.js/lib/languages/javascript.js'; import 'highlight.js/lib/languages/yaml.js'; import 'highlight.js/lib/languages/powershell.js'; import 'highlight.js/styles/dracula.css'; import './code-highlight.scss'; /** * Component for highlighting code syntax * Inspired by: https://github.com/Teradata/covalent */ @Component({ selector: 'swui-code-highlight', template: `
`, host: { class: 'swui-code-highlight' } }) export class CodeHighlightComponent { @Input() language = 'javascript'; @Input() json; element: any; renderer: Renderer; @ViewChild('highlight') content; constructor(renderer: Renderer) { this.renderer = renderer; } ngOnChanges(change) { if(change.json && change.json.currentValue) { const value = change.json.currentValue; const str = JSON.stringify(value, null, ' '); this.prettify(str); } } ngAfterViewInit() { this.element = this.content.nativeElement; const code = this.element.innerHTML; this.renderer.detachView([].slice.call(this.element.childNodes)); this.prettify(code); } prettify(contents) { // ensure load if(!this.element) return; let lines = contents.split('\n'); // Remove empty lines lines = lines.filter(function(line) { return line.trim().length > 0; }); // don't mess w/ empties if(!lines.length) return; // Make it so each line starts at 0 whitespace let firstLineWhitespace = lines[0].match(/^\s*/)[0]; let startingWhitespaceRegex = new RegExp('^' + firstLineWhitespace); lines = lines.map(function(line) { return line .replace('=""', '') // remove empty values .replace(startingWhitespaceRegex, '') .replace(/\s+$/, ''); }); this.renderer.setElementClass(this.element, 'highlight', true); let codeToParse = lines.join('\n') .replace(/\{ \{/gi, '{{').replace(/\} \}/gi, '}}') // replace with < and > to render HTML in angular 2 .replace(/</gi, '<').replace(/>/gi, '>'); if (this.language === 'html') { // need to use CDATA for HTML this.renderer.createText(this.element, codeToParse, undefined); hljs.highlightBlock(this.element); } else { let highlightedCode = hljs.highlight(this.language, codeToParse, true); highlightedCode.value = highlightedCode.value .replace(/=""<\/span>/gi, '') .replace('', '') .replace('', ''); this.element.innerHTML = highlightedCode.value; } } }