diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a22632..0270853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 0.4.0 (2022-12-17) + +### ✨ Features + + * Add show-invisibles plugins + +Credits + +* [@Bunlong](https://github.com/Bunlong) + ## 0.3.0 (2022-12-14) ### ✨ Features diff --git a/README.md b/README.md index 29187f5..97927c2 100644 --- a/README.md +++ b/README.md @@ -788,11 +788,41 @@ export default function App() { } ``` +### Show Invisibles + +Show hidden characters such as tabs and line breaks. + +```javascript +import { usePrism } from 'next-prism' + +// Import a theme.css +import 'next-prism/themes/tomorrow.css' + +// Import show-invisibles source +import 'next-prism/plugins/show-invisibles/show-invisibles'; +// Import show-invisibles.css +import 'next-prism/plugins/show-invisibles/show-invisibles.css'; + +export default function App() { + const { Code } = usePrism() + + return ( + <> + + {`
+ {Math.random()} +
`} +
+ + ) +} +``` + ## 📜 Changelog -Latest version 0.3.0 (2022-12-14): +Latest version 0.4.0 (2022-12-17): - * Add highlightAll() function + * Add show-invisibles plugins Details changes for each release are documented in the [CHANGELOG.md](https://github.com/Bunlong/next-prism/blob/master/CHANGELOG.md). diff --git a/package.json b/package.json index ec3f31a..45bf73f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next-prism", - "version": "0.3.1", + "version": "0.4.0", "description": "A lightweight, robust, and elegant syntax highlighting component for your next React apps.", "author": "Bunlong ", "license": "MIT", diff --git a/plugins/line-numbers/line-numbers.css b/plugins/line-numbers/line-numbers.css index 8170f64..b67b684 100644 --- a/plugins/line-numbers/line-numbers.css +++ b/plugins/line-numbers/line-numbers.css @@ -1 +1,39 @@ -pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right} \ No newline at end of file +pre[class*="language-"].line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre[class*="language-"].line-numbers > code { + position: relative; + white-space: inherit; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.line-numbers-rows > span { + display: block; + counter-increment: linenumber; +} + +.line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; +} diff --git a/plugins/show-invisibles/show-invisibles.css b/plugins/show-invisibles/show-invisibles.css new file mode 100644 index 0000000..c81928a --- /dev/null +++ b/plugins/show-invisibles/show-invisibles.css @@ -0,0 +1,34 @@ +.token.tab:not(:empty), +.token.cr, +.token.lf, +.token.space { + position: relative; +} + +.token.tab:not(:empty):before, +.token.cr:before, +.token.lf:before, +.token.space:before { + color: #808080; + opacity: 0.6; + position: absolute; +} + +.token.tab:not(:empty):before { + content: '\21E5'; +} + +.token.cr:before { + content: '\240D'; +} + +.token.crlf:before { + content: '\240D\240A'; +} +.token.lf:before { + content: '\240A'; +} + +.token.space:before { + content: '\00B7'; +} diff --git a/plugins/show-invisibles/show-invisibles.js b/plugins/show-invisibles/show-invisibles.js new file mode 100644 index 0000000..e1f97f9 --- /dev/null +++ b/plugins/show-invisibles/show-invisibles.js @@ -0,0 +1,83 @@ +(function () { + + if (typeof Prism === 'undefined') { + return; + } + + + var invisibles = { + 'tab': /\t/, + 'crlf': /\r\n/, + 'lf': /\n/, + 'cr': /\r/, + 'space': / / + }; + + + /** + * Handles the recursive calling of `addInvisibles` for one token. + * + * @param {Object|Array} tokens The grammar or array which contains the token. + * @param {string|number} name The name or index of the token in `tokens`. + */ + function handleToken(tokens, name) { + var value = tokens[name]; + + var type = Prism.util.type(value); + switch (type) { + case 'RegExp': + var inside = {}; + tokens[name] = { + pattern: value, + inside: inside + }; + addInvisibles(inside); + break; + + case 'Array': + for (var i = 0, l = value.length; i < l; i++) { + handleToken(value, i); + } + break; + + default: // 'Object' + // eslint-disable-next-line no-redeclare + var inside = value.inside || (value.inside = {}); + addInvisibles(inside); + break; + } + } + + /** + * Recursively adds patterns to match invisible characters to the given grammar (if not added already). + * + * @param {Object} grammar + */ + function addInvisibles(grammar) { + if (!grammar || grammar['tab']) { + return; + } + + // assign invisibles here to "mark" the grammar in case of self references + for (var name in invisibles) { + if (invisibles.hasOwnProperty(name)) { + grammar[name] = invisibles[name]; + } + } + + // eslint-disable-next-line no-redeclare + for (var name in grammar) { + if (grammar.hasOwnProperty(name) && !invisibles[name]) { + if (name === 'rest') { + addInvisibles(grammar['rest']); + } else { + handleToken(grammar, name); + } + } + } + } + + Prism.hooks.add('before-highlight', function (env) { + addInvisibles(env.grammar); + }); +}()); diff --git a/supports/create-react-app/src/App.js b/supports/create-react-app/src/App.js index 153a680..38b376b 100644 --- a/supports/create-react-app/src/App.js +++ b/supports/create-react-app/src/App.js @@ -3,6 +3,9 @@ import { usePrism } from 'next-prism'; import 'next-prism/themes/tomorrow.css'; +import 'next-prism/plugins/show-invisibles/show-invisibles.css'; +import 'next-prism/plugins/show-invisibles/show-invisibles'; + function App() { const [count, setCount] = useState(0); const { Code, highlightAll } = usePrism();