-
-
Notifications
You must be signed in to change notification settings - Fork 298
How to style specific nested tokens? #204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Just ran into this today, trying to style Simple reproduction here: Sandbox: https://codesandbox.io/s/react-syntax-highlighter-forked-kjnk7?file=/src/index.js:265-559 |
@simmerer I would like to try my hand at doing a PR for this. I've narrowed it down to this part of the react-syntax-highlighter/src/create-element.js Lines 3 to 7 in 8aacf94
For example, if the ["token", "template-string", "token", "interpolation", "token", "interpolation-punctuation", "punctuation"] I can think of two ways to solve this:
Edit: After thinking a bit more about this, I guess the second solution would be the best here, since solution 1 means modifying the |
I will come up with a prototype of the specificity solution above (solution 2). |
Ok so using import React from 'react';
+import { compare } from 'specificity';
export function createStyleObject(classNames, elementStyle = {}, stylesheet) {
+ const sortedStylesheet = Object.entries(stylesheet).sort(([selectorA], [selectorB]) => {
+ return compare(selectorA, selectorB)
+ });
- return classNames.reduce((styleObject, className) => {
- return { ...styleObject, ...stylesheet[className] };
+ return sortedStylesheet.reduce((styleObject, [selector, styles]) => {
+ return { ...styleObject, ...(classNames.includes(selector) && styles) };
}, elementStyle);
} Edit: Or, a different code style, potentially easier to follow: import React from 'react';
+import { compare } from 'specificity';
export function createStyleObject(classNames, elementStyle = {}, stylesheet) {
- return classNames.reduce((styleObject, className) => {
- return { ...styleObject, ...stylesheet[className] };
- }, elementStyle);
+ return Object.entries(stylesheet)
+ .filter(([selector]) => classNames.includes(selector))
+ .sort(([selectorA], [selectorB]) => {
+ return compare(selectorA, selectorB);
+ })
+ .reduce((styleObject, [, styles]) => {
+ return { ...styleObject, ...styles };
+ }, elementStyle);
} @simmerer is it acceptable to add this dependency? I'm guessing probably not optimal... Another way would be to manually count specificity without the library. |
Hmm... I guess this solution is just working by coincidence actually, since ["token", "template-string", "token", "interpolation", "token", "interpolation-punctuation", "punctuation"] So the {
punctuation: {
color: '#ff0000',
},
'interpolation-punctuation': {
color: '#00ff00',
},
} |
Ok, found a zero-dependency alternative, which:
Feedback on this approach? +const classSelectorClassNames = {};
+function classSelectorToClassNames(selector) {
+ if (!selector.includes(".")) return null;
+ if (!classSelectorClassNames[selector]) {
+ classSelectorClassNames[selector] = selector.split(".").filter(Boolean);
+ }
+ return classSelectorClassNames[selector];
+}
+
+// Is array1 a subset of array2
+function isSubset(array1, array2) {
+ if (!array1 || !array2) return false;
+ if (!Array.isArray(array1) || !Array.isArray(array2)) return false;
+ const intersection = array1.filter((element) => array2.includes(element));
+ return intersection.length === array1.length;
+}
export function createStyleObject(classNames, elementStyle = {}, stylesheet) {
- return classNames.reduce((styleObject, className) => {
- return { ...styleObject, ...stylesheet[className] };
- }, elementStyle);
+ const stylesheetStyles = Object.entries(stylesheet).reduce(
+ (newStyleObject, [selector, styles]) => {
+ if (classNames.includes(selector)) {
+ return { ...styles, ...newStyleObject };
+ } else if (isSubset(classSelectorToClassNames(selector), classNames)) {
+ return { ...newStyleObject, ...styles };
+ }
+ return newStyleObject;
+ },
+ {}
+ );
+ return { ...elementStyle, ...stylesheetStyles };
} |
Opened a PR with this approach at #305 - of course open for feedback and changing the approach! |
@adamwathan a solution from #305 has now been merged and is available in If it works for you, maybe this issue can be closed :) |
Is your feature request related to a problem? Please describe.
The built-in styles include nested token styles like this:
https://github.com/conorhastings/react-syntax-highlighter/blob/master/src/styles/prism/ghcolors.js#L163
However as far as I can tell they don't actually seem to work.
Describe the solution you'd like
It would be great if there was some way to target nested tokens like you can when writing a CSS theme for Prism/Highlight.
Describe alternatives you've considered
Tried a bunch of syntaxes to see if anything worked:
The text was updated successfully, but these errors were encountered: