Skip to content

Commit

Permalink
Merge pull request #378 from a-ignatov-parc/fix-prefix-css
Browse files Browse the repository at this point in the history
Fix CSS prefixer
  • Loading branch information
rohit-gohri authored Sep 17, 2024
2 parents 5d0aaf3 + 0415860 commit 4da9e93
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 72 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-owls-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'docusaurus-theme-redoc': patch
---

Fixes incorrect CSS prefixing that breaks layout on mobile devices and resolves reintroduced issues with incorrect background color for code samples
3 changes: 3 additions & 0 deletions packages/docusaurus-theme-redoc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"clsx": "^1.2.1",
"lodash": "^4.17.21",
"mobx": "^6.12.4",
"postcss": "^8.4.45",
"postcss-prefix-selector": "^1.16.1",
"redoc": "2.1.5",
"styled-components": "^6.1.11"
},
Expand All @@ -45,6 +47,7 @@
"@docusaurus/theme-common": "^3.4.0",
"@docusaurus/types": "^3.4.0",
"@types/lodash": "^4.14.200",
"@types/postcss-prefix-selector": "^1",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-is": "^18.3.0",
Expand Down
87 changes: 25 additions & 62 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/ServerStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,27 @@ import { AppStore, Redoc, RedocRawOptions } from 'redoc';
// eslint-disable-next-line import/no-extraneous-dependencies
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
import postcss from 'postcss';
import prefixer from 'postcss-prefix-selector';

/**
* @see https://stackoverflow.com/a/54077142
*/
const prefixCssSelectors = function (rules: string, className: string) {
const classLen = className.length;
let char, nextChar, isAt, isIn;

// makes sure the className will not concatenate the selector
className += ' ';

// removes comments
rules = rules.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, '');

// makes sure nextChar will not target a space
rules = rules.replace(/}(\s*)@/g, '}@');
rules = rules.replace(/}(\s*)}/g, '}}');

for (let i = 0; i < rules.length - 2; i++) {
char = rules[i];
nextChar = rules[i + 1];
const prefixCssSelectors = function (css: string, className: string): string {
const processor = postcss().use(
prefixer({
prefix: className,
}),
);

if (char === '@' && nextChar !== 'f') isAt = true;
if (!isAt && char === '{') isIn = true;
if (isIn && char === '}') isIn = false;
return processor.process(css).css;
};

if (
!isIn &&
nextChar !== '@' &&
nextChar !== '}' &&
(char === '}' || char === ',' || ((char === '{' || char === ';') && isAt))
) {
rules = rules.slice(0, i + 1) + className + rules.slice(i + 1);
i += classLen;
isAt = false;
}
}
const renderCss = function (store: AppStore): string {
const styleSheet = new ServerStyleSheet();

// prefix the first select if it is not `@media` and if it is not yet prefixed
if (rules.indexOf(className) !== 0 && rules.indexOf('@') !== 0)
rules = className + rules;
renderToString(
styleSheet.collectStyles(React.createElement(Redoc, { store })),
);

return rules;
return String(styleSheet.instance);
};

const LIGHT_MODE_PREFIX = "html:not([data-theme='dark'])";
Expand All @@ -63,41 +41,26 @@ export function ServerStyles({
darkThemeOptions: RedocRawOptions;
}) {
const fullUrl = useBaseUrl(specProps.url, { absolute: true });
const css = {
light: '',
dark: '',
};
const lightSheet = new ServerStyleSheet();
const lightStore = new AppStore(specProps.spec, fullUrl, lightThemeOptions);
renderToString(
lightSheet.collectStyles(React.createElement(Redoc, { store: lightStore })),
);
const lightStyleTag = lightSheet.getStyleTags();
let lightCss = lightStyleTag.slice(lightStyleTag.indexOf('>') + 1);
lightCss = lightCss.slice(0, lightCss.indexOf('<style'));
css.light = prefixCssSelectors(lightCss, LIGHT_MODE_PREFIX);

const darkSheet = new ServerStyleSheet();
const darkStore = new AppStore(specProps.spec, fullUrl, darkThemeOptions);
renderToString(
darkSheet.collectStyles(React.createElement(Redoc, { store: darkStore })),
const lightCss = prefixCssSelectors(
renderCss(new AppStore(specProps.spec, fullUrl, lightThemeOptions)),
LIGHT_MODE_PREFIX,
);
const darkStyleTag = darkSheet.getStyleTags();
let darkCss = darkStyleTag.slice(darkStyleTag.indexOf('>') + 1);
darkCss = darkCss.slice(0, darkCss.indexOf('<style'));
css.dark = prefixCssSelectors(darkCss, DARK_MODE_PREFIX).slice(
DARK_MODE_PREFIX.length + 1,

const darkCss = prefixCssSelectors(
renderCss(new AppStore(specProps.spec, fullUrl, darkThemeOptions)),
DARK_MODE_PREFIX,
);

return (
<div className="redocusaurus-styles">
<style
key="light-mode-styles"
dangerouslySetInnerHTML={{ __html: css.light }}
dangerouslySetInnerHTML={{ __html: lightCss }}
/>
<style
key="dark-mode-styles"
dangerouslySetInnerHTML={{ __html: css.dark }}
dangerouslySetInnerHTML={{ __html: darkCss }}
/>
</div>
);
Expand Down
22 changes: 12 additions & 10 deletions packages/docusaurus-theme-redoc/src/theme/Redoc/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,16 @@ html[data-theme='dark']
}

/* Fixes https://github.com/rohit-gohri/redocusaurus/issues/306 */
html[data-theme='dark']
.redocusaurus
html[data-theme='dark']
.redocusaurus
div[id^='tag']
button:has(span):has(.operation-type) {
background-color: var(--ifm-color-gray-800);
}

html[data-theme='dark']
.redocusaurus
div[id^='tag']
html[data-theme='dark']
.redocusaurus
div[id^='tag']
button + div {
background-color: var(--ifm-color-emphasis-0);
}
Expand All @@ -146,20 +146,22 @@ html[data-theme='dark']
margin-bottom: 10px;
}

/*
/*
* Code Samples
* @see https://github.com/rohit-gohri/redocusaurus/issues/217
*/
html:not([data-theme='dark'])
.redocusaurus
div[id^='react-tabs']
> div:nth-child(1)
> pre:nth-child(2) {
[role='tabpanel']
pre {
background-color: transparent;
}

/** https://github.com/rohit-gohri/redocusaurus/issues/45 */
html:not([data-theme='dark']) .redocusaurus div[id^='react-tabs'] code {
html:not([data-theme='dark'])
.redocusaurus
[role='tabpanel']
code {
color: var(--ifm-color-emphasis-0);
}

Expand Down
32 changes: 32 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3725,6 +3725,15 @@ __metadata:
languageName: node
linkType: hard

"@types/postcss-prefix-selector@npm:^1":
version: 1.16.3
resolution: "@types/postcss-prefix-selector@npm:1.16.3"
dependencies:
postcss: "npm:^8.4.27"
checksum: c0ece88bf7f5adfdcbf1f44436ce3e78d5fe0431fd84dce4040e53c03af2ca71fd3f1a36d127e1402c085c5507d5403fe461577670252c311556c102d7dc948d
languageName: node
linkType: hard

"@types/prismjs@npm:^1.26.0":
version: 1.26.2
resolution: "@types/prismjs@npm:1.26.2"
Expand Down Expand Up @@ -6357,6 +6366,7 @@ __metadata:
"@docusaurus/types": "npm:^3.4.0"
"@redocly/openapi-core": "npm:1.16.0"
"@types/lodash": "npm:^4.14.200"
"@types/postcss-prefix-selector": "npm:^1"
"@types/react": "npm:^18.3.3"
"@types/react-dom": "npm:^18.3.0"
"@types/react-is": "npm:^18.3.0"
Expand All @@ -6368,6 +6378,8 @@ __metadata:
lodash: "npm:^4.17.21"
mobx: "npm:^6.12.4"
nodemon: "npm:^3.1.0"
postcss: "npm:^8.4.45"
postcss-prefix-selector: "npm:^1.16.1"
react: "npm:^18.3.1"
react-dom: "npm:^18.3.1"
react-is: "npm:^18.3.1"
Expand Down Expand Up @@ -12402,6 +12414,15 @@ __metadata:
languageName: node
linkType: hard

"postcss-prefix-selector@npm:^1.16.1":
version: 1.16.1
resolution: "postcss-prefix-selector@npm:1.16.1"
peerDependencies:
postcss: ">4 <9"
checksum: e6a138f2c2f4be38013e778d0242f7fced1468759b508b3f85349ec1a5cd0bd6e7194998749508edb7a987fff9d4f3ee89b7d4f34e5df34dbf65130bf3bc680c
languageName: node
linkType: hard

"postcss-reduce-idents@npm:^6.0.3":
version: 6.0.3
resolution: "postcss-reduce-idents@npm:6.0.3"
Expand Down Expand Up @@ -12507,6 +12528,17 @@ __metadata:
languageName: node
linkType: hard

"postcss@npm:^8.4.27, postcss@npm:^8.4.45":
version: 8.4.45
resolution: "postcss@npm:8.4.45"
dependencies:
nanoid: "npm:^3.3.7"
picocolors: "npm:^1.0.1"
source-map-js: "npm:^1.2.0"
checksum: 7eaf7346d04929ee979548ece5e34d253eae6f175346e298b2c4621ad6f4ee00adfe7abe72688640e910c0361ae50537c5dda3e35fd1066491282c342b3ee5c8
languageName: node
linkType: hard

"preferred-pm@npm:^3.0.0":
version: 3.1.2
resolution: "preferred-pm@npm:3.1.2"
Expand Down

0 comments on commit 4da9e93

Please sign in to comment.